temml 0.10.24 → 0.10.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/contrib/auto-render/dist/auto-render.js +4 -7
- package/contrib/auto-render/dist/auto-render.min.js +1 -1
- package/contrib/auto-render/test/auto-render.js +4 -7
- package/contrib/mhchem/mhchem.js +19 -5
- package/contrib/mhchem/mhchem.min.js +1 -1
- package/dist/Temml-Asana.css +117 -34
- package/dist/Temml-Fira.css +117 -34
- package/dist/Temml-Latin-Modern.css +117 -34
- package/dist/Temml-Libertinus.css +117 -34
- package/dist/Temml-Local.css +117 -34
- package/dist/Temml-STIX2.css +117 -34
- package/dist/temml.cjs +7099 -6901
- package/dist/temml.js +4694 -4510
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +7099 -6901
- package/dist/temmlPostProcess.js +1 -3
- package/package.json +8 -5
- package/src/Parser.js +7 -4
- package/src/buildMathML.js +55 -32
- package/src/environments/array.js +54 -13
- package/src/environments/cd.js +1 -1
- package/src/functions/accent.js +32 -7
- package/src/functions/color.js +2 -0
- package/src/functions/def.js +1 -2
- package/src/functions/delimsizing.js +14 -5
- package/src/functions/enclose.js +60 -31
- package/src/functions/op.js +15 -1
- package/src/functions/supsub.js +2 -2
- package/src/functions/text.js +7 -3
- package/src/macros.js +5 -1
- package/src/postProcess.js +1 -1
- package/src/symbols.js +5 -0
package/dist/temmlPostProcess.js
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
* https://mit-license.org/
|
15
15
|
*/
|
16
16
|
|
17
|
-
const version = "0.10.
|
17
|
+
const version = "0.10.30";
|
18
18
|
|
19
19
|
function postProcess(block) {
|
20
20
|
const labelMap = {};
|
@@ -65,6 +65,4 @@
|
|
65
65
|
exports.postProcess = postProcess;
|
66
66
|
exports.version = version;
|
67
67
|
|
68
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
69
|
-
|
70
68
|
}));
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "temml",
|
3
|
-
"version": "0.10.
|
3
|
+
"version": "0.10.30",
|
4
4
|
"description": "TeX to MathML conversion in JavaScript.",
|
5
5
|
"main": "dist/temml.js",
|
6
6
|
"engines": {
|
@@ -28,10 +28,13 @@
|
|
28
28
|
],
|
29
29
|
"license": "MIT",
|
30
30
|
"devDependencies": {
|
31
|
-
"eslint": "^
|
31
|
+
"@eslint/eslintrc": "^3.1.0",
|
32
|
+
"@eslint/js": "^9.11.1",
|
33
|
+
"eslint": "^9.11.1",
|
32
34
|
"esm": "^3.2.25",
|
33
|
-
"
|
34
|
-
"
|
35
|
+
"globals": "^15.9.0",
|
36
|
+
"rollup": "^4.22.4",
|
37
|
+
"terser": "^5.34.0"
|
35
38
|
},
|
36
39
|
"scripts": {
|
37
40
|
"lint": "eslint temml.js src",
|
@@ -39,7 +42,7 @@
|
|
39
42
|
"visual-test": "node utils/buildTests.js",
|
40
43
|
"test": "yarn lint && node utils/buildTests.js && yarn unit-test",
|
41
44
|
"minify": "terser test/temml.js -o site/assets/temml.min.js -c -m && terser contrib/mhchem/mhchem.js -o site/assets/mhchem.min.js -c -m",
|
42
|
-
"build": "rollup --config ./utils/rollupConfig.
|
45
|
+
"build": "rollup --config ./utils/rollupConfig.mjs && yarn minify && node utils/insertPlugins.js",
|
43
46
|
"docs": "node utils/buildDocs.js",
|
44
47
|
"dist": "yarn build && node ./utils/copyfiles.js && terser contrib/auto-render/test/auto-render.js -o contrib/auto-render/dist/auto-render.min.js -c -m"
|
45
48
|
}
|
package/src/Parser.js
CHANGED
@@ -16,6 +16,7 @@ import unicodeAccents from /*preval*/ "./unicodeAccents";
|
|
16
16
|
import unicodeSymbols from /*preval*/ "./unicodeSymbols";
|
17
17
|
|
18
18
|
const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
|
19
|
+
const sizeRegEx = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/
|
19
20
|
|
20
21
|
/**
|
21
22
|
* This file contains the parser used to parse out a TeX expression from the
|
@@ -679,7 +680,7 @@ export default class Parser {
|
|
679
680
|
res.text = "0pt"; // Enable \above{}
|
680
681
|
isBlank = true; // This is here specifically for \genfrac
|
681
682
|
}
|
682
|
-
const match =
|
683
|
+
const match = sizeRegEx.exec(res.text);
|
683
684
|
if (!match) {
|
684
685
|
throw new ParseError("Invalid size: '" + res.text + "'", res);
|
685
686
|
}
|
@@ -885,7 +886,7 @@ export default class Parser {
|
|
885
886
|
// At this point, we should have a symbol, possibly with accents.
|
886
887
|
// First expand any accented base symbol according to unicodeSymbols.
|
887
888
|
if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) &&
|
888
|
-
|
889
|
+
this.mode === "math" && !symbols[this.mode][text[0]]) {
|
889
890
|
// This behavior is not strict (XeTeX-compatible) in math mode.
|
890
891
|
if (this.settings.strict && this.mode === "math") {
|
891
892
|
throw new ParseError(`Accented Unicode text character "${text[0]}" used in ` + `math mode`,
|
@@ -895,7 +896,9 @@ export default class Parser {
|
|
895
896
|
text = unicodeSymbols[text[0]] + text.slice(1);
|
896
897
|
}
|
897
898
|
// Strip off any combining characters
|
898
|
-
const match =
|
899
|
+
const match = this.mode === "math"
|
900
|
+
? combiningDiacriticalMarksEndRegex.exec(text)
|
901
|
+
: null
|
899
902
|
if (match) {
|
900
903
|
text = text.substring(0, match.index);
|
901
904
|
if (text === "i") {
|
@@ -948,7 +951,7 @@ export default class Parser {
|
|
948
951
|
};
|
949
952
|
}
|
950
953
|
symbol = s;
|
951
|
-
} else if (text.charCodeAt(0) >= 0x80) {
|
954
|
+
} else if (text.charCodeAt(0) >= 0x80 || combiningDiacriticalMarksEndRegex.exec(text)) {
|
952
955
|
// no symbol for e.g. ^
|
953
956
|
if (this.settings.strict && this.mode === "math") {
|
954
957
|
throw new ParseError(`Unicode text character "${text[0]}" used in math mode`, nucleus)
|
package/src/buildMathML.js
CHANGED
@@ -34,49 +34,72 @@ export const makeText = function(text, mode, style) {
|
|
34
34
|
return new mathMLTree.TextNode(text);
|
35
35
|
};
|
36
36
|
|
37
|
+
const copyChar = (newRow, child) => {
|
38
|
+
if (newRow.children.length === 0 ||
|
39
|
+
newRow.children[newRow.children.length - 1].type !== "mtext") {
|
40
|
+
const mtext = new mathMLTree.MathNode(
|
41
|
+
"mtext",
|
42
|
+
[new mathMLTree.TextNode(child.children[0].text)]
|
43
|
+
)
|
44
|
+
newRow.children.push(mtext)
|
45
|
+
} else {
|
46
|
+
newRow.children[newRow.children.length - 1].children[0].text += child.children[0].text
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
37
50
|
export const consolidateText = mrow => {
|
38
51
|
// If possible, consolidate adjacent <mtext> elements into a single element.
|
39
52
|
if (mrow.type !== "mrow" && mrow.type !== "mstyle") { return mrow }
|
40
53
|
if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
"mtext"
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
const newRow = new mathMLTree.MathNode("mrow")
|
55
|
+
for (let i = 0; i < mrow.children.length; i++) {
|
56
|
+
const child = mrow.children[i];
|
57
|
+
if (child.type === "mtext" && Object.keys(child.attributes).length === 0) {
|
58
|
+
copyChar(newRow, child)
|
59
|
+
} else if (child.type === "mrow") {
|
60
|
+
// We'll also check the children of an mrow. One level only. No recursion.
|
61
|
+
let canConsolidate = true
|
62
|
+
for (let j = 0; j < child.children.length; j++) {
|
63
|
+
const grandChild = child.children[j];
|
64
|
+
if (grandChild.type !== "mtext" || Object.keys(child.attributes).length !== 0) {
|
65
|
+
canConsolidate = false
|
66
|
+
break
|
67
|
+
}
|
68
|
+
}
|
69
|
+
if (canConsolidate) {
|
70
|
+
for (let j = 0; j < child.children.length; j++) {
|
71
|
+
const grandChild = child.children[j];
|
72
|
+
copyChar(newRow, grandChild)
|
59
73
|
}
|
74
|
+
} else {
|
75
|
+
newRow.children.push(child)
|
60
76
|
}
|
61
|
-
} else if (localVariant !== variant || mrow.children[i].type !== "mtext") {
|
62
|
-
return mrow
|
63
77
|
} else {
|
64
|
-
|
78
|
+
newRow.children.push(child)
|
65
79
|
}
|
66
80
|
}
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
81
|
+
for (let i = 0; i < newRow.children.length; i++) {
|
82
|
+
if (newRow.children[i].type === "mtext") {
|
83
|
+
const mtext = newRow.children[i];
|
84
|
+
// Firefox does not render a space at either end of an <mtext> string.
|
85
|
+
// To get proper rendering, we replace leading or trailing spaces with no-break spaces.
|
86
|
+
if (mtext.children[0].text.charAt(0) === " ") {
|
87
|
+
mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1)
|
88
|
+
}
|
89
|
+
const L = mtext.children[0].text.length
|
90
|
+
if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") {
|
91
|
+
mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"
|
92
|
+
}
|
93
|
+
for (const [key, value] of Object.entries(mrow.attributes)) {
|
94
|
+
mtext.attributes[key] = value
|
95
|
+
}
|
96
|
+
}
|
75
97
|
}
|
76
|
-
|
77
|
-
|
98
|
+
if (newRow.children.length === 1 && newRow.children[0].type === "mtext") {
|
99
|
+
return newRow.children[0]; // A consolidated <mtext>
|
100
|
+
} else {
|
101
|
+
return newRow
|
78
102
|
}
|
79
|
-
return mtext
|
80
103
|
}
|
81
104
|
|
82
105
|
const numberRegEx = /^[0-9]$/
|
@@ -7,7 +7,8 @@ import { StyleLevel } from "../constants"
|
|
7
7
|
import ParseError from "../ParseError";
|
8
8
|
import { assertNodeType, assertSymbolNodeType } from "../parseNode";
|
9
9
|
import { checkSymbolNodeType } from "../parseNode";
|
10
|
-
|
10
|
+
import { stringFromArg } from "../macros"
|
11
|
+
import { calculateSize } from "../units"
|
11
12
|
import * as mml from "../buildMathML";
|
12
13
|
|
13
14
|
// Helper functions
|
@@ -38,6 +39,24 @@ const validateAmsEnvironmentContext = context => {
|
|
38
39
|
}
|
39
40
|
}
|
40
41
|
|
42
|
+
const sizeRegEx = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/
|
43
|
+
const arrayGaps = macros => {
|
44
|
+
let arraystretch = macros.get("\\arraystretch")
|
45
|
+
if (typeof arraystretch !== "string") {
|
46
|
+
arraystretch = stringFromArg(arraystretch.tokens)
|
47
|
+
}
|
48
|
+
arraystretch = isNaN(arraystretch) ? null : Number(arraystretch)
|
49
|
+
let arraycolsepStr = macros.get("\\arraycolsep")
|
50
|
+
if (typeof arraycolsepStr !== "string") {
|
51
|
+
arraycolsepStr = stringFromArg(arraycolsepStr.tokens)
|
52
|
+
}
|
53
|
+
const match = sizeRegEx.exec(arraycolsepStr)
|
54
|
+
const arraycolsep = match
|
55
|
+
? { number: +(match[1] + match[2]), unit: match[3] }
|
56
|
+
: null
|
57
|
+
return [arraystretch, arraycolsep]
|
58
|
+
}
|
59
|
+
|
41
60
|
const getTag = (group, style, rowNum) => {
|
42
61
|
let tag
|
43
62
|
const tagContents = group.tags.shift()
|
@@ -76,12 +95,14 @@ function parseArray(
|
|
76
95
|
{
|
77
96
|
cols, // [{ type: string , align: l|c|r|null }]
|
78
97
|
envClasses, // align(ed|at|edat) | array | cases | cd | small | multline
|
79
|
-
addEqnNum,
|
80
|
-
singleRow,
|
98
|
+
addEqnNum, // boolean
|
99
|
+
singleRow, // boolean
|
81
100
|
emptySingleRow, // boolean
|
82
|
-
maxNumCols,
|
83
|
-
leqno
|
84
|
-
|
101
|
+
maxNumCols, // number
|
102
|
+
leqno, // boolean
|
103
|
+
arraystretch, // number | null
|
104
|
+
arraycolsep // size value | null
|
105
|
+
},
|
85
106
|
scriptLevel
|
86
107
|
) {
|
87
108
|
parser.gullet.beginGroup();
|
@@ -111,7 +132,6 @@ function parseArray(
|
|
111
132
|
// Test for \hline at the top of the array.
|
112
133
|
hLinesBeforeRow.push(getHLines(parser));
|
113
134
|
|
114
|
-
// eslint-disable-next-line no-constant-condition
|
115
135
|
while (true) {
|
116
136
|
// Parse each cell in its own group (namespace)
|
117
137
|
let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
|
@@ -211,7 +231,9 @@ function parseArray(
|
|
211
231
|
addEqnNum,
|
212
232
|
scriptLevel,
|
213
233
|
tags,
|
214
|
-
leqno
|
234
|
+
leqno,
|
235
|
+
arraystretch,
|
236
|
+
arraycolsep
|
215
237
|
};
|
216
238
|
}
|
217
239
|
|
@@ -301,12 +323,18 @@ const mathmlBuilder = function(group, style) {
|
|
301
323
|
}
|
302
324
|
|
303
325
|
if (group.envClasses.length > 0) {
|
304
|
-
|
326
|
+
let pad = group.envClasses.includes("jot")
|
305
327
|
? "0.7" // 0.5ex + 0.09em top & bot padding
|
306
328
|
: group.envClasses.includes("small")
|
307
329
|
? "0.35"
|
308
330
|
: "0.5" // 0.5ex default top & bot padding
|
309
|
-
|
331
|
+
if (group.arraystretch && group.arraystretch !== 1) {
|
332
|
+
// In LaTeX, \arraystretch is a factor applied to a 12pt strut height.
|
333
|
+
// It defines a baseline to baseline distance.
|
334
|
+
// Here, we do an approximation of that approach.
|
335
|
+
pad = String(1.4 * group.arraystretch - 0.8)
|
336
|
+
}
|
337
|
+
let sidePadding = group.envClasses.includes("abut")
|
310
338
|
? "0"
|
311
339
|
: group.envClasses.includes("cases")
|
312
340
|
? "0"
|
@@ -315,6 +343,12 @@ const mathmlBuilder = function(group, style) {
|
|
315
343
|
: group.envClasses.includes("cd")
|
316
344
|
? "0.25"
|
317
345
|
: "0.4" // default side padding
|
346
|
+
let sidePadUnit = "em"
|
347
|
+
if (group.arraycolsep) {
|
348
|
+
const arraySidePad = calculateSize(group.arraycolsep, style)
|
349
|
+
sidePadding = arraySidePad.number
|
350
|
+
sidePadUnit = arraySidePad.unit
|
351
|
+
}
|
318
352
|
|
319
353
|
const numCols = tbl.length === 0 ? 0 : tbl[0].children.length
|
320
354
|
|
@@ -333,7 +367,8 @@ const mathmlBuilder = function(group, style) {
|
|
333
367
|
// Padding
|
334
368
|
for (let i = 0; i < tbl.length; i++) {
|
335
369
|
for (let j = 0; j < tbl[i].children.length; j++) {
|
336
|
-
tbl[i].children[j].style.padding = `${pad}ex ${sidePad(j, 1)}
|
370
|
+
tbl[i].children[j].style.padding = `${pad}ex ${sidePad(j, 1)}${sidePadUnit}`
|
371
|
+
+ ` ${pad}ex ${sidePad(j, 0)}${sidePadUnit}`
|
337
372
|
}
|
338
373
|
}
|
339
374
|
|
@@ -587,10 +622,13 @@ defineEnvironment({
|
|
587
622
|
}
|
588
623
|
throw new ParseError("Unknown column alignment: " + ca, nde);
|
589
624
|
});
|
625
|
+
const [arraystretch, arraycolsep] = arrayGaps(context.parser.gullet.macros)
|
590
626
|
const res = {
|
591
627
|
cols,
|
592
628
|
envClasses: ["array"],
|
593
|
-
maxNumCols: cols.length
|
629
|
+
maxNumCols: cols.length,
|
630
|
+
arraystretch,
|
631
|
+
arraycolsep
|
594
632
|
};
|
595
633
|
return parseArray(context.parser, res, dCellStyle(context.envName));
|
596
634
|
},
|
@@ -656,6 +694,7 @@ defineEnvironment({
|
|
656
694
|
}
|
657
695
|
const res = parseArray(context.parser, payload, "text")
|
658
696
|
res.cols = new Array(res.body[0].length).fill({ type: "align", align: colAlign })
|
697
|
+
const [arraystretch, arraycolsep] = arrayGaps(context.parser.gullet.macros)
|
659
698
|
return delimiters
|
660
699
|
? {
|
661
700
|
type: "leftright",
|
@@ -663,7 +702,9 @@ defineEnvironment({
|
|
663
702
|
body: [res],
|
664
703
|
left: delimiters[0],
|
665
704
|
right: delimiters[1],
|
666
|
-
rightColor: undefined // \right uninfluenced by \color in array
|
705
|
+
rightColor: undefined, // \right uninfluenced by \color in array
|
706
|
+
arraystretch,
|
707
|
+
arraycolsep
|
667
708
|
}
|
668
709
|
: res;
|
669
710
|
},
|
package/src/environments/cd.js
CHANGED
@@ -71,7 +71,7 @@ export function parseCD(parser) {
|
|
71
71
|
parser.gullet.beginGroup();
|
72
72
|
parser.gullet.macros.set("\\cr", "\\\\\\relax");
|
73
73
|
parser.gullet.beginGroup();
|
74
|
-
while (true) {
|
74
|
+
while (true) {
|
75
75
|
// Get the parse nodes for the next row.
|
76
76
|
parsedRows.push(parser.parseExpression(false, "\\\\"));
|
77
77
|
parser.gullet.endGroup();
|
package/src/functions/accent.js
CHANGED
@@ -71,6 +71,20 @@ const needWebkitShift = new Set([
|
|
71
71
|
"\\'", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"
|
72
72
|
])
|
73
73
|
|
74
|
+
const combiningChar = {
|
75
|
+
"\\`": "\u0300",
|
76
|
+
"\\'": "\u0301",
|
77
|
+
"\\^": "\u0302",
|
78
|
+
"\\~": "\u0303",
|
79
|
+
"\\=": "\u0304",
|
80
|
+
"\\u": "\u0306",
|
81
|
+
"\\.": "\u0307",
|
82
|
+
'\\"': "\u0308",
|
83
|
+
"\\r": "\u030A",
|
84
|
+
"\\H": "\u030B",
|
85
|
+
"\\v": "\u030C"
|
86
|
+
}
|
87
|
+
|
74
88
|
// Accents
|
75
89
|
defineFunction({
|
76
90
|
type: "accent",
|
@@ -140,13 +154,24 @@ defineFunction({
|
|
140
154
|
console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`)
|
141
155
|
}
|
142
156
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
157
|
+
if (mode === "text" && base.text && base.text.length === 1
|
158
|
+
&& context.funcName in combiningChar && smalls.indexOf(base.text) > -1) {
|
159
|
+
// Return a combining accent character
|
160
|
+
return {
|
161
|
+
type: "textord",
|
162
|
+
mode: "text",
|
163
|
+
text: base.text + combiningChar[context.funcName]
|
164
|
+
}
|
165
|
+
} else {
|
166
|
+
// Build up the accent
|
167
|
+
return {
|
168
|
+
type: "accent",
|
169
|
+
mode: mode,
|
170
|
+
label: context.funcName,
|
171
|
+
isStretchy: false,
|
172
|
+
base: base
|
173
|
+
}
|
174
|
+
}
|
150
175
|
},
|
151
176
|
mathmlBuilder
|
152
177
|
});
|
package/src/functions/color.js
CHANGED
@@ -186,6 +186,7 @@ defineFunction({
|
|
186
186
|
type: "color",
|
187
187
|
mode: parser.mode,
|
188
188
|
color,
|
189
|
+
isTextColor: true,
|
189
190
|
body: ordargument(body)
|
190
191
|
}
|
191
192
|
},
|
@@ -218,6 +219,7 @@ defineFunction({
|
|
218
219
|
type: "color",
|
219
220
|
mode: parser.mode,
|
220
221
|
color,
|
222
|
+
isTextColor: false,
|
221
223
|
body
|
222
224
|
}
|
223
225
|
},
|
package/src/functions/def.js
CHANGED
@@ -118,10 +118,8 @@ function checkDelimiter(delim, context) {
|
|
118
118
|
if (symDelim && delimiters.includes(symDelim.text)) {
|
119
119
|
// If a character is not in the MathML operator dictionary, it will not stretch.
|
120
120
|
// Replace such characters w/characters that will stretch.
|
121
|
-
if (["/", "\u2044"].includes(symDelim.text)) { symDelim.text = "\u2215" }
|
122
121
|
if (["<", "\\lt"].includes(symDelim.text)) { symDelim.text = "⟨" }
|
123
122
|
if ([">", "\\gt"].includes(symDelim.text)) { symDelim.text = "⟩" }
|
124
|
-
if (symDelim.text === "\\backslash") { symDelim.text = "\u2216" }
|
125
123
|
return symDelim;
|
126
124
|
} else if (symDelim) {
|
127
125
|
throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim);
|
@@ -130,6 +128,9 @@ function checkDelimiter(delim, context) {
|
|
130
128
|
}
|
131
129
|
}
|
132
130
|
|
131
|
+
// / \
|
132
|
+
const needExplicitStretch = ["\u002F", "\u005C", "\\backslash", "\\vert", "|"];
|
133
|
+
|
133
134
|
defineFunction({
|
134
135
|
type: "delimsizing",
|
135
136
|
names: [
|
@@ -182,8 +183,7 @@ defineFunction({
|
|
182
183
|
// defaults.
|
183
184
|
node.setAttribute("fence", "false");
|
184
185
|
}
|
185
|
-
if (group.delim
|
186
|
-
group.delim === "|" || group.delim.indexOf("arrow") > -1) {
|
186
|
+
if (needExplicitStretch.includes(group.delim) || group.delim.indexOf("arrow") > -1) {
|
187
187
|
// We have to explicitly set stretchy to true.
|
188
188
|
node.setAttribute("stretchy", "true")
|
189
189
|
}
|
@@ -269,7 +269,7 @@ defineFunction({
|
|
269
269
|
const leftNode = new mathMLTree.MathNode("mo", [mml.makeText(group.left, group.mode)]);
|
270
270
|
leftNode.setAttribute("fence", "true")
|
271
271
|
leftNode.setAttribute("form", "prefix")
|
272
|
-
if (group.left === "\
|
272
|
+
if (group.left === "/" || group.left === "\u005C" || group.left.indexOf("arrow") > -1) {
|
273
273
|
leftNode.setAttribute("stretchy", "true")
|
274
274
|
}
|
275
275
|
inner.unshift(leftNode)
|
@@ -281,6 +281,15 @@ defineFunction({
|
|
281
281
|
if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
|
282
282
|
rightNode.setAttribute("stretchy", "true")
|
283
283
|
}
|
284
|
+
if (group.body.length > 0) {
|
285
|
+
const lastElement = group.body[group.body.length - 1];
|
286
|
+
if (lastElement.type === "color" && !lastElement.isTextColor) {
|
287
|
+
// \color is a switch. If the last element is of type "color" then
|
288
|
+
// the user set the \color switch and left it on.
|
289
|
+
// A \right delimiter turns the switch off, but the delimiter itself gets the color.
|
290
|
+
rightNode.setAttribute("mathcolor", lastElement.color);
|
291
|
+
}
|
292
|
+
}
|
284
293
|
inner.push(rightNode)
|
285
294
|
|
286
295
|
return mml.makeRow(inner);
|
package/src/functions/enclose.js
CHANGED
@@ -22,52 +22,62 @@ const mathmlBuilder = (group, style) => {
|
|
22
22
|
padding()
|
23
23
|
])
|
24
24
|
} else {
|
25
|
-
node = new mathMLTree.MathNode("
|
25
|
+
node = new mathMLTree.MathNode("menclose", [mml.buildGroup(group.body, style)])
|
26
26
|
}
|
27
27
|
switch (group.label) {
|
28
28
|
case "\\overline":
|
29
|
-
node.
|
30
|
-
node.
|
29
|
+
node.setAttribute("notation", "top") // for Firefox & WebKit
|
30
|
+
node.classes.push("tml-overline") // for Chromium
|
31
31
|
break
|
32
32
|
case "\\underline":
|
33
|
-
node.
|
34
|
-
node.
|
33
|
+
node.setAttribute("notation", "bottom")
|
34
|
+
node.classes.push("tml-underline")
|
35
35
|
break
|
36
36
|
case "\\cancel":
|
37
|
-
|
38
|
-
|
39
|
-
node.classes.push("tml-cancel")
|
37
|
+
node.setAttribute("notation", "updiagonalstrike")
|
38
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["tml-cancel", "upstrike"]))
|
40
39
|
break
|
41
40
|
case "\\bcancel":
|
42
|
-
node.
|
41
|
+
node.setAttribute("notation", "downdiagonalstrike")
|
42
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["tml-cancel", "downstrike"]))
|
43
|
+
break
|
44
|
+
case "\\sout":
|
45
|
+
node.setAttribute("notation", "horizontalstrike")
|
46
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["tml-cancel", "sout"]))
|
47
|
+
break
|
48
|
+
case "\\xcancel":
|
49
|
+
node.setAttribute("notation", "updiagonalstrike downdiagonalstrike")
|
50
|
+
node.classes.push("tml-xcancel")
|
43
51
|
break
|
44
|
-
/*
|
45
52
|
case "\\longdiv":
|
46
|
-
node.setAttribute("notation", "longdiv")
|
53
|
+
node.setAttribute("notation", "longdiv")
|
54
|
+
node.classes.push("longdiv-top")
|
55
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["longdiv-arc"]))
|
47
56
|
break
|
48
57
|
case "\\phase":
|
49
|
-
node.setAttribute("notation", "phasorangle")
|
50
|
-
|
51
|
-
|
52
|
-
node.style.padding = "0.03889em 0.03889em 0 0.03889em"
|
53
|
-
node.style.borderTop = "0.049em solid"
|
54
|
-
node.style.borderRight = "0.049em solid"
|
55
|
-
node.style.marginRight = "0.03889em"
|
58
|
+
node.setAttribute("notation", "phasorangle")
|
59
|
+
node.classes.push("phasor-bottom")
|
60
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["phasor-angle"]))
|
56
61
|
break
|
57
|
-
case "\\
|
58
|
-
node.
|
59
|
-
node.
|
60
|
-
node.
|
61
|
-
|
62
|
+
case "\\textcircled":
|
63
|
+
node.setAttribute("notation", "circle")
|
64
|
+
node.classes.push("circle-pad")
|
65
|
+
node.children.push(new mathMLTree.MathNode("mrow", [], ["textcircle"]))
|
66
|
+
break
|
67
|
+
case "\\angl":
|
68
|
+
node.setAttribute("notation", "actuarial")
|
69
|
+
node.classes.push("actuarial")
|
62
70
|
break
|
63
71
|
case "\\boxed":
|
64
72
|
// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} from amsmath.sty
|
65
|
-
node.
|
73
|
+
node.setAttribute("notation", "box")
|
74
|
+
node.classes.push("tml-box")
|
66
75
|
node.setAttribute("scriptlevel", "0")
|
67
76
|
node.setAttribute("displaystyle", "true")
|
68
77
|
break
|
69
78
|
case "\\fbox":
|
70
|
-
node.
|
79
|
+
node.setAttribute("notation", "box")
|
80
|
+
node.classes.push("tml-fbox")
|
71
81
|
break
|
72
82
|
case "\\fcolorbox":
|
73
83
|
case "\\colorbox": {
|
@@ -80,14 +90,11 @@ const mathmlBuilder = (group, style) => {
|
|
80
90
|
const style = { padding: "3pt 0 3pt 0" }
|
81
91
|
|
82
92
|
if (group.label === "\\fcolorbox") {
|
83
|
-
style.border = "0.
|
93
|
+
style.border = "0.0667em solid " + String(group.borderColor)
|
84
94
|
}
|
85
95
|
node.style = style
|
86
96
|
break
|
87
97
|
}
|
88
|
-
case "\\xcancel":
|
89
|
-
node.classes.push("tml-xcancel")
|
90
|
-
break
|
91
98
|
}
|
92
99
|
if (group.backgroundColor) {
|
93
100
|
node.setAttribute("mathbackground", group.backgroundColor);
|
@@ -180,8 +187,8 @@ defineFunction({
|
|
180
187
|
|
181
188
|
defineFunction({
|
182
189
|
type: "enclose",
|
183
|
-
names: ["\\angl", "\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\overline",
|
184
|
-
|
190
|
+
names: ["\\angl", "\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\overline",
|
191
|
+
"\\boxed", "\\longdiv", "\\phase"],
|
185
192
|
props: {
|
186
193
|
numArgs: 1
|
187
194
|
},
|
@@ -215,3 +222,25 @@ defineFunction({
|
|
215
222
|
},
|
216
223
|
mathmlBuilder
|
217
224
|
});
|
225
|
+
|
226
|
+
|
227
|
+
defineFunction({
|
228
|
+
type: "enclose",
|
229
|
+
names: ["\\textcircled"],
|
230
|
+
props: {
|
231
|
+
numArgs: 1,
|
232
|
+
argTypes: ["text"],
|
233
|
+
allowedInArgument: true,
|
234
|
+
allowedInText: true
|
235
|
+
},
|
236
|
+
handler({ parser, funcName }, args) {
|
237
|
+
const body = args[0];
|
238
|
+
return {
|
239
|
+
type: "enclose",
|
240
|
+
mode: parser.mode,
|
241
|
+
label: funcName,
|
242
|
+
body
|
243
|
+
};
|
244
|
+
},
|
245
|
+
mathmlBuilder
|
246
|
+
});
|