From 62506236ec39d99a85a0dfe9a4dba5f8ddccca88 Mon Sep 17 00:00:00 2001 From: physikerwelt Date: Tue, 19 Nov 2024 00:58:07 +0100 Subject: [PATCH] WIP add \ when needed Change-Id: I94887f6ccb45072180a318776ae96aead8658a18 --- src/WikiTexVC/MMLmappings/AMSMappings.php | 5 +- src/WikiTexVC/MMLmappings/BaseMappings.php | 41 +++++++------- src/WikiTexVC/MMLmappings/BaseMethods.php | 16 ------ src/WikiTexVC/MMLmappings/BaseParsing.php | 62 +++++++++++----------- src/WikiTexVC/MMLmappings/Util/MMLutil.php | 40 ++++++-------- src/WikiTexVC/Nodes/Literal.php | 2 +- 6 files changed, 72 insertions(+), 94 deletions(-) diff --git a/src/WikiTexVC/MMLmappings/AMSMappings.php b/src/WikiTexVC/MMLmappings/AMSMappings.php index bfd862a46..447c4d8a9 100644 --- a/src/WikiTexVC/MMLmappings/AMSMappings.php +++ b/src/WikiTexVC/MMLmappings/AMSMappings.php @@ -329,7 +329,8 @@ class AMSMappings { "Bmatrix" => [ 'array', null, '\\{', '\\}', 'c' ], "vmatrix" => [ 'array', null, '\\vert', '\\vert', 'c' ], "Vmatrix" => [ 'array', null, '\\Vert', '\\Vert', 'c' ], - "cases" => [ 'array', null, '\\{', '.', 'll', null, '.2em', 'T' ] + 'cases' => [ 'matrix', '{', '', 'left left', null, '.1em', null, + true ], ]; private const AMSSYMBOLDELIMITERS = [ 'ulcorner' => '\u231C', @@ -394,7 +395,7 @@ class AMSMappings { } public static function getMacroByKey( $key ) { - $ret = MMLutil::getMappingByKey( $key, self::AMSMACROS ); + $ret = MMLutil::getMappingByKey( $key, self::AMSMACROS, false, true ); if ( $ret != null ) { return $ret; } diff --git a/src/WikiTexVC/MMLmappings/BaseMappings.php b/src/WikiTexVC/MMLmappings/BaseMappings.php index 60213284f..78758c61c 100644 --- a/src/WikiTexVC/MMLmappings/BaseMappings.php +++ b/src/WikiTexVC/MMLmappings/BaseMappings.php @@ -68,8 +68,7 @@ class BaseMappings { "varsigma" => '\u03C2', "varstigma" => "\u03DB", "varphi" => '\u03C6', - // special case with \\ to distinguish from literal: - "\\S" => [ '\u00A7', [ "mathvariant" => Variants::NORMAL ] ], + "S" => [ '\u00A7', [ "mathvariant" => Variants::NORMAL ] ], "aleph" => [ '\u2135', [ "mathvariant" => Variants::NORMAL ] ], "hbar" => [ '\u210F', [ Tag::ALTERNATE => "1" ] ], // actually: "variantForm" => "True" "imath" => '\u0131', @@ -102,7 +101,6 @@ class BaseMappings { ]; private const MATHCHAR0MO = [ - "-" => '\u2212', // added this additionally for running all tc "surd" => '\u221A', "coprod" => [ '\u2210', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], @@ -477,11 +475,11 @@ class BaseMappings { "lower" => 'raiseLower', "moveleft" => 'MoveLeftRight', "moveright" => 'MoveLeftRight', - '\\,' => [ 'spacer', MathSpace::THINMATHSPACE ], - "\\'" => [ 'spacer', MathSpace::MEDIUMMATHSPACE ], - '\\>' => [ 'spacer', MathSpace::MEDIUMMATHSPACE ], - '\\;' => [ 'spacer', MathSpace::THICKMATHSPACE ], - '\\!' => [ 'spacer', MathSpace::NEGATIVETHINMATHSPACE ], + ',' => [ 'spacer', MathSpace::THINMATHSPACE ], + "'" => [ 'spacer', MathSpace::MEDIUMMATHSPACE ], + '>' => [ 'spacer', MathSpace::MEDIUMMATHSPACE ], + ';' => [ 'spacer', MathSpace::THICKMATHSPACE ], + '!' => [ 'spacer', MathSpace::NEGATIVETHINMATHSPACE ], "enspace" => [ 'spacer', 0.5 ], "quad" => [ 'spacer', 1 ], "qquad" => [ 'spacer', 2 ], @@ -557,7 +555,7 @@ class BaseMappings { "(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.5em', 'D' ], "displaylines" => [ 'matrix', null, null, 'center', null, '.5em', 'D' ], "cr" => 'Cr', - "\\" => 'crLaTeX', + "" => 'crLaTeX', "newline" => [ 'crLaTeX', true ], "hline" => [ 'hline', 'solid' ], "hdashline" => [ 'hline', 'dashed' ], @@ -731,11 +729,11 @@ class BaseMappings { // This is from cancelConfiguration.js private const CANCEL = [ - "cancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE ], - "bcancel" => [ 'cancel', Notation::DOWNDIAGONALSTRIKE ], - "xcancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE . ' ' . + "\\cancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE ], + "\\bcancel" => [ 'cancel', Notation::DOWNDIAGONALSTRIKE ], + "\\xcancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE . ' ' . Notation::DOWNDIAGONALSTRIKE ], - "cancelto" => [ 'cancelTo', Notation::UPDIAGONALSTRIKE . " " . Notation::UPDIAGONALARROW . + "\\cancelto" => [ 'cancelTo', Notation::UPDIAGONALSTRIKE . " " . Notation::UPDIAGONALARROW . " " . Notation::NORTHEASTARROW ] ]; // They are currently from mhchemConfiguration.js @@ -777,7 +775,7 @@ class BaseMappings { "oiiint" => [ 'oint', '\u2230', [ "texClass" => TexClass::OP ] ], "ointctrclockwise" => [ 'oint', '\u2233', [ "texClass" => TexClass::OP ] ], "varointclockwise" => [ 'oint', '\u2232', [ "texClass" => TexClass::OP ] ], - "\\P" => [ 'oint', '\u00B6', [ "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" ], @@ -828,15 +826,18 @@ class BaseMappings { } public static function getOperatorByKey( $key ) { - return MMLutil::getMappingByKey( $key, self::MATHCHAR0MO, true ); + 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 ); + return MMLutil::getMappingByKey( $key, self::MATHCHAR0MI, true, true ); } public static function getMacroByKey( $key ) { - return MMLutil::getMappingByKeySimple( $key, self::MACROS ); + return MMLutil::getMappingByKeySimple( $key, self::MACROS, true ); } public static function getMTenvByKey( $key ) { @@ -857,15 +858,15 @@ class BaseMappings { } public static function getCharacterByKey( $key ) { - return MMLutil::getMappingByKeySimple( $key, self::MATCHAR7 ); + return MMLutil::getMappingByKeySimple( $key, self::MATCHAR7, true ); } public static function getCustomByKey( $key ) { - return MMLutil::getMappingByKeySimple( $key, self::CUSTOM ); + return MMLutil::getMappingByKeySimple( $key, self::CUSTOM, true ); } public static function getMhChemByKey( $key ) { - return MMLutil::getMappingByKeySimple( $key, self::MHCHEM ); + return MMLutil::getMappingByKeySimple( $key, self::MHCHEM, true ); } public static function getColorByKey( $key ) { diff --git a/src/WikiTexVC/MMLmappings/BaseMethods.php b/src/WikiTexVC/MMLmappings/BaseMethods.php index 0eafb6ecb..3cf876a44 100644 --- a/src/WikiTexVC/MMLmappings/BaseMethods.php +++ b/src/WikiTexVC/MMLmappings/BaseMethods.php @@ -28,9 +28,6 @@ class BaseMethods { // just discard these elements, sometimes empty TexArray return null; } - if ( $prepareInput ) { - $input = MMLutil::inputPreparation( $input ); - } // Checking for a named parsing function $resFct = BaseMappings::getMacroByKey( $input ); @@ -76,9 +73,6 @@ class BaseMethods { public function checkAndParseOperator( $input, $node, $passedArgs, $operatorContent, $state, $prepareInput = true ) { - if ( $prepareInput ) { - $input = MMLutil::inputPreparation( $input ); - } $resOperator = BaseMappings::getOperatorByKey( $input ); if ( $resOperator == null ) { @@ -158,9 +152,6 @@ class BaseMethods { } public function checkAndParseIdentifier( $input, $node, $passedArgs, $operatorContent, $prepareInput = true ) { - if ( $prepareInput ) { - $input = MMLutil::inputPreparation( $input ); - } $resIdentifier = BaseMappings::getIdentifierByKey( $input ); if ( $resIdentifier == null ) { $resIdentifier = AMSMappings::getIdentifierByKey( $input ); @@ -206,7 +197,6 @@ class BaseMethods { $resDelimiter = BaseMappings::getDelimiterByKey( trim( $input ) ); if ( $resDelimiter == null ) { - $input = MMLutil::inputPreparation( $input ); $resDelimiter = AMSMappings::getSymbolDelimiterByKey( $input ); if ( $resDelimiter == null ) { $resDelimiter = AMSMappings::getMathDelimiterByKey( $input ); @@ -228,9 +218,6 @@ class BaseMethods { } public function checkAndParseMathCharacter( $input, $node, $passedArgs, $operatorContent, $prepareInput = true ) { - if ( $prepareInput ) { - $input = MMLutil::inputPreparation( $input ); - } $resChar = BaseMappings::getCharacterByKey( $input ); if ( $resChar == null ) { return null; @@ -250,9 +237,6 @@ class BaseMethods { return null; } - if ( $prepareInput ) { - $input = MMLutil::inputPreparation( $input ); - } if ( !( $input === 'color' || $input === 'pagecolor' ) ) { return null; } diff --git a/src/WikiTexVC/MMLmappings/BaseParsing.php b/src/WikiTexVC/MMLmappings/BaseParsing.php index 434a215e0..2a97f54d6 100644 --- a/src/WikiTexVC/MMLmappings/BaseParsing.php +++ b/src/WikiTexVC/MMLmappings/BaseParsing.php @@ -372,9 +372,9 @@ class BaseParsing { if ( !$node instanceof Fun1 ) { return null; } - if ( $name == "rlap" ) { + if ( trim( $name ) === "\\rlap" ) { $args = [ "width" => "0" ]; - } elseif ( $name == "llap" ) { + } elseif ( trim( $name ) === "\\llap" ) { $args = [ "width" => "0", "lspace" => "-1width" ]; } else { return null; @@ -386,13 +386,13 @@ class BaseParsing { public static function macro( $node, $passedArgs, $operatorContent, $name, $macro, $argcount = null, $def = null ) { // Parse the Macro - switch ( $name ) { - case "mod": + switch ( trim( $name ) ) { + case "\\mod": $mmlRow = new MMLmrow(); $mo = new MMLmo( "", [ "lspace" => "2.5pt", "rspace" => "2.5pt" ] ); $inner = $node->getArg() instanceof TexNode ? $node->getArg()->renderMML() : ""; return $mmlRow->encapsulateRaw( $mo->encapsulate( "mod" ) . $inner ); - case "pmod": + case "\\pmod": // tbd indicate in mapping that this is composed within php $mmlRow = new MMLmrow(); $mspace = new MMLmspace( "", [ "width" => "0.444em" ] ); @@ -404,11 +404,11 @@ class BaseParsing { return $mmlRow->encapsulateRaw( $mspace->encapsulate() . $mo->encapsulate( "(" ) . $mi->encapsulate( "mod" ) . $mspace2->encapsulate() . $inner . $mo->encapsulate( ")" ) ); - case "varlimsup": - case "varliminf": + case "\\varlimsup": + case "\\varliminf": // hardcoded macro in php (there is also a dynamic mapping which is not completely resolved atm) $mmlRow = new MMLmrow( TexClass::OP ); - if ( $name === "varlimsup" ) { + if ( trim( $name ) === "\\varlimsup" ) { $movu = new MMLmover(); } else { @@ -419,7 +419,7 @@ class BaseParsing { return $mmlRow->encapsulateRaw( $movu->encapsulateRaw( $mmlMi->encapsulateRaw( "lim" ) . $mo->encapsulateRaw( "―" ) ) ); - case "varinjlim": + case "\\varinjlim": $mmlRow = new MMLmrow( TexClass::OP ); $mmlMunder = new MMLmunder(); $mi = new MMLmi(); @@ -428,7 +428,7 @@ class BaseParsing { $mi->encapsulateRaw( "lim" ) . $mo->encapsulateRaw( "→" ) ) ); - case "varprojlim": + case "\\varprojlim": $mmlRow = new MMLmrow( TexClass::OP ); $mmlMunder = new MMLmunder(); $mi = new MMLmi(); @@ -437,7 +437,7 @@ class BaseParsing { $mi->encapsulate( "lim" ) . $mo->encapsulateRaw( "←" ) ) ); - case "stackrel": + 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 ); @@ -455,7 +455,7 @@ class BaseParsing { ); } return $mmlRow->encapsulateRaw( $mmlRowInner->encapsulateRaw( $inner ) ); - case "bmod": + case "\\bmod": $mo = new MMLmo( "", [ "lspace" => Sizes::THICKMATHSPACE, "rspace" => Sizes::THICKMATHSPACE ] ); $mmlRow = new MMLmrow( TexClass::ORD ); $mspace = new MMLmspace( "", [ "width" => "0.167em" ] ); @@ -463,31 +463,31 @@ class BaseParsing { $mmlRow->encapsulateRaw( $node->getArg()->renderMML() ) : ""; return $mmlRow->encapsulateRaw( $mo->encapsulate( "mod" ) . $inner . $mmlRow->encapsulateRaw( $mspace->getEmpty() ) ); - case "implies": + 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": + 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": + case "\\tripledash": // Using emdash for rendering here. $mo = new MMLmo(); return $mo->encapsulateRaw( "—" ); - case "longrightleftharpoons": - case "longLeftrightharpoons": - case "longRightleftharpoons": + 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": + 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 ); @@ -573,16 +573,14 @@ class BaseParsing { $mmlMoOpen = $bm->checkAndParseDelimiter( $open, $node, [], [], true, TexClass::OPEN ); if ( $mmlMoOpen == null ) { - $open = MMLutil::inputPreparation( $open ); $mmlMoOpen = new MMLmo( TexClass::OPEN, [] ); - $mmlMoOpen = $mmlMoOpen->encapsulateRaw( $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 ) { - $close = MMLutil::inputPreparation( $close ); $mmlMoClose = new MMLmo( TexClass::CLOSE, $closeAtts ); $mmlMoClose = $mmlMoClose->encapsulateRaw( $close ); } @@ -612,9 +610,9 @@ class BaseParsing { $attributes = []; $start = ""; $tail = ""; - if ( $name === "atop" ) { + if ( trim( $name ) === "\\atop" ) { $attributes = [ "linethickness" => "0" ]; - } elseif ( $name == "choose" ) { + } elseif ( trim( $name ) == "\\choose" ) { $mrowAll = new MMLmrow( TexClass::ORD ); $mrowOpen = new MMLmrow( TexClass::OPEN ); $mrowClose = new MMLmrow( TexClass::CLOSE ); @@ -649,7 +647,7 @@ class BaseParsing { // This is a custom mapping not in js. $mmlText = new MMLmtext( "", $attributes ); $mrow = new MMLmrow(); - switch ( $name ) { + switch ( trim( $name ) ) { case "oint": $mStyle = new MMLmstyle( "", [ "displaystyle" => "true" ] ); $mo = new MMLmo(); @@ -723,11 +721,11 @@ class BaseParsing { return null; } - if ( $name == "raise" ) { + if ( trim( $name ) === "\\raise" ) { $args = [ "height" => MMLutil::addPreOperator( $em, "+" ), "depth" => MMLutil::addPreOperator( $em, "-" ), "voffset" => MMLutil::addPreOperator( $em, "+" ) ]; - } elseif ( $name == "lower" ) { + } elseif ( trim( $name ) === "\\lower" ) { $args = [ "height" => MMLutil::addPreOperator( $em, "-" ), "depth" => MMLutil::addPreOperator( $em, "+" ), "voffset" => MMLutil::addPreOperator( $em, "-" ) ]; @@ -883,11 +881,11 @@ class BaseParsing { break; } - if ( in_array( $name, [ "bigl", "Bigl", "biggl", "Biggl" ] ) ) { + if ( in_array( $name, [ "\\bigl", "\\Bigl", "\\biggl", "\\Biggl" ] ) ) { $passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::OPEN ] ); } - if ( in_array( $name, [ "bigr", "Bigr", "biggr", "Biggr" ] ) ) { + if ( in_array( $name, [ "\\bigr", "\\Bigr", "\\biggr", "\\Biggr" ] ) ) { $passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::CLOSE ] ); } @@ -896,7 +894,7 @@ class BaseParsing { return $ret; } - $argPrep = MMLutil::inputPreparation( $node->getArg() ); + $argPrep = $node->getArg(); return $mrowOuter->encapsulateRaw( $mrow->encapsulateRaw( $mo->encapsulateRaw( $argPrep ) ) ); } @@ -913,7 +911,7 @@ class BaseParsing { $applyFct = self::getApplyFct( $operatorContent ); if ( $node instanceof Literal ) { $mi = new MMLmi(); - return $mi->encapsulateRaw( $name ) . $applyFct; + return $mi->encapsulateRaw( ltrim( $name, '\\' ) ) . $applyFct; } $mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics $msub = new MMLmsub(); @@ -1123,7 +1121,7 @@ class BaseParsing { $mo = new MMLmo(); $mmlMrow = new MMLmrow(); if ( $operatorContent != null && array_key_exists( "foundOC", $operatorContent ) ) { - $op = MMLutil::inputPreparation( $operatorContent["foundOC"] ); + $op = $operatorContent["foundOC"]; $macro = BaseMappings::getNullaryMacro( $op ); if ( !$macro ) { $macro = BaseMappings::getIdentifierByKey( $op ); diff --git a/src/WikiTexVC/MMLmappings/Util/MMLutil.php b/src/WikiTexVC/MMLmappings/Util/MMLutil.php index b9ed2776d..8c6528308 100644 --- a/src/WikiTexVC/MMLmappings/Util/MMLutil.php +++ b/src/WikiTexVC/MMLmappings/Util/MMLutil.php @@ -153,27 +153,6 @@ class MMLutil { return ( $matches[1] == "-" ? "-" : "" ) . $ret; } - /** - * Some common steps of processing an input string before passing it as a key to the mappings. - * @param string $input string to be processed - * @return string prepared input string - */ - public static function inputPreparation( $input ): string { - if ( $input === null ) { - return ""; - } - $input = trim( $input ); - if ( str_starts_with( $input, "\\" ) && strlen( $input ) >= 2 ) { - $input = substr( $input, 1 ); - // These are edge cases where input can be a Literal OR an Operator - $edgeCases = [ "S", "P", ";", ",", "!", "'", ">", "|" ]; - if ( in_array( $input, $edgeCases, true ) ) { - $input = "\\" . $input; - } - } - return $input; - } - public static function createEntity( $code ): ?string { return IntlChar::chr( intval( $code, 16 ) ); } @@ -184,9 +163,20 @@ class MMLutil { * @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 ) { + 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 ) ) { @@ -206,7 +196,11 @@ class MMLutil { * @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 ) { + 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]; } diff --git a/src/WikiTexVC/Nodes/Literal.php b/src/WikiTexVC/Nodes/Literal.php index 6bfa796cb..48fc067d4 100644 --- a/src/WikiTexVC/Nodes/Literal.php +++ b/src/WikiTexVC/Nodes/Literal.php @@ -88,7 +88,7 @@ class Literal extends TexNode { return $mi->encapsulateRaw( $operatorContent["foundOC"] ); } - $inputP = MMLutil::inputPreparation( $input ); + $inputP = $input; // Sieve for Operators $bm = new BaseMethods();