Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
AMSMappings
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
9 / 9
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAll
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getInstance
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getOperatorByKey
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getIdentifierByKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSymbolDelimiterByKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMathDelimiterByKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMacroByKey
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getEnvironmentByKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings;
3
4use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths\MathSpace;
5use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Align;
6use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\TexClass;
7use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Variants;
8use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil;
9
10/**
11 * Based on AMSMappings.js in MML3
12 * Only importing infix atm
13 * Singleton
14 *
15 */
16class AMSMappings {
17
18    /** @var self|null */
19    private static $instance = null;
20    private const AMSMACROS = [
21        "mathring" => [ 'accent', '02DA' ],
22        "nobreakspace" => 'Tilde',
23        "negmedspace" => [ 'spacer', MathSpace::NEGATIVEMEDIUMMATHSPACE ],
24        "negthickspace" => [ 'spacer', MathSpace::NEGATIVETHICKMATHSPACE ],
25        "idotsint" => [ 'MultiIntegral', '\\int\\cdots\\int' ],
26        "dddot" => [ 'accent', '20DB' ],
27        "ddddot" => [ 'accent', '20DC' ],
28        "sideset" => 'SideSet',
29        "boxed" => [ 'macro', '\\fbox{$\\displaystyle{#1}$}', 1 ],
30        "tag" => 'HandleTag',
31        "notag" => 'HandleNoTag',
32        "eqref" => [ 'HandleRef', true ],
33        "substack" => [ 'macro', '\\begin{subarray}{c}#1\\end{subarray}', 1 ],
34        "injlim" => [ 'namedOp', 'inj lim' ],
35        "projlim" => [ 'namedOp', 'proj lim' ],
36        "varliminf" => [ 'macro', '\\mathop{\\underline{\\mmlToken{mi}{lim}}}' ],
37        "varlimsup" => [ 'macro', '\\mathop{\\overline{\\mmlToken{mi}{lim}}}' ],
38        // replaced underrightarrow here not supported
39        "varinjlim" => [ 'macro', '\\mathop{\\xrightarrow{\\mmlToken{mi}{lim}}}' ],
40        // replaced underleftarrow here not supported
41        "varprojlim" => [ 'macro', '\\mathop{\\xleftarrow{\\mmlToken{mi}{lim}}}' ],
42        "DeclareMathOperator" => 'HandleDeclareOp',
43        "operatorname" => 'handleOperatorName',
44        "genfrac" => 'genFrac',
45        "frac" => [ 'genFrac', '', '', '', '' ],
46        "tfrac" => [ 'genFrac', '', '', '', '1' ],
47        "dfrac" => [ 'genFrac', '', '', '', '0' ],
48        "binom" => [ 'genFrac', '(', ')', '0', '0' ],
49        "tbinom" => [ 'genFrac', '(', ')', '0', '1' ],
50        "dbinom" => [ 'genFrac', '(', ')', '0', '0' ],
51        "cfrac" => 'cFrac',
52        "shoveleft" => [ 'HandleShove', Align::LEFT ],
53        "shoveright" => [ 'HandleShove', Align::RIGHT ],
54        "xrightarrow" => [ 'xArrow', 0x2192, 5, 10 ],
55        "xleftarrow" => [ 'xArrow', 0x2190, 10, 5 ]
56        ];
57    private const AMSMATHCHAR0MI = [
58        "digamma" => '\u03DD',
59        "varkappa" => '\u03F0',
60        "varGamma" => [ '\u0393', [ "mathvariant" => Variants::ITALIC ] ],
61        "varDelta" => [ '\u0394', [ "mathvariant" => Variants::ITALIC ] ],
62        "varTheta" => [ '\u0398', [ "mathvariant" => Variants::ITALIC ] ],
63        "varLambda" => [ '\u039B', [ "mathvariant" => Variants::ITALIC ] ],
64        "varXi" => [ '\u039E', [ "mathvariant" => Variants::ITALIC ] ],
65        "varPi" => [ '\u03A0', [ "mathvariant" => Variants::ITALIC ] ],
66        "varSigma" => [ '\u03A3', [ "mathvariant" => Variants::ITALIC ] ],
67        "varStigma" => [ '\u03DB', [ "mathvariant" => Variants::ITALIC ] ],
68        "varUpsilon" => [ '\u03A5', [ "mathvariant" => Variants::ITALIC ] ],
69        "varPhi" => [ '\u03A6', [ "mathvariant" => Variants::ITALIC ] ],
70        "varPsi" => [ '\u03A8', [ "mathvariant" => Variants::ITALIC ] ],
71        "varOmega" => [ '\u03A9', [ "mathvariant" => Variants::ITALIC ] ],
72        "beth" => '\u2136',
73        "gimel" => '\u2137',
74        "daleth" => '\u2138',
75        "backprime" => [ '\u2035', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
76        "hslash" => '\u210F',
77        "varnothing" => [ '\u2205', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
78        "blacktriangle" => '\u25B4',
79        "triangledown" => [ '\u25BD', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
80        "blacktriangledown" => '\u25BE',
81        "square" => '\u25FB',
82        "Box" => '\u25FB',
83        "blacksquare" => '\u25FC',
84        "lozenge" => '\u25CA',
85        "Diamond" => '\u25CA',
86        "blacklozenge" => '\u29EB',
87        "circledS" => [ '\u24C8', [ "mathvariant" => Variants::NORMAL ] ],
88        "bigstar" => '\u2605',
89        "sphericalangle" => '\u2222',
90        "measuredangle" => '\u2221',
91        "nexists" => '\u2204',
92        "complement" => '\u2201',
93        "mho" => '\u2127',
94        "eth" => [ '\u00F0', [ "mathvariant" => Variants::NORMAL ] ],
95        "Finv" => '\u2132',
96        "diagup" => '\u2571',
97        "Game" => '\u2141',
98        "diagdown" => '\u2572',
99        "Bbbk" => [ '\u006B', [ "mathvariant" => Variants::DOUBLESTRUCK ] ],
100        "yen" => '\u00A5',
101        "circledR" => '\u00AE',
102        "checkmark" => '\u2713',
103        "maltese" => '\u2720'
104        ];
105    private const AMSMATHCHAR0MO = [
106        "iiiint" => [ '\u2A0C', [ "texClass" => TexClass::OP ] ], // added this mapping from other array
107        "dotplus" => '\u2214',
108        "ltimes" => '\u22C9',
109        "smallsetminus" => [ '\u2216', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
110        "rtimes" => '\u22CA',
111        "Cap" => '\u22D2',
112        "doublecap" => '\u22D2',
113        "leftthreetimes" => '\u22CB',
114        "Cup" => '\u22D3',
115        "doublecup" => '\u22D3',
116        "rightthreetimes" => '\u22CC',
117        "barwedge" => '\u22BC',
118        "curlywedge" => '\u22CF',
119        "veebar" => '\u22BB',
120        "curlyvee" => '\u22CE',
121        "doublebarwedge" => '\u2A5E',
122        "boxminus" => '\u229F',
123        "circleddash" => '\u229D',
124        "boxtimes" => '\u22A0',
125        "circledast" => '\u229B',
126        "boxdot" => '\u22A1',
127        "circledcirc" => '\u229A',
128        "boxplus" => '\u229E',
129        "centerdot" => [ '\u22C5', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
130        "divideontimes" => '\u22C7',
131        "intercal" => '\u22BA',
132        "leqq" => '\u2266',
133        "geqq" => '\u2267',
134        "leqslant" => '\u2A7D',
135        "geqslant" => '\u2A7E',
136        "eqslantless" => '\u2A95',
137        "eqslantgtr" => '\u2A96',
138        "lesssim" => '\u2272',
139        "gtrsim" => '\u2273',
140        "lessapprox" => '\u2A85',
141        "gtrapprox" => '\u2A86',
142        "approxeq" => '\u224A',
143        "lessdot" => '\u22D6',
144        "gtrdot" => '\u22D7',
145        "lll" => '\u22D8',
146        "llless" => '\u22D8',
147        "ggg" => '\u22D9',
148        "gggtr" => '\u22D9',
149        "lessgtr" => '\u2276',
150        "gtrless" => '\u2277',
151        "lesseqgtr" => '\u22DA',
152        "gtreqless" => '\u22DB',
153        "lesseqqgtr" => '\u2A8B',
154        "gtreqqless" => '\u2A8C',
155        "doteqdot" => '\u2251',
156        "Doteq" => '\u2251',
157        "eqcirc" => '\u2256',
158        "risingdotseq" => '\u2253',
159        "circeq" => '\u2257',
160        "fallingdotseq" => '\u2252',
161        "triangleq" => '\u225C',
162        "backsim" => '\u223D',
163        "thicksim" => [ '\u223C', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
164        "backsimeq" => '\u22CD',
165        "thickapprox" => [ '\u2248', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True"
166        "subseteqq" => '\u2AC5',
167        "supseteqq" => '\u2AC6',
168        "Subset" => '\u22D0',
169        "Supset" => '\u22D1',
170        "sqsubset" => '\u228F',
171        "sqsupset" => '\u2290',
172        "preccurlyeq" => '\u227C',
173        "succcurlyeq" => '\u227D',
174        "curlyeqprec" => '\u22DE',
175        "curlyeqsucc" => '\u22DF',
176        "precsim" => '\u227E',
177        "succsim" => '\u227F',
178        "precapprox" => '\u2AB7',
179        "succapprox" => '\u2AB8',
180        "vartriangleleft" => '\u22B2',
181        "lhd" => '\u22B2',
182        "vartriangleright" => '\u22B3',
183        "rhd" => '\u22B3',
184        "trianglelefteq" => '\u22B4',
185        "unlhd" => '\u22B4',
186        "trianglerighteq" => '\u22B5',
187        "unrhd" => '\u22B5',
188        "vDash" => [ '\u22A8', [ "variantForm" => true ] ],
189        "Vdash" => '\u22A9',
190        "Vvdash" => '\u22AA',
191        "smallsmile" => [ '\u2323', [ "variantForm" => true ] ],
192        "shortmid" => [ '\u2223', [ "variantForm" => true ] ],
193        "smallfrown" => [ '\u2322', [ "variantForm" => true ] ],
194        "shortparallel" => [ '\u2225', [ "variantForm" => true ] ],
195        "bumpeq" => '\u224F',
196        "between" => '\u226C',
197        "Bumpeq" => '\u224E',
198        "pitchfork" => '\u22D4',
199        "varpropto" => [ '\u221D', [ "variantForm" => true ] ],
200        "backepsilon" => '\u220D',
201        "blacktriangleleft" => '\u25C2',
202        "blacktriangleright" => '\u25B8',
203        "therefore" => '\u2234',
204        "because" => '\u2235',
205        "eqsim" => '\u2242',
206        "vartriangle" => [ '\u25B3', [ "variantForm" => true ] ],
207        "Join" => '\u22C8',
208        "nless" => '\u226E',
209        "ngtr" => '\u226F',
210        "nleq" => '\u2270',
211        "ngeq" => '\u2271',
212        "nleqslant" => [ '\u2A87', [ "variantForm" => true ] ],
213        "ngeqslant" => [ '\u2A88', [ "variantForm" => true ] ],
214        "nleqq" => [ '\u2270', [ "variantForm" => true ] ],
215        "ngeqq" => [ '\u2271', [ "variantForm" => true ] ],
216        "lneq" => '\u2A87',
217        "gneq" => '\u2A88',
218        "lneqq" => '\u2268',
219        "gneqq" => '\u2269',
220        "lvertneqq" => [ '\u2268', [ "variantForm" => true ] ],
221        "gvertneqq" => [ '\u2269', [ "variantForm" => true ] ],
222        "lnsim" => '\u22E6',
223        "gnsim" => '\u22E7',
224        "lnapprox" => '\u2A89',
225        "gnapprox" => '\u2A8A',
226        "nprec" => '\u2280',
227        "nsucc" => '\u2281',
228        "npreceq" => [ '\u22E0', [ "variantForm" => true ] ],
229        "nsucceq" => [ '\u22E1', [ "variantForm" => true ] ],
230        "precneqq" => '\u2AB5',
231        "succneqq" => '\u2AB6',
232        "precnsim" => '\u22E8',
233        "succnsim" => '\u22E9',
234        "precnapprox" => '\u2AB9',
235        "succnapprox" => '\u2ABA',
236        "nsim" => '\u2241',
237        "ncong" => '\u2246',
238        "nshortmid" => [ '\u2224', [ "variantForm" => true ] ],
239        "nshortparallel" => [ '\u2226', [ "variantForm" => true ] ],
240        "nmid" => '\u2224',
241        "nparallel" => '\u2226',
242        "nvdash" => '\u22AC',
243        "nvDash" => '\u22AD',
244        "nVdash" => '\u22AE',
245        "nVDash" => '\u22AF',
246        "ntriangleleft" => '\u22EA',
247        "ntriangleright" => '\u22EB',
248        "ntrianglelefteq" => '\u22EC',
249        "ntrianglerighteq" => '\u22ED',
250        "nsubseteq" => '\u2288',
251        "nsupseteq" => '\u2289',
252        "nsubseteqq" => [ '\u2288', [ "variantForm" => true ] ],
253        "nsupseteqq" => [ '\u2289', [ "variantForm" => true ] ],
254        "subsetneq" => '\u228A',
255        "supsetneq" => '\u228B',
256        "varsubsetneq" => [ '\u228A', [ "variantForm" => true ] ],
257        "varsupsetneq" => [ '\u228B', [ "variantForm" => true ] ],
258        "subsetneqq" => '\u2ACB',
259        "supsetneqq" => '\u2ACC',
260        "varsubsetneqq" => [ '\u2ACB', [ "variantForm" => true ] ],
261        "varsupsetneqq" => [ '\u2ACC', [ "variantForm" => true ] ],
262        "leftleftarrows" => '\u21C7',
263        "rightrightarrows" => '\u21C9',
264        "leftrightarrows" => '\u21C6',
265        "rightleftarrows" => '\u21C4',
266        "Lleftarrow" => '\u21DA',
267        "Rrightarrow" => '\u21DB',
268        "twoheadleftarrow" => '\u219E',
269        "twoheadrightarrow" => '\u21A0',
270        "leftarrowtail" => '\u21A2',
271        "rightarrowtail" => '\u21A3',
272        "looparrowleft" => '\u21AB',
273        "looparrowright" => '\u21AC',
274        "leftrightharpoons" => '\u21CB',
275        "rightleftharpoons" => [ '\u21CC', [ "variantForm" => true ] ],
276        "curvearrowleft" => '\u21B6',
277        "curvearrowright" => '\u21B7',
278        "circlearrowleft" => '\u21BA',
279        "circlearrowright" => '\u21BB',
280        "Lsh" => '\u21B0',
281        "Rsh" => '\u21B1',
282        "upuparrows" => '\u21C8',
283        "downdownarrows" => '\u21CA',
284        "upharpoonleft" => '\u21BF',
285        "upharpoonright" => '\u21BE',
286        "downharpoonleft" => '\u21C3',
287        "restriction" => '\u21BE',
288        "multimap" => '\u22B8',
289        "downharpoonright" => '\u21C2',
290        "leftrightsquigarrow" => '\u21AD',
291        "rightsquigarrow" => '\u21DD',
292        "leadsto" => '\u21DD',
293        "dashrightarrow" => '\u21E2',
294        "dashleftarrow" => '\u21E0',
295        "nleftarrow" => '\u219A',
296        "nrightarrow" => '\u219B',
297        "nLeftarrow" => '\u21CD',
298        "nRightarrow" => '\u21CF',
299        "nleftrightarrow" => '\u21AE',
300        "nLeftrightarrow" => '\u21CE'
301    ];
302
303    private const AMSMATHENVIRONMENT = [
304        'equation*' => [ 'Equation', null, false ],
305        'eqnarray*' => [ 'EqnArray', null, false, true, 'rcl', null, '.5em' ],
306        'align' => [ 'EqnArray', null, true, true, 'rl', 'ParseUtil_js_1.default.cols(0, 2)' ],
307        'align*' => [ 'EqnArray', null, false, true, 'rl', "ParseUtil_js_1.default.cols(0, 2)" ],
308        "multline" => [ 'Multline', null, true ],
309        'multline*' => [ 'Multline', null, false ],
310        "split" => [ 'EqnArray', null, false, false, 'rl', "ParseUtil_js_1.default.cols(0)" ],
311        "gather" => [ 'EqnArray', null, true, true, 'c' ],
312        'gather*' => [ 'EqnArray', null, false, true, 'c' ],
313        "alignat" => [ 'alignAt', null, true, true ],
314        'alignat*' => [ 'alignAt', null, false, true ],
315        "alignedat" => [ 'alignAt', null, false, false ],
316        "aligned" => [ 'amsEqnArray', null, null, null, 'rl', "ParseUtil_js_1.default.cols(0, 2)", '.5em', 'D' ],
317        "gathered" => [ 'amsEqnArray', null, null, null, 'c', null, '.5em', 'D' ],
318        "xalignat" => [ 'XalignAt', null, true, true ],
319        'xalignat*' => [ 'XalignAt', null, false, true ],
320        "xxalignat" => [ 'XalignAt', null, false, false ],
321        "flalign" => [ 'FlalignArray', null, true, false, true, 'rlc', 'auto auto fit' ],
322        'flalign*' => [ 'FlalignArray', null, false, false, true, 'rlc', 'auto auto fit' ],
323        "subarray" => [ 'array', null, null, null, null, "ParseUtil_js_1.default.cols(0)", '0.1em', 'S', 1 ],
324        "smallmatrix" => [ 'array', null, null, null, 'c', "ParseUtil_js_1.default.cols(1 / 3)",
325            '.2em', 'S', 1 ],
326        "matrix" => [ 'array', null, null, null, 'c' ],
327        "pmatrix" => [ 'array', null, '(', ')', 'c' ],
328        "bmatrix" => [ 'array', null, '[', ']', 'c' ],
329        "Bmatrix" => [ 'array', null, '\\{', '\\}', 'c' ],
330        "vmatrix" => [ 'array', null, '\\vert', '\\vert', 'c' ],
331        "Vmatrix" => [ 'array', null, '\\Vert', '\\Vert', 'c' ],
332        'cases' => [ 'matrix', '{', '', 'left left', null, '.1em', null, true ],
333        'array' => [ 'matrix' ]
334    ];
335    private const AMSSYMBOLDELIMITERS = [
336        'ulcorner' => '\u231C',
337        'urcorner' => '\u231D',
338        'llcorner' => '\u231E',
339        'lrcorner' => '\u231F'
340    ];
341
342    private const AMSSYMBOLMACROS = [
343        "implies" => [ 'macro', '\\;\\Longrightarrow\\;' ],
344        "impliedby" => [ 'macro', '\\;\\Longleftarrow\\;' ]
345    ];
346
347    private const AMSMATHDELIMITERS = [
348        'lvert' => [ '\u007C', [ "texClass" => TexClass::OPEN ] ],
349        'rvert' => [ '\u007C', [ "texClass" => TexClass::CLOSE ] ],
350        'lVert' => [ '\u2016', [ "texClass" => TexClass::OPEN ] ],
351        'rVert' => [ '\u2016', [ "texClass" => TexClass::CLOSE ] ]
352    ];
353    private const ALL = [
354        "amsmathchar0mo" => self::AMSMATHCHAR0MO,
355        "amsmathchar0mi" => self::AMSMATHCHAR0MI,
356        "amsmacros" => self::AMSMACROS,
357        "amssymbolmacros" => self::AMSSYMBOLMACROS,
358        "amsdelimiters" => self::AMSSYMBOLDELIMITERS,
359        "amsmathenvironment" => self::AMSMATHENVIRONMENT
360    ];
361
362    private function __construct() {
363        // Just an empty private constructor, for singleton pattern
364    }
365
366    public static function getAll(): array {
367        return self::ALL;
368    }
369
370    public static function getInstance() {
371        self::$instance ??= new AMSMappings();
372        return self::$instance;
373    }
374
375    public static function getOperatorByKey( $key ) {
376        // &#x221A; to \\u.... this is only temporary probably entities.php will be refactored with \u vals again
377        $key = MMLutil::x2uNotation( $key );
378        return MMLutil::getMappingByKey( $key, self::AMSMATHCHAR0MO, true, true );
379    }
380
381    public static function getIdentifierByKey( $key ) {
382        return MMLutil::getMappingByKey( $key, self::AMSMATHCHAR0MI, true, true );
383    }
384
385    public static function getSymbolDelimiterByKey( $key ) {
386        return MMLutil::getMappingByKey( $key, self::AMSSYMBOLDELIMITERS, true, true );
387    }
388
389    public static function getMathDelimiterByKey( $key ) {
390        return MMLutil::getMappingByKey( $key, self::AMSMATHDELIMITERS, true, true );
391    }
392
393    public static function getMacroByKey( $key ) {
394        $ret = MMLutil::getMappingByKey( $key, self::AMSMACROS, false, true );
395        if ( $ret != null ) {
396            return $ret;
397        }
398        return MMLutil::getMappingByKey( $key, self::AMSSYMBOLMACROS, true, true );
399    }
400
401    public static function getEnvironmentByKey( $key ) {
402        return MMLutil::getMappingByKey( $key, self::AMSMATHENVIRONMENT );
403    }
404}