temml 0.10.0 → 0.10.3
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 +3 -4
- package/contrib/auto-render/test/auto-render-spec.js +1 -1
- package/contrib/mhchem/mhchem.js +2 -2
- package/dist/Temml-Asana.css +17 -1
- package/dist/Temml-Latin-Modern.css +17 -5
- package/dist/Temml-Libertinus.css +17 -5
- package/dist/Temml-Local.css +16 -0
- package/dist/Temml-STIX2.css +16 -0
- package/dist/temml.cjs +67 -58
- package/dist/temml.js +65 -56
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +67 -58
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +2 -1
- package/src/MacroExpander.js +20 -21
- package/src/Parser.js +8 -3
- package/src/Settings.js +1 -1
- package/src/buildMathML.js +4 -13
- package/src/functions/delimsizing.js +5 -0
- package/src/functions/op.js +1 -5
- package/src/functions/operatorname.js +10 -8
- package/src/functions/supsub.js +7 -0
- package/src/linebreaking.js +3 -1
- package/src/mathMLTree.js +1 -1
- package/src/postProcess.js +1 -1
- package/src/symbols.js +5 -2
package/README.md
CHANGED
@@ -7,11 +7,10 @@
|
|
7
7
|
| KaTeX | 280 KB |
|
8
8
|
| TeXZilla | 168 KB |
|
9
9
|
|
10
|
-
As a futher advantage, Temml can use local system fonts. The minimum Temml installation serves a font file that is only 12kb.
|
10
|
+
As a futher advantage, Temml can use local system fonts. The minimum Temml installation serves a font file that is only 12kb. Sadly, Chromium has some rendering bugs when using system fonts. It
|
11
|
+
work better with the Latin Modern font, a 380 KB file.
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
Temml’s coverage of LaTeX functions is as good as MathJax, slightly better than KaTeX 0.13.0 and substantially better than TeXZilla. See a [detailed coverage comparison](https://temml.org/docs/en/comparison.html).
|
13
|
+
Temml’s coverage of LaTeX functions is as good as MathJax, slightly better than KaTeX 0.16.0 and substantially better than TeXZilla. See a [detailed coverage comparison](https://temml.org/docs/en/comparison.html).
|
15
14
|
|
16
15
|
Temml's test suite includes many rendered examples, including the Temml [supported functions page](https://temml.org/docs/en/supported.html) and tests from [Mozilla](https://temml.org/tests/mozilla-tests.html), [Wikipedia](https://temml.org/tests/wiki-tests.html), [mhchem](https://temml.org/tests/mhchem-tests.html), and [LaTeXML](https://temml.org/tests/LaTeXML-tests.html).
|
17
16
|
|
@@ -104,7 +104,7 @@ describe("A delimiter splitter", function() {
|
|
104
104
|
]);
|
105
105
|
});
|
106
106
|
|
107
|
-
it("splits
|
107
|
+
it("splits multiple times", function() {
|
108
108
|
expect("hello ( world ) boo ( more ) stuff").toSplitInto("(", ")", [
|
109
109
|
{ type: "text", data: "hello " },
|
110
110
|
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
package/contrib/mhchem/mhchem.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/* eslint-disable */
|
2
|
-
/* -*- Mode:
|
2
|
+
/* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
|
3
3
|
/* vim: set ts=2 et sw=2 tw=80: */
|
4
4
|
|
5
5
|
/*************************************************************
|
@@ -1696,7 +1696,7 @@ temml.__defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\
|
|
1696
1696
|
};
|
1697
1697
|
|
1698
1698
|
//
|
1699
|
-
// Helpers for code
|
1699
|
+
// Helpers for code analysis
|
1700
1700
|
// Will show type error at calling position
|
1701
1701
|
//
|
1702
1702
|
/** @param {number} a */
|
package/dist/Temml-Asana.css
CHANGED
@@ -35,7 +35,7 @@ mtext {
|
|
35
35
|
}
|
36
36
|
|
37
37
|
math {
|
38
|
-
font-family: Asana Math;
|
38
|
+
font-family: Asana Math, math;
|
39
39
|
}
|
40
40
|
|
41
41
|
*.mathcal,
|
@@ -43,6 +43,22 @@ mo.tml-prime {
|
|
43
43
|
font-feature-settings: 'salt';
|
44
44
|
}
|
45
45
|
|
46
|
+
/* flex-wrap for line-breaking in Chromium */
|
47
|
+
math {
|
48
|
+
display: inline-flex;
|
49
|
+
flex-wrap: wrap;
|
50
|
+
align-items: baseline;
|
51
|
+
}
|
52
|
+
math > mrow {
|
53
|
+
padding: 0.5ex 0ex;
|
54
|
+
}
|
55
|
+
|
56
|
+
/* Avoid flex-wrap in Firefox */
|
57
|
+
@supports (-moz-appearance:meterbar) and (display:flex) {
|
58
|
+
math { display: inline; }
|
59
|
+
math > mrow { padding: 0 }
|
60
|
+
}
|
61
|
+
|
46
62
|
/* AMS environment auto-numbering via CSS counter. */
|
47
63
|
.tml-eqn::before {
|
48
64
|
counter-increment: tmlEqnNo;
|
@@ -40,12 +40,8 @@ math * {
|
|
40
40
|
border-color: currentColor;
|
41
41
|
}
|
42
42
|
|
43
|
-
.latin-modern math {
|
44
|
-
font-family: "Latin Modern Math", "Times New Roman", math;
|
45
|
-
}
|
46
|
-
|
47
43
|
math {
|
48
|
-
font-family: Latin Modern Math;
|
44
|
+
font-family: "Latin Modern Math", "Times New Roman", math;
|
49
45
|
}
|
50
46
|
|
51
47
|
*.mathscr {
|
@@ -56,6 +52,22 @@ mo.tml-prime {
|
|
56
52
|
font-family: Temml;
|
57
53
|
}
|
58
54
|
|
55
|
+
/* flex-wrap for line-breaking in Chromium */
|
56
|
+
math {
|
57
|
+
display: inline-flex;
|
58
|
+
flex-wrap: wrap;
|
59
|
+
align-items: baseline;
|
60
|
+
}
|
61
|
+
math > mrow {
|
62
|
+
padding: 0.5ex 0ex;
|
63
|
+
}
|
64
|
+
|
65
|
+
/* Avoid flex-wrap in Firefox */
|
66
|
+
@supports (-moz-appearance:meterbar) and (display:flex) {
|
67
|
+
math { display: inline; }
|
68
|
+
math > mrow { padding: 0 }
|
69
|
+
}
|
70
|
+
|
59
71
|
/* AMS environment auto-numbering via CSS counter. */
|
60
72
|
.tml-eqn::before {
|
61
73
|
counter-increment: tmlEqnNo;
|
@@ -38,12 +38,8 @@ math * {
|
|
38
38
|
border-color: currentColor;
|
39
39
|
}
|
40
40
|
|
41
|
-
.libertinus math {
|
42
|
-
font-family: "Libertinus Math", "Times New Roman", math;
|
43
|
-
}
|
44
|
-
|
45
41
|
math {
|
46
|
-
font-family: Libertinus Math;
|
42
|
+
font-family: Libertinus Math, math;
|
47
43
|
}
|
48
44
|
|
49
45
|
*.mathcal {
|
@@ -54,6 +50,22 @@ mo.tml-prime {
|
|
54
50
|
font-feature-settings: 'ssty';
|
55
51
|
}
|
56
52
|
|
53
|
+
/* flex-wrap for line-breaking in Chromium */
|
54
|
+
math {
|
55
|
+
display: inline-flex;
|
56
|
+
flex-wrap: wrap;
|
57
|
+
align-items: baseline;
|
58
|
+
}
|
59
|
+
math > mrow {
|
60
|
+
padding: 0.5ex 0ex;
|
61
|
+
}
|
62
|
+
|
63
|
+
/* Avoid flex-wrap in Firefox */
|
64
|
+
@supports (-moz-appearance:meterbar) and (display:flex) {
|
65
|
+
math { display: inline; }
|
66
|
+
math > mrow { padding: 0 }
|
67
|
+
}
|
68
|
+
|
57
69
|
/* AMS environment auto-numbering via CSS counter. */
|
58
70
|
.tml-eqn::before {
|
59
71
|
counter-increment: tmlEqnNo;
|
package/dist/Temml-Local.css
CHANGED
@@ -36,6 +36,22 @@ mo.tml-prime {
|
|
36
36
|
font-family: Temml;
|
37
37
|
}
|
38
38
|
|
39
|
+
/* flex-wrap for line-breaking in Chromium */
|
40
|
+
math {
|
41
|
+
display: inline-flex;
|
42
|
+
flex-wrap: wrap;
|
43
|
+
align-items: baseline;
|
44
|
+
}
|
45
|
+
math > mrow {
|
46
|
+
padding: 0.5ex 0ex;
|
47
|
+
}
|
48
|
+
|
49
|
+
/* Avoid flex-wrap in Firefox */
|
50
|
+
@supports (-moz-appearance:meterbar) and (display:flex) {
|
51
|
+
math { display: inline; }
|
52
|
+
math > mrow { padding: 0 }
|
53
|
+
}
|
54
|
+
|
39
55
|
/* AMS environment auto-numbering via CSS counter. */
|
40
56
|
.tml-eqn::before {
|
41
57
|
counter-increment: tmlEqnNo;
|
package/dist/Temml-STIX2.css
CHANGED
@@ -44,6 +44,22 @@ mo.tml-prime {
|
|
44
44
|
font-feature-settings: 'ss04';
|
45
45
|
}
|
46
46
|
|
47
|
+
/* flex-wrap for line-breaking in Chromium */
|
48
|
+
math {
|
49
|
+
display: inline-flex;
|
50
|
+
flex-wrap: wrap;
|
51
|
+
align-items: baseline;
|
52
|
+
}
|
53
|
+
math > mrow {
|
54
|
+
padding: 0.5ex 0ex;
|
55
|
+
}
|
56
|
+
|
57
|
+
/* Avoid flex-wrap in Firefox */
|
58
|
+
@supports (-moz-appearance:meterbar) and (display:flex) {
|
59
|
+
math { display: inline; }
|
60
|
+
math > mrow { padding: 0 }
|
61
|
+
}
|
62
|
+
|
47
63
|
/* AMS environment auto-numbering via CSS counter. */
|
48
64
|
.tml-eqn::before {
|
49
65
|
counter-increment: tmlEqnNo;
|
package/dist/temml.cjs
CHANGED
@@ -190,7 +190,7 @@ class Settings {
|
|
190
190
|
this.leqno = utils.deflt(options.leqno, false); // boolean
|
191
191
|
this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string
|
192
192
|
this.macros = options.macros || {};
|
193
|
-
this.wrap = utils.deflt(options.wrap, "
|
193
|
+
this.wrap = utils.deflt(options.wrap, "tex"); // "tex" | "="
|
194
194
|
this.xml = utils.deflt(options.xml, false); // boolean
|
195
195
|
this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean
|
196
196
|
this.strict = utils.deflt(options.strict, false); // boolean
|
@@ -668,7 +668,7 @@ class TextNode {
|
|
668
668
|
|
669
669
|
/**
|
670
670
|
* Converts the text node into a string
|
671
|
-
* (representing the text
|
671
|
+
* (representing the text itself).
|
672
672
|
*/
|
673
673
|
toText() {
|
674
674
|
return this.text;
|
@@ -845,7 +845,6 @@ defineSymbol(math, rel, "\u226a", "\\ll", true);
|
|
845
845
|
defineSymbol(math, rel, "\u226b", "\\gg", true);
|
846
846
|
defineSymbol(math, rel, "\u224d", "\\asymp", true);
|
847
847
|
defineSymbol(math, rel, "\u2225", "\\parallel");
|
848
|
-
defineSymbol(math, rel, "\u22c8", "\\bowtie", true);
|
849
848
|
defineSymbol(math, rel, "\u2323", "\\smile", true);
|
850
849
|
defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true);
|
851
850
|
defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true);
|
@@ -1162,7 +1161,6 @@ defineSymbol(math, rel, "\u22d9", "\\gggtr");
|
|
1162
1161
|
defineSymbol(math, bin, "\u22b2", "\\lhd");
|
1163
1162
|
defineSymbol(math, bin, "\u22b3", "\\rhd");
|
1164
1163
|
defineSymbol(math, rel, "\u2242", "\\eqsim", true);
|
1165
|
-
defineSymbol(math, rel, "\u22c8", "\\Join");
|
1166
1164
|
defineSymbol(math, rel, "\u2251", "\\Doteq", true);
|
1167
1165
|
defineSymbol(math, rel, "\u297d", "\\strictif", true);
|
1168
1166
|
defineSymbol(math, rel, "\u297c", "\\strictfi", true);
|
@@ -1188,6 +1186,11 @@ defineSymbol(math, bin, "\u22ba", "\\intercal", true);
|
|
1188
1186
|
defineSymbol(math, bin, "\u22d2", "\\doublecap");
|
1189
1187
|
defineSymbol(math, bin, "\u22d3", "\\doublecup");
|
1190
1188
|
defineSymbol(math, bin, "\u22a0", "\\boxtimes", true);
|
1189
|
+
defineSymbol(math, bin, "\u22c8", "\\bowtie", true);
|
1190
|
+
defineSymbol(math, bin, "\u22c8", "\\Join");
|
1191
|
+
defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
|
1192
|
+
defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
|
1193
|
+
defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
|
1191
1194
|
|
1192
1195
|
// AMS Arrows
|
1193
1196
|
// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
|
@@ -1746,10 +1749,12 @@ for (let i = 0; i < 10; i++) {
|
|
1746
1749
|
* Then the top level of a <math> element can be occupied by <mrow> elements, and the browser
|
1747
1750
|
* will break after a <mrow> if the expression extends beyond the container limit.
|
1748
1751
|
*
|
1749
|
-
*
|
1752
|
+
* The default is for soft line breaks after each top-level binary or
|
1750
1753
|
* relational operator, per TeXbook p. 173. So we gather the expression into <mrow>s so that
|
1751
1754
|
* each <mrow> ends in a binary or relational operator.
|
1752
1755
|
*
|
1756
|
+
* An option is for soft line breaks before an "=" sign. That changes the <mrow>s.
|
1757
|
+
*
|
1753
1758
|
* Soft line breaks will not work in Chromium and Safari, only Firefox.
|
1754
1759
|
*
|
1755
1760
|
* Hopefully browsers will someday do their own linebreaking and we will be able to delete
|
@@ -1892,7 +1897,7 @@ function setLineBreaks(expression, wrapMode, isDisplayMode, color) {
|
|
1892
1897
|
}
|
1893
1898
|
|
1894
1899
|
/**
|
1895
|
-
* This file converts a parse tree into a
|
1900
|
+
* This file converts a parse tree into a corresponding MathML tree. The main
|
1896
1901
|
* entry point is the `buildMathML` function, which takes a parse tree from the
|
1897
1902
|
* parser.
|
1898
1903
|
*/
|
@@ -2095,18 +2100,6 @@ function buildMathML(tree, texExpression, style, settings) {
|
|
2095
2100
|
wrapper = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
|
2096
2101
|
}
|
2097
2102
|
|
2098
|
-
if (wrap !== "none" && wrapper.children.length > 1) {
|
2099
|
-
const maths = [];
|
2100
|
-
for (let i = 0; i < wrapper.children.length; i++) {
|
2101
|
-
const math = new mathMLTree.MathNode("math", [wrapper.children[i]]);
|
2102
|
-
if (settings.xml) {
|
2103
|
-
math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
|
2104
|
-
}
|
2105
|
-
maths.push(math);
|
2106
|
-
}
|
2107
|
-
return mathMLTree.newDocumentFragment(maths)
|
2108
|
-
}
|
2109
|
-
|
2110
2103
|
const math = new mathMLTree.MathNode("math", [wrapper]);
|
2111
2104
|
|
2112
2105
|
if (settings.xml) {
|
@@ -2114,6 +2107,9 @@ function buildMathML(tree, texExpression, style, settings) {
|
|
2114
2107
|
}
|
2115
2108
|
if (settings.displayMode) {
|
2116
2109
|
math.setAttribute("display", "block");
|
2110
|
+
math.style.display = math.children.length === 1 && math.children[0].type === "mtable"
|
2111
|
+
? "inline"
|
2112
|
+
: "inline-block";
|
2117
2113
|
}
|
2118
2114
|
return math;
|
2119
2115
|
}
|
@@ -3523,6 +3519,11 @@ const delimiters = [
|
|
3523
3519
|
"."
|
3524
3520
|
];
|
3525
3521
|
|
3522
|
+
// Export isDelimiter for benefit of parser.
|
3523
|
+
const dels = ["}", "\\left", "\\middle", "\\right"];
|
3524
|
+
const isDelimiter = str => str.length > 0 &&
|
3525
|
+
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str));
|
3526
|
+
|
3526
3527
|
// Metrics of the different sizes. Found by looking at TeX's output of
|
3527
3528
|
// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
|
3528
3529
|
// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
|
@@ -6205,10 +6206,6 @@ const noSuccessor = ["\\smallint"];
|
|
6205
6206
|
// Math operators (e.g. \sin) need a space between these types and themselves:
|
6206
6207
|
const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
|
6207
6208
|
|
6208
|
-
const dels$1 = ["}", "\\left", "\\middle", "\\right"];
|
6209
|
-
const isDelimiter$1 = str => str.length > 0 &&
|
6210
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels$1.includes(str));
|
6211
|
-
|
6212
6209
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
6213
6210
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
6214
6211
|
|
@@ -6429,7 +6426,7 @@ defineFunction({
|
|
6429
6426
|
parentIsSupSub: false,
|
6430
6427
|
symbol: false,
|
6431
6428
|
stack: false,
|
6432
|
-
isFollowedByDelimiter: isDelimiter
|
6429
|
+
isFollowedByDelimiter: isDelimiter(next),
|
6433
6430
|
needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
|
6434
6431
|
name: funcName
|
6435
6432
|
};
|
@@ -6454,7 +6451,7 @@ defineFunction({
|
|
6454
6451
|
parentIsSupSub: false,
|
6455
6452
|
symbol: false,
|
6456
6453
|
stack: false,
|
6457
|
-
isFollowedByDelimiter: isDelimiter
|
6454
|
+
isFollowedByDelimiter: isDelimiter(next),
|
6458
6455
|
needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
|
6459
6456
|
name: funcName
|
6460
6457
|
};
|
@@ -6540,11 +6537,7 @@ function defineMacro(name, body) {
|
|
6540
6537
|
_macros[name] = body;
|
6541
6538
|
}
|
6542
6539
|
|
6543
|
-
|
6544
|
-
const isDelimiter = str => str.length > 0 &&
|
6545
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str));
|
6546
|
-
|
6547
|
-
// NOTE: Unlike most builders, this one handles not only
|
6540
|
+
// NOTE: Unlike most builders, this one handles not only
|
6548
6541
|
// "operatorname", but also "supsub" since \operatorname* can
|
6549
6542
|
// affect super/subscripting.
|
6550
6543
|
|
@@ -6554,8 +6547,12 @@ const mathmlBuilder$1 = (group, style) => {
|
|
6554
6547
|
// Is expression a string or has it something like a fraction?
|
6555
6548
|
let isAllString = true; // default
|
6556
6549
|
for (let i = 0; i < expression.length; i++) {
|
6557
|
-
|
6550
|
+
let node = expression[i];
|
6558
6551
|
if (node instanceof mathMLTree.MathNode) {
|
6552
|
+
if (node.type === "mrow" && node.children.length === 1 &&
|
6553
|
+
node.children[0] instanceof mathMLTree.MathNode) {
|
6554
|
+
node = node.children[0];
|
6555
|
+
}
|
6559
6556
|
switch (node.type) {
|
6560
6557
|
case "mi":
|
6561
6558
|
case "mn":
|
@@ -6613,7 +6610,9 @@ const mathmlBuilder$1 = (group, style) => {
|
|
6613
6610
|
let wrapper;
|
6614
6611
|
if (isAllString) {
|
6615
6612
|
wrapper = new mathMLTree.MathNode("mi", expression);
|
6616
|
-
|
6613
|
+
if (expression[0].text.length === 1) {
|
6614
|
+
wrapper.setAttribute("mathvariant", "normal");
|
6615
|
+
}
|
6617
6616
|
} else {
|
6618
6617
|
wrapper = new mathMLTree.MathNode("mrow", expression);
|
6619
6618
|
}
|
@@ -7151,6 +7150,7 @@ defineFunctionBuilders({
|
|
7151
7150
|
let isOver;
|
7152
7151
|
let isSup;
|
7153
7152
|
let appendApplyFunction = false;
|
7153
|
+
let appendSpace = false;
|
7154
7154
|
let needsLeadingSpace = false;
|
7155
7155
|
|
7156
7156
|
if (group.base && group.base.type === "horizBrace") {
|
@@ -7165,6 +7165,7 @@ defineFunctionBuilders({
|
|
7165
7165
|
(group.base.type === "op" || group.base.type === "operatorname")) {
|
7166
7166
|
group.base.parentIsSupSub = true;
|
7167
7167
|
appendApplyFunction = !group.base.symbol;
|
7168
|
+
appendSpace = appendApplyFunction && !group.isFollowedByDelimiter;
|
7168
7169
|
needsLeadingSpace = group.base.needsLeadingSpace;
|
7169
7170
|
}
|
7170
7171
|
|
@@ -7252,6 +7253,11 @@ defineFunctionBuilders({
|
|
7252
7253
|
} else {
|
7253
7254
|
node = mathMLTree.newDocumentFragment([node, operator]);
|
7254
7255
|
}
|
7256
|
+
if (appendSpace) {
|
7257
|
+
const space = new mathMLTree.MathNode("mspace");
|
7258
|
+
space.setAttribute("width", "0.1667em"); // thin space.
|
7259
|
+
node.children.push(space);
|
7260
|
+
}
|
7255
7261
|
} else if (symbolRegEx.test(nodeType)) {
|
7256
7262
|
// Wrap in a <mrow>. Otherwise Firefox stretchy parens will not stretch to include limits.
|
7257
7263
|
node = new mathMLTree.MathNode("mrow", [node]);
|
@@ -8884,7 +8890,7 @@ defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{
|
|
8884
8890
|
defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}");
|
8885
8891
|
|
8886
8892
|
/* eslint-disable */
|
8887
|
-
/* -*- Mode:
|
8893
|
+
/* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
|
8888
8894
|
/* vim: set ts=2 et sw=2 tw=80: */
|
8889
8895
|
|
8890
8896
|
/*************************************************************
|
@@ -10581,7 +10587,7 @@ defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap
|
|
10581
10587
|
};
|
10582
10588
|
|
10583
10589
|
//
|
10584
|
-
// Helpers for code
|
10590
|
+
// Helpers for code analysis
|
10585
10591
|
// Will show type error at calling position
|
10586
10592
|
//
|
10587
10593
|
/** @param {number} a */
|
@@ -11006,15 +11012,15 @@ class MacroExpander {
|
|
11006
11012
|
* Expand the next token only once if possible.
|
11007
11013
|
*
|
11008
11014
|
* If the token is expanded, the resulting tokens will be pushed onto
|
11009
|
-
* the stack in reverse order and
|
11010
|
-
*
|
11015
|
+
* the stack in reverse order, and the number of such tokens will be
|
11016
|
+
* returned. This number might be zero or positive.
|
11011
11017
|
*
|
11012
|
-
* If not, the
|
11013
|
-
*
|
11014
|
-
* instead of an `Array` return value.
|
11018
|
+
* If not, the return value is `false`, and the next token remains at the
|
11019
|
+
* top of the stack.
|
11015
11020
|
*
|
11016
11021
|
* In either case, the next token will be on the top of the stack,
|
11017
|
-
* or the stack will be empty
|
11022
|
+
* or the stack will be empty (in case of empty expansion
|
11023
|
+
* and no other tokens).
|
11018
11024
|
*
|
11019
11025
|
* Used to implement `expandAfterFuture` and `expandNextToken`.
|
11020
11026
|
*
|
@@ -11030,7 +11036,7 @@ class MacroExpander {
|
|
11030
11036
|
throw new ParseError("Undefined control sequence: " + name);
|
11031
11037
|
}
|
11032
11038
|
this.pushToken(topToken);
|
11033
|
-
return
|
11039
|
+
return false;
|
11034
11040
|
}
|
11035
11041
|
this.expansionCount++;
|
11036
11042
|
if (this.expansionCount > this.settings.maxExpand) {
|
@@ -11064,7 +11070,7 @@ class MacroExpander {
|
|
11064
11070
|
}
|
11065
11071
|
// Concatenate expansion onto top of stack.
|
11066
11072
|
this.pushTokens(tokens);
|
11067
|
-
return tokens;
|
11073
|
+
return tokens.length;
|
11068
11074
|
}
|
11069
11075
|
|
11070
11076
|
/**
|
@@ -11083,14 +11089,13 @@ class MacroExpander {
|
|
11083
11089
|
*/
|
11084
11090
|
expandNextToken() {
|
11085
11091
|
for (;;) {
|
11086
|
-
|
11087
|
-
|
11088
|
-
if (expanded instanceof Token) {
|
11092
|
+
if (this.expandOnce() === false) { // fully expanded
|
11093
|
+
const token = this.stack.pop();
|
11089
11094
|
// The token after \noexpand is interpreted as if its meaning were ‘\relax’
|
11090
|
-
if (
|
11091
|
-
|
11095
|
+
if (token.treatAsRelax) {
|
11096
|
+
token.text = "\\relax";
|
11092
11097
|
}
|
11093
|
-
return
|
11098
|
+
return token
|
11094
11099
|
}
|
11095
11100
|
}
|
11096
11101
|
|
@@ -11116,15 +11121,15 @@ class MacroExpander {
|
|
11116
11121
|
const oldStackLength = this.stack.length;
|
11117
11122
|
this.pushTokens(tokens);
|
11118
11123
|
while (this.stack.length > oldStackLength) {
|
11119
|
-
|
11120
|
-
|
11121
|
-
|
11122
|
-
if (
|
11124
|
+
// Expand only expandable tokens
|
11125
|
+
if (this.expandOnce(true) === false) { // fully expanded
|
11126
|
+
const token = this.stack.pop();
|
11127
|
+
if (token.treatAsRelax) {
|
11123
11128
|
// the expansion of \noexpand is the token itself
|
11124
|
-
|
11125
|
-
|
11129
|
+
token.noexpand = false;
|
11130
|
+
token.treatAsRelax = false;
|
11126
11131
|
}
|
11127
|
-
output.push(
|
11132
|
+
output.push(token);
|
11128
11133
|
}
|
11129
11134
|
}
|
11130
11135
|
return output;
|
@@ -11952,7 +11957,7 @@ class Parser {
|
|
11952
11957
|
* Parses an "expression", which is a list of atoms.
|
11953
11958
|
*
|
11954
11959
|
* `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
|
11955
|
-
* happens when functions have higher
|
11960
|
+
* happens when functions have higher precedence han infix
|
11956
11961
|
* nodes in implicit parses.
|
11957
11962
|
*
|
11958
11963
|
* `breakOnTokenText`: The text of the token that the expression should end
|
@@ -12203,12 +12208,16 @@ class Parser {
|
|
12203
12208
|
return base
|
12204
12209
|
} else {
|
12205
12210
|
// We got either a superscript or subscript, create a supsub
|
12211
|
+
const isFollowedByDelimiter = (!base || base.type !== "op" && base.type !== "operatorname")
|
12212
|
+
? undefined
|
12213
|
+
: isDelimiter(this.nextToken.text);
|
12206
12214
|
return {
|
12207
12215
|
type: "supsub",
|
12208
12216
|
mode: this.mode,
|
12209
12217
|
base: base,
|
12210
12218
|
sup: superscript,
|
12211
|
-
sub: subscript
|
12219
|
+
sub: subscript,
|
12220
|
+
isFollowedByDelimiter
|
12212
12221
|
}
|
12213
12222
|
}
|
12214
12223
|
} else {
|
@@ -12369,7 +12378,7 @@ class Parser {
|
|
12369
12378
|
while (true) {
|
12370
12379
|
const ch = this.fetch().text;
|
12371
12380
|
// \ufe0e is the Unicode variation selector to supress emoji. Ignore it.
|
12372
|
-
if (ch === " " || ch === "\ufe0e") {
|
12381
|
+
if (ch === " " || ch === "\u00a0" || ch === "\ufe0e") {
|
12373
12382
|
this.consume();
|
12374
12383
|
} else {
|
12375
12384
|
break
|
@@ -12961,7 +12970,7 @@ class Style {
|
|
12961
12970
|
* https://mit-license.org/
|
12962
12971
|
*/
|
12963
12972
|
|
12964
|
-
const version = "0.10.
|
12973
|
+
const version = "0.10.3";
|
12965
12974
|
|
12966
12975
|
function postProcess(block) {
|
12967
12976
|
const labelMap = {};
|