(
expression: AnyParseNode[],
options: Options,
isOrdgroup?: boolean,
)
| 166 | * <mtext> tag. |
| 167 | */ |
| 168 | export const buildExpression = function( |
| 169 | expression: AnyParseNode[], |
| 170 | options: Options, |
| 171 | isOrdgroup?: boolean, |
| 172 | ): MathNode[] { |
| 173 | if (expression.length === 1) { |
| 174 | const group = buildGroup(expression[0], options); |
| 175 | if (isOrdgroup && group instanceof MathNode && group.type === "mo") { |
| 176 | // When TeX writers want to suppress spacing on an operator, |
| 177 | // they often put the operator by itself inside braces. |
| 178 | group.setAttribute("lspace", "0em"); |
| 179 | group.setAttribute("rspace", "0em"); |
| 180 | } |
| 181 | return [group]; |
| 182 | } |
| 183 | |
| 184 | const groups = []; |
| 185 | let lastGroup; |
| 186 | for (let i = 0; i < expression.length; i++) { |
| 187 | const group = buildGroup(expression[i], options); |
| 188 | if (group instanceof MathNode && lastGroup instanceof MathNode) { |
| 189 | // Concatenate adjacent <mtext>s |
| 190 | if (group.type === 'mtext' && lastGroup.type === 'mtext' |
| 191 | && group.getAttribute('mathvariant') === |
| 192 | lastGroup.getAttribute('mathvariant')) { |
| 193 | lastGroup.children.push(...group.children); |
| 194 | continue; |
| 195 | // Concatenate adjacent <mn>s |
| 196 | } else if (group.type === 'mn' && lastGroup.type === 'mn') { |
| 197 | lastGroup.children.push(...group.children); |
| 198 | continue; |
| 199 | // Concatenate <mn>...</mn> followed by <mi>.</mi> |
| 200 | } else if (isNumberPunctuation(group) && lastGroup.type === 'mn') { |
| 201 | lastGroup.children.push(...group.children); |
| 202 | continue; |
| 203 | // Concatenate <mi>.</mi> followed by <mn>...</mn> |
| 204 | } else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) { |
| 205 | group.children = [...lastGroup.children, ...group.children]; |
| 206 | groups.pop(); |
| 207 | // Put preceding <mn>...</mn> or <mi>.</mi> inside base of |
| 208 | // <msup><mn>...base...</mn>...exponent...</msup> (or <msub>) |
| 209 | } else if ((group.type === 'msup' || group.type === 'msub') && |
| 210 | group.children.length >= 1 && |
| 211 | (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup)) |
| 212 | ) { |
| 213 | const base = group.children[0]; |
| 214 | if (base instanceof MathNode && base.type === 'mn') { |
| 215 | base.children = [...lastGroup.children, ...base.children]; |
| 216 | groups.pop(); |
| 217 | } |
| 218 | // \not |
| 219 | } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) { |
| 220 | const lastChild = lastGroup.children[0]; |
| 221 | if (lastChild instanceof TextNode && lastChild.text === '\u0338' && |
| 222 | (group.type === 'mo' || group.type === 'mi' || |
| 223 | group.type === 'mn')) { |
| 224 | const child = group.children[0]; |
| 225 | if (child instanceof TextNode && child.text.length > 0) { |
no test coverage detected