temml 0.10.18 → 0.10.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -940,8 +940,8 @@ defineSymbol(math, textord, "\u2207", "\\nabla", true);
940
940
  defineSymbol(math, textord, "\u266d", "\\flat", true);
941
941
  defineSymbol(math, textord, "\u2113", "\\ell", true);
942
942
  defineSymbol(math, textord, "\u266e", "\\natural", true);
943
- defineSymbol(math, textord, "Å", "\\AA", true);
944
- defineSymbol(text, textord, "Å", "\\AA", true);
943
+ defineSymbol(math, textord, "Å", "\\Angstrom", true);
944
+ defineSymbol(text, textord, "Å", "\\Angstrom", true);
945
945
  defineSymbol(math, textord, "\u2663", "\\clubsuit", true);
946
946
  defineSymbol(math, textord, "\u2667", "\\varclubsuit", true);
947
947
  defineSymbol(math, textord, "\u2118", "\\wp", true);
@@ -2055,6 +2055,16 @@ const consolidateNumbers = expression => {
2055
2055
  expression[nums[i].start].text += expression[j].text;
2056
2056
  }
2057
2057
  expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
2058
+ // Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
2059
+ // If so, merge the first <mn> into the base.
2060
+ if (expression.length > nums[i].start + 1) {
2061
+ const nextTerm = expression[nums[i].start + 1];
2062
+ if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
2063
+ numberRegEx$1.test(nextTerm.base.text)) {
2064
+ nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
2065
+ expression.splice(nums[i].start, 1);
2066
+ }
2067
+ }
2058
2068
  }
2059
2069
  };
2060
2070
 
@@ -2062,20 +2072,22 @@ const consolidateNumbers = expression => {
2062
2072
  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
2063
2073
  * unless the array has length 1. Always returns a single node.
2064
2074
  */
2065
- const makeRow = function(body) {
2075
+ const makeRow = function(body, semisimple = false) {
2066
2076
  if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
2067
2077
  return body[0];
2068
- } else {
2078
+ } else if (!semisimple) {
2069
2079
  // Suppress spacing on <mo> nodes at both ends of the row.
2070
2080
  if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
2071
2081
  body[0].attributes.lspace = "0em";
2082
+ body[0].attributes.rspace = "0em";
2072
2083
  }
2073
2084
  const end = body.length - 1;
2074
2085
  if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
2086
+ body[end].attributes.lspace = "0em";
2075
2087
  body[end].attributes.rspace = "0em";
2076
2088
  }
2077
- return new mathMLTree.MathNode("mrow", body);
2078
2089
  }
2090
+ return new mathMLTree.MathNode("mrow", body);
2079
2091
  };
2080
2092
 
2081
2093
  const isRel = item => {
@@ -2089,10 +2101,10 @@ const isRel = item => {
2089
2101
  * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
2090
2102
  * (2) Suppress spacing between two adjacent relations.
2091
2103
  */
2092
- const buildExpression = function(expression, style, isOrdgroup) {
2093
- if (expression.length === 1) {
2104
+ const buildExpression = function(expression, style, semisimple = false) {
2105
+ if (!semisimple && expression.length === 1) {
2094
2106
  const group = buildGroup$1(expression[0], style);
2095
- if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
2107
+ if (group instanceof MathNode && group.type === "mo") {
2096
2108
  // When TeX writers want to suppress spacing on an operator,
2097
2109
  // they often put the operator by itself inside braces.
2098
2110
  group.setAttribute("lspace", "0em");
@@ -2122,8 +2134,8 @@ const buildExpression = function(expression, style, isOrdgroup) {
2122
2134
  * Equivalent to buildExpression, but wraps the elements in an <mrow>
2123
2135
  * if there's more than one. Returns a single node instead of an array.
2124
2136
  */
2125
- const buildExpressionRow = function(expression, style, isOrdgroup) {
2126
- return makeRow(buildExpression(expression, style, isOrdgroup));
2137
+ const buildExpressionRow = function(expression, style, semisimple = false) {
2138
+ return makeRow(buildExpression(expression, style, semisimple), semisimple);
2127
2139
  };
2128
2140
 
2129
2141
  /**
@@ -2808,7 +2820,8 @@ function cdArrow(arrowChar, labels, parser) {
2808
2820
  const arrowGroup = {
2809
2821
  type: "ordgroup",
2810
2822
  mode: "math",
2811
- body: [leftLabel, sizedArrow, rightLabel]
2823
+ body: [leftLabel, sizedArrow, rightLabel],
2824
+ semisimple: true
2812
2825
  };
2813
2826
  return parser.callFunction("\\\\cdparent", [arrowGroup], []);
2814
2827
  }
@@ -3930,20 +3943,12 @@ const mathmlBuilder$8 = (group, style) => {
3930
3943
  node.style.borderBottom = "0.065em solid";
3931
3944
  break
3932
3945
  case "\\cancel":
3933
- node.style.background = `linear-gradient(to top left,
3934
- rgba(0,0,0,0) 0%,
3935
- rgba(0,0,0,0) calc(50% - 0.06em),
3936
- rgba(0,0,0,1) 50%,
3937
- rgba(0,0,0,0) calc(50% + 0.06em),
3938
- 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");
3939
3949
  break
3940
3950
  case "\\bcancel":
3941
- node.style.background = `linear-gradient(to top right,
3942
- rgba(0,0,0,0) 0%,
3943
- rgba(0,0,0,0) calc(50% - 0.06em),
3944
- rgba(0,0,0,1) 50%,
3945
- rgba(0,0,0,0) calc(50% + 0.06em),
3946
- rgba(0,0,0,0) 100%);`;
3951
+ node.classes.push("tml-bcancel");
3947
3952
  break
3948
3953
  /*
3949
3954
  case "\\longdiv":
@@ -3990,18 +3995,7 @@ rgba(0,0,0,0) 100%);`;
3990
3995
  break
3991
3996
  }
3992
3997
  case "\\xcancel":
3993
- node.style.background = `linear-gradient(to top left,
3994
- rgba(0,0,0,0) 0%,
3995
- rgba(0,0,0,0) calc(50% - 0.06em),
3996
- rgba(0,0,0,1) 50%,
3997
- rgba(0,0,0,0) calc(50% + 0.06em),
3998
- rgba(0,0,0,0) 100%),
3999
- linear-gradient(to top right,
4000
- rgba(0,0,0,0) 0%,
4001
- rgba(0,0,0,0) calc(50% - 0.06em),
4002
- rgba(0,0,0,1) 50%,
4003
- rgba(0,0,0,0) calc(50% + 0.06em),
4004
- rgba(0,0,0,0) 100%);`;
3998
+ node.classes.push("tml-xcancel");
4005
3999
  break
4006
4000
  }
4007
4001
  if (group.backgroundColor) {
@@ -4199,7 +4193,7 @@ const getTag = (group, style, rowNum) => {
4199
4193
  if (tagContents) {
4200
4194
  // The author has written a \tag or a \notag in this row.
4201
4195
  if (tagContents.body) {
4202
- tag = buildExpressionRow(tagContents.body, style);
4196
+ tag = buildExpressionRow(tagContents.body, style, true);
4203
4197
  tag.classes = ["tml-tag"];
4204
4198
  } else {
4205
4199
  // \notag. Return an empty span.
@@ -4246,7 +4240,9 @@ function parseArray(
4246
4240
  parser.gullet.macros.set("\\cr", "\\\\\\relax");
4247
4241
  }
4248
4242
  if (addEqnNum) {
4249
- 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}}");
4250
4246
  parser.gullet.macros.set("\\notag", "\\env@notag");
4251
4247
  parser.gullet.macros.set("\\nonumber", "\\env@notag");
4252
4248
  }
@@ -4287,7 +4283,8 @@ function parseArray(
4287
4283
  cell = {
4288
4284
  type: "ordgroup",
4289
4285
  mode: parser.mode,
4290
- body: cell
4286
+ body: cell,
4287
+ semisimple: true
4291
4288
  };
4292
4289
  row.push(cell);
4293
4290
  const next = parser.fetch().text;
@@ -5120,7 +5117,7 @@ const mathmlBuilder$6 = (group, style) => {
5120
5117
  const mathGroup = buildGroup$1(group.body, newStyle);
5121
5118
 
5122
5119
  if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
5123
- if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
5120
+ if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
5124
5121
  mathGroup.style.fontWeight = "bold";
5125
5122
  return mathGroup
5126
5123
  }
@@ -6477,10 +6474,10 @@ defineFunction({
6477
6474
  },
6478
6475
  mathmlBuilder(group, style) {
6479
6476
  if (group.isCharacterBox) {
6480
- const inner = buildExpression(group.body, style);
6477
+ const inner = buildExpression(group.body, style, true);
6481
6478
  return inner[0]
6482
6479
  } else {
6483
- return buildExpressionRow(group.body, style, true)
6480
+ return buildExpressionRow(group.body, style)
6484
6481
  }
6485
6482
  }
6486
6483
  });
@@ -6500,6 +6497,13 @@ const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
6500
6497
  // NOTE: Unlike most `builders`s, this one handles not only "op", but also
6501
6498
  // "supsub" since some of them (like \int) can affect super/subscripting.
6502
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
+
6503
6507
  const mathmlBuilder$2 = (group, style) => {
6504
6508
  let node;
6505
6509
 
@@ -6511,9 +6515,11 @@ const mathmlBuilder$2 = (group, style) => {
6511
6515
  } else {
6512
6516
  node.setAttribute("movablelimits", "false");
6513
6517
  }
6518
+ if (group.fromMathOp) { setSpacing(node); }
6514
6519
  } else if (group.body) {
6515
6520
  // This is an operator with children. Add them.
6516
6521
  node = new MathNode("mo", buildExpression(group.body, style));
6522
+ if (group.fromMathOp) { setSpacing(node); }
6517
6523
  } else {
6518
6524
  // This is a text operator. Add all of the characters from the operator's name.
6519
6525
  node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
@@ -6633,6 +6639,7 @@ defineFunction({
6633
6639
  limits: true,
6634
6640
  parentIsSupSub: false,
6635
6641
  symbol: isSymbol,
6642
+ fromMathOp: true,
6636
6643
  stack: false,
6637
6644
  name: isSymbol ? arr[0].text : null,
6638
6645
  body: isSymbol ? null : ordargument(body)
@@ -6966,7 +6973,7 @@ defineMacro("\\operatorname",
6966
6973
  defineFunctionBuilders({
6967
6974
  type: "ordgroup",
6968
6975
  mathmlBuilder(group, style) {
6969
- return buildExpressionRow(group.body, style, true);
6976
+ return buildExpressionRow(group.body, style, group.semisimple);
6970
6977
  }
6971
6978
  });
6972
6979
 
@@ -8916,6 +8923,8 @@ defineMacro("\\quad", "\\hskip1em\\relax");
8916
8923
  // \def\qquad{\hskip2em\relax}
8917
8924
  defineMacro("\\qquad", "\\hskip2em\\relax");
8918
8925
 
8926
+ defineMacro("\\AA", "\\TextOrMath{\\Angstrom}{\\mathring{A}}\\relax");
8927
+
8919
8928
  // \tag@in@display form of \tag
8920
8929
  defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
8921
8930
  defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
@@ -11993,6 +12002,8 @@ var unicodeSymbols = {
11993
12002
 
11994
12003
  /* eslint no-constant-condition:0 */
11995
12004
 
12005
+ const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
12006
+
11996
12007
  /**
11997
12008
  * This file contains the parser used to parse out a TeX expression from the
11998
12009
  * input. Since TeX isn't context-free, standard parsers don't work particularly
@@ -12762,8 +12773,7 @@ class Parser {
12762
12773
  body: expression,
12763
12774
  // A group formed by \begingroup...\endgroup is a semi-simple group
12764
12775
  // which doesn't affect spacing in math mode, i.e., is transparent.
12765
- // https://tex.stackexchange.com/questions/1930/when-should-one-
12766
- // use-begingroup-instead-of-bgroup
12776
+ // https://tex.stackexchange.com/questions/1930/
12767
12777
  semisimple: text === "\\begingroup" || undefined
12768
12778
  };
12769
12779
  } else {
@@ -12877,7 +12887,11 @@ class Parser {
12877
12887
  // Recognize base symbol
12878
12888
  let symbol;
12879
12889
  if (symbols[this.mode][text]) {
12880
- 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
+ }
12881
12895
  const loc = SourceLocation.range(nucleus);
12882
12896
  let s;
12883
12897
  if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
@@ -13147,7 +13161,7 @@ class Style {
13147
13161
  * https://mit-license.org/
13148
13162
  */
13149
13163
 
13150
- const version = "0.10.18";
13164
+ const version = "0.10.20";
13151
13165
 
13152
13166
  function postProcess(block) {
13153
13167
  const labelMap = {};