Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
72.73% |
56 / 77 |
|
58.33% |
7 / 12 |
CRAP | |
0.00% |
0 / 1 |
Literal | |
72.73% |
56 / 77 |
|
58.33% |
7 / 12 |
55.09 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
changeUnicodeFontInput | |
60.00% |
3 / 5 |
|
0.00% |
0 / 1 |
3.58 | |||
renderMML | |
65.22% |
30 / 46 |
|
0.00% |
0 / 1 |
29.16 | |||
getArg | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setArg | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getLiterals | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getExtendedLiterals | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
extractIdentifiers | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
extractSubscripts | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModIdent | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getLiteral | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
createVlineElement | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | declare( strict_types = 1 ); |
4 | |
5 | namespace MediaWiki\Extension\Math\WikiTexVC\Nodes; |
6 | |
7 | use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\BaseMethods; |
8 | use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLParsingUtil; |
9 | use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil; |
10 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmi; |
11 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmn; |
12 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmo; |
13 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmpadded; |
14 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow; |
15 | use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmstyle; |
16 | use MediaWiki\Extension\Math\WikiTexVC\TexUtil; |
17 | |
18 | class Literal extends TexNode { |
19 | |
20 | /** @var string */ |
21 | private $arg; |
22 | private $literals; |
23 | private $extendedLiterals; |
24 | |
25 | public function __construct( string $arg ) { |
26 | parent::__construct( $arg ); |
27 | $this->arg = $arg; |
28 | $this->literals = array_keys( TexUtil::getInstance()->getBaseElements()['is_literal'] ); |
29 | $this->extendedLiterals = $this->literals; |
30 | array_push( $this->extendedLiterals, '\\infty', '\\emptyset' ); |
31 | } |
32 | |
33 | public function changeUnicodeFontInput( $input, $state ) { |
34 | /** |
35 | * In some font modifications, it is required to explicitly use unicode |
36 | * characters instead of (only) attributes in MathML to indicate the font. |
37 | * This is mostly because of Chrome behaviour. I.e. see: https://phabricator.wikimedia.org/T352196 |
38 | */ |
39 | if ( isset( $state["double-struck-literals"] ) ) { |
40 | return MMLParsingUtil::mapToDoubleStruckUnicode( $input ); |
41 | } elseif ( isset( $state["calligraphic"] ) ) { |
42 | return MMLParsingUtil::mapToCaligraphicUnicode( $input ); |
43 | } |
44 | return $input; |
45 | } |
46 | |
47 | public function renderMML( $arguments = [], $state = [] ) { |
48 | if ( isset( $state["intent-params"] ) ) { |
49 | foreach ( $state["intent-params"] as $intparam ) { |
50 | if ( $intparam == $this->arg ) { |
51 | $arguments["arg"] = $intparam; |
52 | } |
53 | } |
54 | } |
55 | |
56 | if ( isset( $state["intent-params-expl"] ) ) { |
57 | $arguments["arg"] = $state["intent-params-expl"]; |
58 | } |
59 | |
60 | if ( $this->arg === " " ) { |
61 | // Fixes https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Math/+/961711 |
62 | // And they creation of empty mo elements. |
63 | return ""; |
64 | } |
65 | |
66 | if ( is_numeric( $this->arg ) ) { |
67 | $mn = new MMLmn( "", $arguments ); |
68 | return $mn->encapsulateRaw( $this->changeUnicodeFontInput( $this->arg, $state ) ); |
69 | } |
70 | // is important to split and find chars within curly and differentiate, see tc 459 |
71 | $foundOperatorContent = MMLutil::initalParseLiteralExpression( $this->arg ); |
72 | if ( !$foundOperatorContent ) { |
73 | $input = $this->arg; |
74 | $operatorContent = null; |
75 | } else { |
76 | $input = $foundOperatorContent[1][0]; |
77 | $operatorContent = [ "foundOC" => $foundOperatorContent[2][0] ]; |
78 | } |
79 | |
80 | // This is rather a workaround: |
81 | // Sometimes literals from WikiTexVC contain complete \\operatorname {asd} hinted as bug tex-2-mml.json |
82 | if ( str_contains( $input, "\\operatorname" ) ) { |
83 | $mi = new MMLmi(); |
84 | return $mi->encapsulateRaw( $operatorContent["foundOC"] ); |
85 | } |
86 | |
87 | $inputP = MMLutil::inputPreparation( $input ); |
88 | |
89 | // Sieve for Operators |
90 | $bm = new BaseMethods(); |
91 | $ret = $bm->checkAndParseOperator( $inputP, $this, $arguments, $operatorContent, $state, false ); |
92 | if ( $ret ) { |
93 | return $ret; |
94 | } |
95 | // Sieve for mathchar07 chars |
96 | $bm = new BaseMethods(); |
97 | $ret = $bm->checkAndParseMathCharacter( $inputP, $this, $arguments, $operatorContent, false ); |
98 | if ( $ret ) { |
99 | return $ret; |
100 | } |
101 | |
102 | // Sieve for Identifiers |
103 | $ret = $bm->checkAndParseIdentifier( $inputP, $this, $arguments, $operatorContent, false ); |
104 | if ( $ret ) { |
105 | return $ret; |
106 | } |
107 | // Sieve for Delimiters |
108 | $ret = $bm->checkAndParseDelimiter( $input, $this, $arguments, $operatorContent ); |
109 | if ( $ret ) { |
110 | return $ret; |
111 | } |
112 | |
113 | // Sieve for Makros |
114 | $ret = BaseMethods::checkAndParse( $inputP, $arguments, |
115 | array_merge( $operatorContent ?? [], $state ?? [] ), |
116 | $this, false ); |
117 | if ( $ret ) { |
118 | |
119 | return $ret; |
120 | } |
121 | |
122 | // Specific |
123 | if ( !( empty( $state['inMatrix'] ) ) && trim( $this->arg ) === '\vline' ) { |
124 | return $this->createVlineElement(); |
125 | } |
126 | |
127 | if ( !( empty( $state['inHBox'] ) ) ) { |
128 | // No mi, if literal is from HBox |
129 | return $input; |
130 | } |
131 | |
132 | // If falling through all sieves just create an MI element |
133 | $mi = new MMLmi( "", $arguments ); |
134 | return $mi->encapsulateRaw( $this->changeUnicodeFontInput( $input, $state ) ); // $this->arg |
135 | } |
136 | |
137 | /** |
138 | * @return string |
139 | */ |
140 | public function getArg(): string { |
141 | return $this->arg; |
142 | } |
143 | |
144 | public function setArg( $arg ) { |
145 | $this->arg = $arg; |
146 | } |
147 | |
148 | /** |
149 | * @return int[]|string[] |
150 | */ |
151 | public function getLiterals(): array { |
152 | return $this->literals; |
153 | } |
154 | |
155 | /** |
156 | * @return int[]|string[] |
157 | */ |
158 | public function getExtendedLiterals(): array { |
159 | return $this->extendedLiterals; |
160 | } |
161 | |
162 | public function extractIdentifiers( $args = null ) { |
163 | return $this->getLiteral( $this->literals, '/^([a-zA-Z\']|\\\\int)$/' ); |
164 | } |
165 | |
166 | public function extractSubscripts() { |
167 | return $this->getLiteral( $this->extendedLiterals, '/^([0-9a-zA-Z+\',-])$/' ); |
168 | } |
169 | |
170 | public function getModIdent() { |
171 | if ( $this->arg === '\\ ' ) { |
172 | return [ '\\ ' ]; |
173 | } |
174 | return $this->getLiteral( $this->literals, '/^([0-9a-zA-Z\'])$/' ); |
175 | } |
176 | |
177 | private function getLiteral( $lit, $regexp ) { |
178 | $s = trim( $this->arg ); |
179 | if ( preg_match( $regexp, $s ) == 1 ) { |
180 | return [ $s ]; |
181 | } elseif ( in_array( $s, $lit, true ) ) { |
182 | return [ $s ]; |
183 | } else { |
184 | return []; |
185 | } |
186 | } |
187 | |
188 | /** |
189 | * @return string |
190 | */ |
191 | public function createVlineElement(): string { |
192 | $mrow = new MMLmrow(); |
193 | $mpAdded = new MMLmpadded( "", [ "depth" => "0", "height" => "0" ] ); |
194 | $mStyle = new MMLmstyle( "", [ "mathsize" => "1.2em" ] ); |
195 | $mo = new MMLmo( "", [ "fence" => "false", "stretchy" => "false" ] ); |
196 | return $mrow->encapsulateRaw( $mpAdded->encapsulateRaw( |
197 | $mStyle->encapsulateRaw( $mo->encapsulateRaw( "|" ) ) ) ); |
198 | } |
199 | |
200 | } |