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 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
- Chromium will support MathML in release 109 [early in 2023](https://chromiumdash.appspot.com/schedule), At that point, all the major browsers will support MathML and Temml will become the most lightweight way to render math in a browser.
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 mutliple times", function() {
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 },
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable */
2
- /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
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 anaylsis
1699
+ // Helpers for code analysis
1700
1700
  // Will show type error at calling position
1701
1701
  //
1702
1702
  /** @param {number} a */
@@ -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;
@@ -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;
@@ -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, "none"); // "none" | "tex" | "="
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 iteself).
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
- * We want the expression to render with soft line breaks after each top-level binary or
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 cooresponding MathML tree. The main
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$1(next),
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$1(next),
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
- const dels = ["}", "\\left", "\\middle", "\\right"];
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
- const node = expression[i];
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
- wrapper.setAttribute("mathvariant", "normal");
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: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
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 anaylsis
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 will be returned as an array,
11010
- * also in reverse order.
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 next token will be returned without removing it
11013
- * from the stack. This case can be detected by a `Token` return value
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 topToken;
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
- const expanded = this.expandOnce();
11087
- // expandOnce returns Token if and only if it's fully expanded.
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 (expanded.treatAsRelax) {
11091
- expanded.text = "\\relax";
11095
+ if (token.treatAsRelax) {
11096
+ token.text = "\\relax";
11092
11097
  }
11093
- return this.stack.pop(); // === expanded
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
- const expanded = this.expandOnce(true); // expand only expandable tokens
11120
- // expandOnce returns Token if and only if it's fully expanded.
11121
- if (expanded instanceof Token) {
11122
- if (expanded.treatAsRelax) {
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
- expanded.noexpand = false;
11125
- expanded.treatAsRelax = false;
11129
+ token.noexpand = false;
11130
+ token.treatAsRelax = false;
11126
11131
  }
11127
- output.push(this.stack.pop());
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 precendence han infix
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.0";
12973
+ const version = "0.10.3";
12965
12974
 
12966
12975
  function postProcess(block) {
12967
12976
  const labelMap = {};