temml 0.10.0 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- 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 = {};
|