temml 0.10.19 → 0.10.20

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.
@@ -47,6 +47,39 @@ mo.tml-prime {
47
47
  font-feature-settings: 'salt';
48
48
  }
49
49
 
50
+ mrow.tml-cancel {
51
+ background: linear-gradient(to top left,
52
+ rgba(0,0,0,0) 0%,
53
+ rgba(0,0,0,0) calc(50% - 0.06em),
54
+ rgba(0,0,0,1) 50%,
55
+ rgba(0,0,0,0) calc(50% + 0.06em),
56
+ rgba(0,0,0,0) 100%);
57
+ }
58
+
59
+ mrow.tml-bcancel {
60
+ background: linear-gradient(to top right,
61
+ rgba(0,0,0,0) 0%,
62
+ rgba(0,0,0,0) calc(50% - 0.06em),
63
+ rgba(0,0,0,1) 50%,
64
+ rgba(0,0,0,0) calc(50% + 0.06em),
65
+ rgba(0,0,0,0) 100%);
66
+ }
67
+
68
+ mrow.tml-xcancel {
69
+ background: linear-gradient(to top left,
70
+ rgba(0,0,0,0) 0%,
71
+ rgba(0,0,0,0) calc(50% - 0.06em),
72
+ rgba(0,0,0,1) 50%,
73
+ rgba(0,0,0,0) calc(50% + 0.06em),
74
+ rgba(0,0,0,0) 100%),
75
+ linear-gradient(to top right,
76
+ rgba(0,0,0,0) 0%,
77
+ rgba(0,0,0,0) calc(50% - 0.06em),
78
+ rgba(0,0,0,1) 50%,
79
+ rgba(0,0,0,0) calc(50% + 0.06em),
80
+ rgba(0,0,0,0) 100%)
81
+ }
82
+
50
83
  /* Prevent f' from overlapping in Chromium */
51
84
  mo.prime-pad {
52
85
  padding-left: 0.08em;
@@ -57,6 +57,39 @@ mo.tml-prime {
57
57
  font-family: Temml;
58
58
  }
59
59
 
60
+ mrow.tml-cancel {
61
+ background: linear-gradient(to top left,
62
+ rgba(0,0,0,0) 0%,
63
+ rgba(0,0,0,0) calc(50% - 0.06em),
64
+ rgba(0,0,0,1) 50%,
65
+ rgba(0,0,0,0) calc(50% + 0.06em),
66
+ rgba(0,0,0,0) 100%);
67
+ }
68
+
69
+ mrow.tml-bcancel {
70
+ background: linear-gradient(to top right,
71
+ rgba(0,0,0,0) 0%,
72
+ rgba(0,0,0,0) calc(50% - 0.06em),
73
+ rgba(0,0,0,1) 50%,
74
+ rgba(0,0,0,0) calc(50% + 0.06em),
75
+ rgba(0,0,0,0) 100%);
76
+ }
77
+
78
+ mrow.tml-xcancel {
79
+ background: linear-gradient(to top left,
80
+ rgba(0,0,0,0) 0%,
81
+ rgba(0,0,0,0) calc(50% - 0.06em),
82
+ rgba(0,0,0,1) 50%,
83
+ rgba(0,0,0,0) calc(50% + 0.06em),
84
+ rgba(0,0,0,0) 100%),
85
+ linear-gradient(to top right,
86
+ rgba(0,0,0,0) 0%,
87
+ rgba(0,0,0,0) calc(50% - 0.06em),
88
+ rgba(0,0,0,1) 50%,
89
+ rgba(0,0,0,0) calc(50% + 0.06em),
90
+ rgba(0,0,0,0) 100%)
91
+ }
92
+
60
93
  /* Prevent f' from overlapping in Chromium */
61
94
  mo.prime-pad {
62
95
  padding-left: 0.08em;
@@ -54,6 +54,39 @@ mo.tml-prime {
54
54
  font-feature-settings: 'ssty';
55
55
  }
56
56
 
57
+ mrow.tml-cancel {
58
+ background: linear-gradient(to top left,
59
+ rgba(0,0,0,0) 0%,
60
+ rgba(0,0,0,0) calc(50% - 0.06em),
61
+ rgba(0,0,0,1) 50%,
62
+ rgba(0,0,0,0) calc(50% + 0.06em),
63
+ rgba(0,0,0,0) 100%);
64
+ }
65
+
66
+ mrow.tml-bcancel {
67
+ background: linear-gradient(to top right,
68
+ rgba(0,0,0,0) 0%,
69
+ rgba(0,0,0,0) calc(50% - 0.06em),
70
+ rgba(0,0,0,1) 50%,
71
+ rgba(0,0,0,0) calc(50% + 0.06em),
72
+ rgba(0,0,0,0) 100%);
73
+ }
74
+
75
+ mrow.tml-xcancel {
76
+ background: linear-gradient(to top left,
77
+ rgba(0,0,0,0) 0%,
78
+ rgba(0,0,0,0) calc(50% - 0.06em),
79
+ rgba(0,0,0,1) 50%,
80
+ rgba(0,0,0,0) calc(50% + 0.06em),
81
+ rgba(0,0,0,0) 100%),
82
+ linear-gradient(to top right,
83
+ rgba(0,0,0,0) 0%,
84
+ rgba(0,0,0,0) calc(50% - 0.06em),
85
+ rgba(0,0,0,1) 50%,
86
+ rgba(0,0,0,0) calc(50% + 0.06em),
87
+ rgba(0,0,0,0) 100%)
88
+ }
89
+
57
90
  /* Prevent f' from overlapping in Chromium */
58
91
  mo.prime-pad {
59
92
  padding-left: 0.08em;
@@ -40,6 +40,39 @@ mo.tml-prime {
40
40
  font-family: Temml;
41
41
  }
42
42
 
43
+ mrow.tml-cancel {
44
+ background: linear-gradient(to top left,
45
+ rgba(0,0,0,0) 0%,
46
+ rgba(0,0,0,0) calc(50% - 0.06em),
47
+ rgba(0,0,0,1) 50%,
48
+ rgba(0,0,0,0) calc(50% + 0.06em),
49
+ rgba(0,0,0,0) 100%);
50
+ }
51
+
52
+ mrow.tml-bcancel {
53
+ background: linear-gradient(to top right,
54
+ rgba(0,0,0,0) 0%,
55
+ rgba(0,0,0,0) calc(50% - 0.06em),
56
+ rgba(0,0,0,1) 50%,
57
+ rgba(0,0,0,0) calc(50% + 0.06em),
58
+ rgba(0,0,0,0) 100%);
59
+ }
60
+
61
+ mrow.tml-xcancel {
62
+ background: linear-gradient(to top left,
63
+ rgba(0,0,0,0) 0%,
64
+ rgba(0,0,0,0) calc(50% - 0.06em),
65
+ rgba(0,0,0,1) 50%,
66
+ rgba(0,0,0,0) calc(50% + 0.06em),
67
+ rgba(0,0,0,0) 100%),
68
+ linear-gradient(to top right,
69
+ rgba(0,0,0,0) 0%,
70
+ rgba(0,0,0,0) calc(50% - 0.06em),
71
+ rgba(0,0,0,1) 50%,
72
+ rgba(0,0,0,0) calc(50% + 0.06em),
73
+ rgba(0,0,0,0) 100%)
74
+ }
75
+
43
76
  /* Prevent f' from overlapping in Chromium */
44
77
  mo.prime-pad {
45
78
  padding-left: 0.08em;
@@ -48,6 +48,39 @@ mo.tml-prime {
48
48
  font-feature-settings: 'ss04';
49
49
  }
50
50
 
51
+ mrow.tml-cancel {
52
+ background: linear-gradient(to top left,
53
+ rgba(0,0,0,0) 0%,
54
+ rgba(0,0,0,0) calc(50% - 0.06em),
55
+ rgba(0,0,0,1) 50%,
56
+ rgba(0,0,0,0) calc(50% + 0.06em),
57
+ rgba(0,0,0,0) 100%);
58
+ }
59
+
60
+ mrow.tml-bcancel {
61
+ background: linear-gradient(to top right,
62
+ rgba(0,0,0,0) 0%,
63
+ rgba(0,0,0,0) calc(50% - 0.06em),
64
+ rgba(0,0,0,1) 50%,
65
+ rgba(0,0,0,0) calc(50% + 0.06em),
66
+ rgba(0,0,0,0) 100%);
67
+ }
68
+
69
+ mrow.tml-xcancel {
70
+ background: linear-gradient(to top left,
71
+ rgba(0,0,0,0) 0%,
72
+ rgba(0,0,0,0) calc(50% - 0.06em),
73
+ rgba(0,0,0,1) 50%,
74
+ rgba(0,0,0,0) calc(50% + 0.06em),
75
+ rgba(0,0,0,0) 100%),
76
+ linear-gradient(to top right,
77
+ rgba(0,0,0,0) 0%,
78
+ rgba(0,0,0,0) calc(50% - 0.06em),
79
+ rgba(0,0,0,1) 50%,
80
+ rgba(0,0,0,0) calc(50% + 0.06em),
81
+ rgba(0,0,0,0) 100%)
82
+ }
83
+
51
84
  /* Prevent f' from overlapping in Chromium */
52
85
  mo.prime-pad {
53
86
  padding-left: 0.08em;
package/dist/temml.cjs CHANGED
@@ -2072,20 +2072,22 @@ const consolidateNumbers = expression => {
2072
2072
  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
2073
2073
  * unless the array has length 1. Always returns a single node.
2074
2074
  */
2075
- const makeRow = function(body) {
2075
+ const makeRow = function(body, semisimple = false) {
2076
2076
  if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
2077
2077
  return body[0];
2078
- } else {
2078
+ } else if (!semisimple) {
2079
2079
  // Suppress spacing on <mo> nodes at both ends of the row.
2080
2080
  if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
2081
2081
  body[0].attributes.lspace = "0em";
2082
+ body[0].attributes.rspace = "0em";
2082
2083
  }
2083
2084
  const end = body.length - 1;
2084
2085
  if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
2086
+ body[end].attributes.lspace = "0em";
2085
2087
  body[end].attributes.rspace = "0em";
2086
2088
  }
2087
- return new mathMLTree.MathNode("mrow", body);
2088
2089
  }
2090
+ return new mathMLTree.MathNode("mrow", body);
2089
2091
  };
2090
2092
 
2091
2093
  const isRel = item => {
@@ -2099,10 +2101,10 @@ const isRel = item => {
2099
2101
  * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
2100
2102
  * (2) Suppress spacing between two adjacent relations.
2101
2103
  */
2102
- const buildExpression = function(expression, style, isOrdgroup) {
2103
- if (expression.length === 1) {
2104
+ const buildExpression = function(expression, style, semisimple = false) {
2105
+ if (!semisimple && expression.length === 1) {
2104
2106
  const group = buildGroup$1(expression[0], style);
2105
- if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
2107
+ if (group instanceof MathNode && group.type === "mo") {
2106
2108
  // When TeX writers want to suppress spacing on an operator,
2107
2109
  // they often put the operator by itself inside braces.
2108
2110
  group.setAttribute("lspace", "0em");
@@ -2132,8 +2134,8 @@ const buildExpression = function(expression, style, isOrdgroup) {
2132
2134
  * Equivalent to buildExpression, but wraps the elements in an <mrow>
2133
2135
  * if there's more than one. Returns a single node instead of an array.
2134
2136
  */
2135
- const buildExpressionRow = function(expression, style, isOrdgroup) {
2136
- return makeRow(buildExpression(expression, style, isOrdgroup));
2137
+ const buildExpressionRow = function(expression, style, semisimple = false) {
2138
+ return makeRow(buildExpression(expression, style, semisimple), semisimple);
2137
2139
  };
2138
2140
 
2139
2141
  /**
@@ -2818,7 +2820,8 @@ function cdArrow(arrowChar, labels, parser) {
2818
2820
  const arrowGroup = {
2819
2821
  type: "ordgroup",
2820
2822
  mode: "math",
2821
- body: [leftLabel, sizedArrow, rightLabel]
2823
+ body: [leftLabel, sizedArrow, rightLabel],
2824
+ semisimple: true
2822
2825
  };
2823
2826
  return parser.callFunction("\\\\cdparent", [arrowGroup], []);
2824
2827
  }
@@ -3940,20 +3943,12 @@ const mathmlBuilder$8 = (group, style) => {
3940
3943
  node.style.borderBottom = "0.065em solid";
3941
3944
  break
3942
3945
  case "\\cancel":
3943
- node.style.background = `linear-gradient(to top left,
3944
- rgba(0,0,0,0) 0%,
3945
- rgba(0,0,0,0) calc(50% - 0.06em),
3946
- rgba(0,0,0,1) 50%,
3947
- rgba(0,0,0,0) calc(50% + 0.06em),
3948
- rgba(0,0,0,0) 100%);`;
3946
+ // We can't use an inline background-gradient. It does not work client-side.
3947
+ // So set a class and put the rule in the external CSS file.
3948
+ node.classes.push("tml-cancel");
3949
3949
  break
3950
3950
  case "\\bcancel":
3951
- node.style.background = `linear-gradient(to top right,
3952
- rgba(0,0,0,0) 0%,
3953
- rgba(0,0,0,0) calc(50% - 0.06em),
3954
- rgba(0,0,0,1) 50%,
3955
- rgba(0,0,0,0) calc(50% + 0.06em),
3956
- rgba(0,0,0,0) 100%);`;
3951
+ node.classes.push("tml-bcancel");
3957
3952
  break
3958
3953
  /*
3959
3954
  case "\\longdiv":
@@ -4000,18 +3995,7 @@ rgba(0,0,0,0) 100%);`;
4000
3995
  break
4001
3996
  }
4002
3997
  case "\\xcancel":
4003
- node.style.background = `linear-gradient(to top left,
4004
- rgba(0,0,0,0) 0%,
4005
- rgba(0,0,0,0) calc(50% - 0.06em),
4006
- rgba(0,0,0,1) 50%,
4007
- rgba(0,0,0,0) calc(50% + 0.06em),
4008
- rgba(0,0,0,0) 100%),
4009
- linear-gradient(to top right,
4010
- rgba(0,0,0,0) 0%,
4011
- rgba(0,0,0,0) calc(50% - 0.06em),
4012
- rgba(0,0,0,1) 50%,
4013
- rgba(0,0,0,0) calc(50% + 0.06em),
4014
- rgba(0,0,0,0) 100%);`;
3998
+ node.classes.push("tml-xcancel");
4015
3999
  break
4016
4000
  }
4017
4001
  if (group.backgroundColor) {
@@ -4209,7 +4193,7 @@ const getTag = (group, style, rowNum) => {
4209
4193
  if (tagContents) {
4210
4194
  // The author has written a \tag or a \notag in this row.
4211
4195
  if (tagContents.body) {
4212
- tag = buildExpressionRow(tagContents.body, style);
4196
+ tag = buildExpressionRow(tagContents.body, style, true);
4213
4197
  tag.classes = ["tml-tag"];
4214
4198
  } else {
4215
4199
  // \notag. Return an empty span.
@@ -4256,7 +4240,9 @@ function parseArray(
4256
4240
  parser.gullet.macros.set("\\cr", "\\\\\\relax");
4257
4241
  }
4258
4242
  if (addEqnNum) {
4259
- parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}");
4243
+ parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren");
4244
+ parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
4245
+ parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}");
4260
4246
  parser.gullet.macros.set("\\notag", "\\env@notag");
4261
4247
  parser.gullet.macros.set("\\nonumber", "\\env@notag");
4262
4248
  }
@@ -4297,7 +4283,8 @@ function parseArray(
4297
4283
  cell = {
4298
4284
  type: "ordgroup",
4299
4285
  mode: parser.mode,
4300
- body: cell
4286
+ body: cell,
4287
+ semisimple: true
4301
4288
  };
4302
4289
  row.push(cell);
4303
4290
  const next = parser.fetch().text;
@@ -5130,7 +5117,7 @@ const mathmlBuilder$6 = (group, style) => {
5130
5117
  const mathGroup = buildGroup$1(group.body, newStyle);
5131
5118
 
5132
5119
  if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
5133
- if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
5120
+ if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
5134
5121
  mathGroup.style.fontWeight = "bold";
5135
5122
  return mathGroup
5136
5123
  }
@@ -6487,10 +6474,10 @@ defineFunction({
6487
6474
  },
6488
6475
  mathmlBuilder(group, style) {
6489
6476
  if (group.isCharacterBox) {
6490
- const inner = buildExpression(group.body, style);
6477
+ const inner = buildExpression(group.body, style, true);
6491
6478
  return inner[0]
6492
6479
  } else {
6493
- return buildExpressionRow(group.body, style, true)
6480
+ return buildExpressionRow(group.body, style)
6494
6481
  }
6495
6482
  }
6496
6483
  });
@@ -6510,6 +6497,13 @@ const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
6510
6497
  // NOTE: Unlike most `builders`s, this one handles not only "op", but also
6511
6498
  // "supsub" since some of them (like \int) can affect super/subscripting.
6512
6499
 
6500
+ const setSpacing = node => {
6501
+ // The user wrote a \mathop{…} function. Change spacing from default to OP spacing.
6502
+ // The most likely spacing for an OP is a thin space per TeXbook p170.
6503
+ node.attributes.lspace = "0.1667em";
6504
+ node.attributes.rspace = "0.1667em";
6505
+ };
6506
+
6513
6507
  const mathmlBuilder$2 = (group, style) => {
6514
6508
  let node;
6515
6509
 
@@ -6521,9 +6515,11 @@ const mathmlBuilder$2 = (group, style) => {
6521
6515
  } else {
6522
6516
  node.setAttribute("movablelimits", "false");
6523
6517
  }
6518
+ if (group.fromMathOp) { setSpacing(node); }
6524
6519
  } else if (group.body) {
6525
6520
  // This is an operator with children. Add them.
6526
6521
  node = new MathNode("mo", buildExpression(group.body, style));
6522
+ if (group.fromMathOp) { setSpacing(node); }
6527
6523
  } else {
6528
6524
  // This is a text operator. Add all of the characters from the operator's name.
6529
6525
  node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
@@ -6643,6 +6639,7 @@ defineFunction({
6643
6639
  limits: true,
6644
6640
  parentIsSupSub: false,
6645
6641
  symbol: isSymbol,
6642
+ fromMathOp: true,
6646
6643
  stack: false,
6647
6644
  name: isSymbol ? arr[0].text : null,
6648
6645
  body: isSymbol ? null : ordargument(body)
@@ -6976,7 +6973,7 @@ defineMacro("\\operatorname",
6976
6973
  defineFunctionBuilders({
6977
6974
  type: "ordgroup",
6978
6975
  mathmlBuilder(group, style) {
6979
- return buildExpressionRow(group.body, style, true);
6976
+ return buildExpressionRow(group.body, style, group.semisimple);
6980
6977
  }
6981
6978
  });
6982
6979
 
@@ -12005,6 +12002,8 @@ var unicodeSymbols = {
12005
12002
 
12006
12003
  /* eslint no-constant-condition:0 */
12007
12004
 
12005
+ const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
12006
+
12008
12007
  /**
12009
12008
  * This file contains the parser used to parse out a TeX expression from the
12010
12009
  * input. Since TeX isn't context-free, standard parsers don't work particularly
@@ -12774,8 +12773,7 @@ class Parser {
12774
12773
  body: expression,
12775
12774
  // A group formed by \begingroup...\endgroup is a semi-simple group
12776
12775
  // which doesn't affect spacing in math mode, i.e., is transparent.
12777
- // https://tex.stackexchange.com/questions/1930/when-should-one-
12778
- // use-begingroup-instead-of-bgroup
12776
+ // https://tex.stackexchange.com/questions/1930/
12779
12777
  semisimple: text === "\\begingroup" || undefined
12780
12778
  };
12781
12779
  } else {
@@ -12889,7 +12887,11 @@ class Parser {
12889
12887
  // Recognize base symbol
12890
12888
  let symbol;
12891
12889
  if (symbols[this.mode][text]) {
12892
- const group = symbols[this.mode][text].group;
12890
+ let group = symbols[this.mode][text].group;
12891
+ if (group === "bin" && binLeftCancellers.includes(this.prevAtomType)) {
12892
+ // Change from a binary operator to a unary (prefix) operator
12893
+ group = "open";
12894
+ }
12893
12895
  const loc = SourceLocation.range(nucleus);
12894
12896
  let s;
12895
12897
  if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
@@ -13159,7 +13161,7 @@ class Style {
13159
13161
  * https://mit-license.org/
13160
13162
  */
13161
13163
 
13162
- const version = "0.10.19";
13164
+ const version = "0.10.20";
13163
13165
 
13164
13166
  function postProcess(block) {
13165
13167
  const labelMap = {};
package/dist/temml.js CHANGED
@@ -2073,20 +2073,22 @@ var temml = (function () {
2073
2073
  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
2074
2074
  * unless the array has length 1. Always returns a single node.
2075
2075
  */
2076
- const makeRow = function(body) {
2076
+ const makeRow = function(body, semisimple = false) {
2077
2077
  if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
2078
2078
  return body[0];
2079
- } else {
2079
+ } else if (!semisimple) {
2080
2080
  // Suppress spacing on <mo> nodes at both ends of the row.
2081
2081
  if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
2082
2082
  body[0].attributes.lspace = "0em";
2083
+ body[0].attributes.rspace = "0em";
2083
2084
  }
2084
2085
  const end = body.length - 1;
2085
2086
  if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
2087
+ body[end].attributes.lspace = "0em";
2086
2088
  body[end].attributes.rspace = "0em";
2087
2089
  }
2088
- return new mathMLTree.MathNode("mrow", body);
2089
2090
  }
2091
+ return new mathMLTree.MathNode("mrow", body);
2090
2092
  };
2091
2093
 
2092
2094
  const isRel = item => {
@@ -2100,10 +2102,10 @@ var temml = (function () {
2100
2102
  * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
2101
2103
  * (2) Suppress spacing between two adjacent relations.
2102
2104
  */
2103
- const buildExpression = function(expression, style, isOrdgroup) {
2104
- if (expression.length === 1) {
2105
+ const buildExpression = function(expression, style, semisimple = false) {
2106
+ if (!semisimple && expression.length === 1) {
2105
2107
  const group = buildGroup$1(expression[0], style);
2106
- if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
2108
+ if (group instanceof MathNode && group.type === "mo") {
2107
2109
  // When TeX writers want to suppress spacing on an operator,
2108
2110
  // they often put the operator by itself inside braces.
2109
2111
  group.setAttribute("lspace", "0em");
@@ -2133,8 +2135,8 @@ var temml = (function () {
2133
2135
  * Equivalent to buildExpression, but wraps the elements in an <mrow>
2134
2136
  * if there's more than one. Returns a single node instead of an array.
2135
2137
  */
2136
- const buildExpressionRow = function(expression, style, isOrdgroup) {
2137
- return makeRow(buildExpression(expression, style, isOrdgroup));
2138
+ const buildExpressionRow = function(expression, style, semisimple = false) {
2139
+ return makeRow(buildExpression(expression, style, semisimple), semisimple);
2138
2140
  };
2139
2141
 
2140
2142
  /**
@@ -2819,7 +2821,8 @@ var temml = (function () {
2819
2821
  const arrowGroup = {
2820
2822
  type: "ordgroup",
2821
2823
  mode: "math",
2822
- body: [leftLabel, sizedArrow, rightLabel]
2824
+ body: [leftLabel, sizedArrow, rightLabel],
2825
+ semisimple: true
2823
2826
  };
2824
2827
  return parser.callFunction("\\\\cdparent", [arrowGroup], []);
2825
2828
  }
@@ -3941,20 +3944,12 @@ var temml = (function () {
3941
3944
  node.style.borderBottom = "0.065em solid";
3942
3945
  break
3943
3946
  case "\\cancel":
3944
- node.style.background = `linear-gradient(to top left,
3945
- rgba(0,0,0,0) 0%,
3946
- rgba(0,0,0,0) calc(50% - 0.06em),
3947
- rgba(0,0,0,1) 50%,
3948
- rgba(0,0,0,0) calc(50% + 0.06em),
3949
- rgba(0,0,0,0) 100%);`;
3947
+ // We can't use an inline background-gradient. It does not work client-side.
3948
+ // So set a class and put the rule in the external CSS file.
3949
+ node.classes.push("tml-cancel");
3950
3950
  break
3951
3951
  case "\\bcancel":
3952
- node.style.background = `linear-gradient(to top right,
3953
- rgba(0,0,0,0) 0%,
3954
- rgba(0,0,0,0) calc(50% - 0.06em),
3955
- rgba(0,0,0,1) 50%,
3956
- rgba(0,0,0,0) calc(50% + 0.06em),
3957
- rgba(0,0,0,0) 100%);`;
3952
+ node.classes.push("tml-bcancel");
3958
3953
  break
3959
3954
  /*
3960
3955
  case "\\longdiv":
@@ -4001,18 +3996,7 @@ rgba(0,0,0,0) 100%);`;
4001
3996
  break
4002
3997
  }
4003
3998
  case "\\xcancel":
4004
- node.style.background = `linear-gradient(to top left,
4005
- rgba(0,0,0,0) 0%,
4006
- rgba(0,0,0,0) calc(50% - 0.06em),
4007
- rgba(0,0,0,1) 50%,
4008
- rgba(0,0,0,0) calc(50% + 0.06em),
4009
- rgba(0,0,0,0) 100%),
4010
- linear-gradient(to top right,
4011
- rgba(0,0,0,0) 0%,
4012
- rgba(0,0,0,0) calc(50% - 0.06em),
4013
- rgba(0,0,0,1) 50%,
4014
- rgba(0,0,0,0) calc(50% + 0.06em),
4015
- rgba(0,0,0,0) 100%);`;
3999
+ node.classes.push("tml-xcancel");
4016
4000
  break
4017
4001
  }
4018
4002
  if (group.backgroundColor) {
@@ -4210,7 +4194,7 @@ rgba(0,0,0,0) 100%);`;
4210
4194
  if (tagContents) {
4211
4195
  // The author has written a \tag or a \notag in this row.
4212
4196
  if (tagContents.body) {
4213
- tag = buildExpressionRow(tagContents.body, style);
4197
+ tag = buildExpressionRow(tagContents.body, style, true);
4214
4198
  tag.classes = ["tml-tag"];
4215
4199
  } else {
4216
4200
  // \notag. Return an empty span.
@@ -4257,7 +4241,9 @@ rgba(0,0,0,0) 100%);`;
4257
4241
  parser.gullet.macros.set("\\cr", "\\\\\\relax");
4258
4242
  }
4259
4243
  if (addEqnNum) {
4260
- parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}");
4244
+ parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren");
4245
+ parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
4246
+ parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}");
4261
4247
  parser.gullet.macros.set("\\notag", "\\env@notag");
4262
4248
  parser.gullet.macros.set("\\nonumber", "\\env@notag");
4263
4249
  }
@@ -4298,7 +4284,8 @@ rgba(0,0,0,0) 100%);`;
4298
4284
  cell = {
4299
4285
  type: "ordgroup",
4300
4286
  mode: parser.mode,
4301
- body: cell
4287
+ body: cell,
4288
+ semisimple: true
4302
4289
  };
4303
4290
  row.push(cell);
4304
4291
  const next = parser.fetch().text;
@@ -5131,7 +5118,7 @@ rgba(0,0,0,0) 100%);`;
5131
5118
  const mathGroup = buildGroup$1(group.body, newStyle);
5132
5119
 
5133
5120
  if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
5134
- if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
5121
+ if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
5135
5122
  mathGroup.style.fontWeight = "bold";
5136
5123
  return mathGroup
5137
5124
  }
@@ -6488,10 +6475,10 @@ rgba(0,0,0,0) 100%);`;
6488
6475
  },
6489
6476
  mathmlBuilder(group, style) {
6490
6477
  if (group.isCharacterBox) {
6491
- const inner = buildExpression(group.body, style);
6478
+ const inner = buildExpression(group.body, style, true);
6492
6479
  return inner[0]
6493
6480
  } else {
6494
- return buildExpressionRow(group.body, style, true)
6481
+ return buildExpressionRow(group.body, style)
6495
6482
  }
6496
6483
  }
6497
6484
  });
@@ -6511,6 +6498,13 @@ rgba(0,0,0,0) 100%);`;
6511
6498
  // NOTE: Unlike most `builders`s, this one handles not only "op", but also
6512
6499
  // "supsub" since some of them (like \int) can affect super/subscripting.
6513
6500
 
6501
+ const setSpacing = node => {
6502
+ // The user wrote a \mathop{…} function. Change spacing from default to OP spacing.
6503
+ // The most likely spacing for an OP is a thin space per TeXbook p170.
6504
+ node.attributes.lspace = "0.1667em";
6505
+ node.attributes.rspace = "0.1667em";
6506
+ };
6507
+
6514
6508
  const mathmlBuilder$2 = (group, style) => {
6515
6509
  let node;
6516
6510
 
@@ -6522,9 +6516,11 @@ rgba(0,0,0,0) 100%);`;
6522
6516
  } else {
6523
6517
  node.setAttribute("movablelimits", "false");
6524
6518
  }
6519
+ if (group.fromMathOp) { setSpacing(node); }
6525
6520
  } else if (group.body) {
6526
6521
  // This is an operator with children. Add them.
6527
6522
  node = new MathNode("mo", buildExpression(group.body, style));
6523
+ if (group.fromMathOp) { setSpacing(node); }
6528
6524
  } else {
6529
6525
  // This is a text operator. Add all of the characters from the operator's name.
6530
6526
  node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
@@ -6644,6 +6640,7 @@ rgba(0,0,0,0) 100%);`;
6644
6640
  limits: true,
6645
6641
  parentIsSupSub: false,
6646
6642
  symbol: isSymbol,
6643
+ fromMathOp: true,
6647
6644
  stack: false,
6648
6645
  name: isSymbol ? arr[0].text : null,
6649
6646
  body: isSymbol ? null : ordargument(body)
@@ -6977,7 +6974,7 @@ rgba(0,0,0,0) 100%);`;
6977
6974
  defineFunctionBuilders({
6978
6975
  type: "ordgroup",
6979
6976
  mathmlBuilder(group, style) {
6980
- return buildExpressionRow(group.body, style, true);
6977
+ return buildExpressionRow(group.body, style, group.semisimple);
6981
6978
  }
6982
6979
  });
6983
6980
 
@@ -10106,6 +10103,8 @@ rgba(0,0,0,0) 100%);`;
10106
10103
 
10107
10104
  /* eslint no-constant-condition:0 */
10108
10105
 
10106
+ const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
10107
+
10109
10108
  /**
10110
10109
  * This file contains the parser used to parse out a TeX expression from the
10111
10110
  * input. Since TeX isn't context-free, standard parsers don't work particularly
@@ -10875,8 +10874,7 @@ rgba(0,0,0,0) 100%);`;
10875
10874
  body: expression,
10876
10875
  // A group formed by \begingroup...\endgroup is a semi-simple group
10877
10876
  // which doesn't affect spacing in math mode, i.e., is transparent.
10878
- // https://tex.stackexchange.com/questions/1930/when-should-one-
10879
- // use-begingroup-instead-of-bgroup
10877
+ // https://tex.stackexchange.com/questions/1930/
10880
10878
  semisimple: text === "\\begingroup" || undefined
10881
10879
  };
10882
10880
  } else {
@@ -10990,7 +10988,11 @@ rgba(0,0,0,0) 100%);`;
10990
10988
  // Recognize base symbol
10991
10989
  let symbol;
10992
10990
  if (symbols[this.mode][text]) {
10993
- const group = symbols[this.mode][text].group;
10991
+ let group = symbols[this.mode][text].group;
10992
+ if (group === "bin" && binLeftCancellers.includes(this.prevAtomType)) {
10993
+ // Change from a binary operator to a unary (prefix) operator
10994
+ group = "open";
10995
+ }
10994
10996
  const loc = SourceLocation.range(nucleus);
10995
10997
  let s;
10996
10998
  if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
@@ -11260,7 +11262,7 @@ rgba(0,0,0,0) 100%);`;
11260
11262
  * https://mit-license.org/
11261
11263
  */
11262
11264
 
11263
- const version = "0.10.19";
11265
+ const version = "0.10.20";
11264
11266
 
11265
11267
  function postProcess(block) {
11266
11268
  const labelMap = {};