WIP add \ when needed

Change-Id: I94887f6ccb45072180a318776ae96aead8658a18
This commit is contained in:
physikerwelt 2024-11-19 00:58:07 +01:00
parent 44243ad466
commit 62506236ec
No known key found for this signature in database
GPG key ID: FCC793EFFA5FB13C
6 changed files with 72 additions and 94 deletions

View file

@ -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;
}

View file

@ -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 ) {

View file

@ -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;
}

View file

@ -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 );

View file

@ -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];
}

View file

@ -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();