temml 0.10.21 → 0.10.23

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  | Library | Minified JavaScript + CSS |
4
4
  |:--------------|:-------------------------:|
5
- | Temml | 150 KB |
5
+ | Temml | 151 KB |
6
6
  | MathJax 2.7.5 | 338 KB |
7
7
  | KaTeX | 280 KB |
8
8
  | TeXZilla | 168 KB |
@@ -30,10 +30,6 @@ math * {
30
30
  border-color: currentColor;
31
31
  }
32
32
 
33
- mtext {
34
- font-family: Asana Math;
35
- }
36
-
37
33
  math {
38
34
  font-family: Asana Math, math;
39
35
  }
@@ -0,0 +1,152 @@
1
+ /*
2
+ Fira Math fonts are released under the SIL OPEN FONT LICENSE Version 1.1.
3
+
4
+ The Fira Math WOFF2 font has been obtained from
5
+ http://www.gust.org.pl/projects/e-foundry/
6
+
7
+ The Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points
8
+ have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals,
9
+ Unicode range 1D49C to 1D4B5.
10
+ */
11
+
12
+ @font-face {
13
+ font-family: 'Temml';
14
+ src: url('Temml.woff2') format('woff2');
15
+ font-weight: normal;
16
+ font-style: normal;
17
+ }
18
+
19
+ @font-face {
20
+ font-family: Fira Math;
21
+ src: url('FiraMath-Regular.woff2');
22
+ }
23
+
24
+ math {
25
+ font-style: normal;
26
+ font-weight: normal;
27
+ line-height: normal;
28
+ font-size-adjust: none;
29
+ text-indent: 0;
30
+ text-transform: none;
31
+ letter-spacing: normal;
32
+ word-wrap: normal;
33
+ direction: ltr;
34
+ }
35
+
36
+ math * {
37
+ border-color: currentColor;
38
+ }
39
+
40
+ math {
41
+ font-family: "Fira Math", math;
42
+ }
43
+
44
+ /* Next line is active in Firefox and Safari.
45
+ * Not in Chromium, which recognizes display: "block math" written inline. */
46
+ math.tml-display { display: block; }
47
+
48
+ *.mathscr {
49
+ font-family: "Temml";
50
+ }
51
+
52
+ /* Chromium prime alignment */
53
+ mo.tml-prime {
54
+ font-family: Temml;
55
+ }
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
+
90
+ /* Prevent f' from overlapping in Chromium */
91
+ mo.prime-pad {
92
+ padding-left: 0.08em;
93
+ }
94
+
95
+ /* Array cell justification in Firefox & WebKit */
96
+ .tml-right {
97
+ text-align: right;
98
+ }
99
+ .tml-left {
100
+ text-align: left;
101
+ }
102
+
103
+ /* Stretch \widetilde & set array cell justification in Chromium */
104
+ @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
105
+ .tml-crooked-2 {
106
+ transform: scale(2.0, 1.1)
107
+ }
108
+ .tml-crooked-3 {
109
+ transform: scale(3.0, 1.3)
110
+ }
111
+ .tml-crooked-4 {
112
+ transform: scale(4.0, 1.4)
113
+ }
114
+ .tml-right {
115
+ text-align: -webkit-right;
116
+ }
117
+ .tml-left {
118
+ text-align: -webkit-left;
119
+ }
120
+ }
121
+
122
+ /* Adjust WebKit accents */
123
+ @supports (-webkit-backdrop-filter: blur(1px)) {
124
+ .tml-xshift { transform: translate(0px, 0.45em) }
125
+ .tml-capshift { transform: translate(0px, 0.35em) }
126
+ }
127
+
128
+ /* flex-wrap for line-breaking in Chromium */
129
+ math {
130
+ display: inline-flex;
131
+ flex-wrap: wrap;
132
+ align-items: baseline;
133
+ }
134
+ math > mrow {
135
+ padding: 0.5ex 0ex;
136
+ }
137
+
138
+ /* Avoid flex-wrap in Firefox */
139
+ @-moz-document url-prefix() {
140
+ math { display: inline; }
141
+ math > mrow { padding: 0 }
142
+ }
143
+
144
+ /* AMS environment auto-numbering via CSS counter. */
145
+ .tml-eqn::before {
146
+ counter-increment: tmlEqnNo;
147
+ content: "(" counter(tmlEqnNo) ")";
148
+ }
149
+
150
+ body {
151
+ counter-reset: tmlEqnNo;
152
+ }
@@ -32,10 +32,6 @@ math * {
32
32
  * Not in Chromium, which recognizes display: "block math" written inline. */
33
33
  math.tml-display { display: block; }
34
34
 
35
- mtext {
36
- font-family: STIX2;
37
- }
38
-
39
35
  math {
40
36
  font-family: STIX2, math;
41
37
  }
package/dist/temml.cjs CHANGED
@@ -936,7 +936,8 @@ defineSymbol(math, textord, "\u2135", "\\aleph", true);
936
936
  defineSymbol(math, textord, "\u2200", "\\forall", true);
937
937
  defineSymbol(math, textord, "\u210f", "\\hbar", true);
938
938
  defineSymbol(math, textord, "\u2203", "\\exists", true);
939
- defineSymbol(math, textord, "\u2207", "\\nabla", true);
939
+ // is actually a unary operator, not binary. But this works.
940
+ defineSymbol(math, bin, "\u2207", "\\nabla", true);
940
941
  defineSymbol(math, textord, "\u266d", "\\flat", true);
941
942
  defineSymbol(math, textord, "\u2113", "\\ell", true);
942
943
  defineSymbol(math, textord, "\u266e", "\\natural", true);
@@ -990,6 +991,7 @@ defineSymbol(math, bin, "\u2021", "\\ddagger");
990
991
  defineSymbol(math, bin, "\u2240", "\\wr", true);
991
992
  defineSymbol(math, bin, "\u2a3f", "\\amalg");
992
993
  defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath
994
+ defineSymbol(math, bin, "\u2AFD", "\\sslash", true); // from stmaryrd
993
995
 
994
996
  // Arrow Symbols
995
997
  defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true);
@@ -1024,6 +1026,7 @@ defineSymbol(math, mathord, "\u2609", "\\astrosun", true);
1024
1026
  defineSymbol(math, mathord, "\u263c", "\\sun", true);
1025
1027
  defineSymbol(math, mathord, "\u263e", "\\leftmoon", true);
1026
1028
  defineSymbol(math, mathord, "\u263d", "\\rightmoon", true);
1029
+ defineSymbol(math, mathord, "\u2295", "\\Earth");
1027
1030
 
1028
1031
  // AMS Negated Binary Relations
1029
1032
  defineSymbol(math, rel, "\u226e", "\\nless", true);
@@ -1251,6 +1254,8 @@ defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
1251
1254
  defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
1252
1255
  defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
1253
1256
 
1257
+ defineSymbol(math, bin, "\u2238", "\\dotminus", true); // stix
1258
+
1254
1259
  // AMS Arrows
1255
1260
  // Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
1256
1261
  // We'll map it to AMS function \dashrightarrow. It produces the same atom.
@@ -1408,6 +1413,7 @@ defineSymbol(math, mathord, "\u2aeb", "\\Bot");
1408
1413
  defineSymbol(math, bin, "\u2217", "\u2217", true);
1409
1414
  defineSymbol(math, bin, "+", "+");
1410
1415
  defineSymbol(math, bin, "*", "*");
1416
+ defineSymbol(math, bin, "\u2044", "/", true);
1411
1417
  defineSymbol(math, bin, "\u2044", "\u2044");
1412
1418
  defineSymbol(math, bin, "\u2212", "-", true);
1413
1419
  defineSymbol(math, bin, "\u22c5", "\\cdot", true);
@@ -1864,7 +1870,8 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
1864
1870
  continue
1865
1871
  }
1866
1872
  block.push(node);
1867
- if (node.type && node.type === "mo" && node.children.length === 1) {
1873
+ if (node.type && node.type === "mo" && node.children.length === 1 &&
1874
+ !Object.hasOwn(node.attributes, "movablelimits")) {
1868
1875
  const ch = node.children[0].text;
1869
1876
  if (openDelims.indexOf(ch) > -1) {
1870
1877
  level += 1;
@@ -1879,7 +1886,7 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
1879
1886
  mrows.push(element);
1880
1887
  block = [node];
1881
1888
  }
1882
- } else if (level === 0 && wrapMode === "tex") {
1889
+ } else if (level === 0 && wrapMode === "tex" && ch !== "∇") {
1883
1890
  // Check if the following node is a \nobreak text node, e.g. "~""
1884
1891
  const next = i < expression.length - 1 ? expression[i + 1] : null;
1885
1892
  let glueIsFreeOfNobreak = true;
@@ -2017,9 +2024,11 @@ const consolidateText = mrow => {
2017
2024
  };
2018
2025
 
2019
2026
  const numberRegEx$1 = /^[0-9]$/;
2020
- const isCommaOrDot = node => {
2021
- return (node.type === "atom" && node.text === ",") ||
2022
- (node.type === "textord" && node.text === ".")
2027
+ const isDotOrComma = (node, followingNode) => {
2028
+ return ((node.type === "textord" && node.text === ".") ||
2029
+ (node.type === "atom" && node.text === ",")) &&
2030
+ // Don't consolidate if there is a space after the comma.
2031
+ node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
2023
2032
  };
2024
2033
  const consolidateNumbers = expression => {
2025
2034
  // Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
@@ -2042,7 +2051,8 @@ const consolidateNumbers = expression => {
2042
2051
 
2043
2052
  // Determine if numeral groups are separated by a comma or dot.
2044
2053
  for (let i = nums.length - 1; i > 0; i--) {
2045
- if (nums[i - 1].end === nums[i].start - 2 && isCommaOrDot(expression[nums[i].start - 1])) {
2054
+ if (nums[i - 1].end === nums[i].start - 2 &&
2055
+ isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
2046
2056
  // Merge the two groups.
2047
2057
  nums[i - 1].end = nums[i].end;
2048
2058
  nums.splice(i, 1);
@@ -3258,7 +3268,7 @@ defineFunction({
3258
3268
  }
3259
3269
 
3260
3270
  // Parse out the implicit body that should be colored.
3261
- const body = parser.parseExpression(true, breakOnTokenText);
3271
+ const body = parser.parseExpression(true, breakOnTokenText, true);
3262
3272
 
3263
3273
  return {
3264
3274
  type: "color",
@@ -3700,17 +3710,13 @@ const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
3700
3710
 
3701
3711
  // Delimiter functions
3702
3712
  function checkDelimiter(delim, context) {
3703
- if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") {
3704
- // Recover "/" from the zero spacing group. (See macros.js)
3705
- delim = { type: "textord", text: "/", mode: "math" };
3706
- }
3707
3713
  const symDelim = checkSymbolNodeType(delim);
3708
3714
  if (symDelim && delimiters.includes(symDelim.text)) {
3709
3715
  // If a character is not in the MathML operator dictionary, it will not stretch.
3710
3716
  // Replace such characters w/characters that will stretch.
3717
+ if (["/", "\u2044"].includes(symDelim.text)) { symDelim.text = "\u2215"; }
3711
3718
  if (["<", "\\lt"].includes(symDelim.text)) { symDelim.text = "⟨"; }
3712
3719
  if ([">", "\\gt"].includes(symDelim.text)) { symDelim.text = "⟩"; }
3713
- if (symDelim.text === "/") { symDelim.text = "\u2215"; }
3714
3720
  if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; }
3715
3721
  return symDelim;
3716
3722
  } else if (symDelim) {
@@ -3819,8 +3825,26 @@ defineFunction({
3819
3825
  const parser = context.parser;
3820
3826
  // Parse out the implicit body
3821
3827
  ++parser.leftrightDepth;
3822
- // parseExpression stops before '\\right'
3823
- const body = parser.parseExpression(false);
3828
+ // parseExpression stops before '\\right' or `\\middle`
3829
+ let body = parser.parseExpression(false, null, true);
3830
+ let nextToken = parser.fetch();
3831
+ while (nextToken.text === "\\middle") {
3832
+ // `\middle`, from the ε-TeX package, ends one group and starts another group.
3833
+ // We had to parse this expression with `breakOnMiddle` enabled in order
3834
+ // to get TeX-compliant parsing of \over.
3835
+ // But we do not want, at this point, to end on \middle, so continue
3836
+ // to parse until we fetch a `\right`.
3837
+ parser.consume();
3838
+ const middle = parser.fetch().text;
3839
+ if (!symbols.math[middle]) {
3840
+ throw new ParseError(`Invalid delimiter '${middle}' after '\\middle'`);
3841
+ }
3842
+ checkDelimiter({ type: "atom", mode: "math", text: middle }, { funcName: "\\middle" });
3843
+ body.push({ type: "middle", mode: "math", delim: middle });
3844
+ parser.consume();
3845
+ body = body.concat(parser.parseExpression(false, null, true));
3846
+ nextToken = parser.fetch();
3847
+ }
3824
3848
  --parser.leftrightDepth;
3825
3849
  // Check the next token
3826
3850
  parser.expect("\\right", false);
@@ -5094,6 +5118,21 @@ defineFunction({
5094
5118
  }
5095
5119
  });
5096
5120
 
5121
+ const isLongVariableName = (group, font) => {
5122
+ if (font !== "mathrm" || group.body.type !== "ordgroup" || group.body.body.length === 1) {
5123
+ return false
5124
+ }
5125
+ if (group.body.body[0].type !== "mathord") { return false }
5126
+ for (let i = 1; i < group.body.body.length; i++) {
5127
+ const parseNodeType = group.body.body[i].type;
5128
+ if (!(parseNodeType === "mathord" ||
5129
+ (parseNodeType === "textord" && !isNaN(group.body.body[i].text)))) {
5130
+ return false
5131
+ }
5132
+ }
5133
+ return true
5134
+ };
5135
+
5097
5136
  const mathmlBuilder$6 = (group, style) => {
5098
5137
  const font = group.font;
5099
5138
  const newStyle = style.withFont(font);
@@ -5105,6 +5144,20 @@ const mathmlBuilder$6 = (group, style) => {
5105
5144
  return mathGroup
5106
5145
  }
5107
5146
  // Check if it is possible to consolidate elements into a single <mi> element.
5147
+ if (isLongVariableName(group, font)) {
5148
+ // This is a \mathrm{…} group. It gets special treatment because symbolsOrd.js
5149
+ // wraps <mi> elements with <mrow>s to work around a Firefox bug.
5150
+ const mi = mathGroup.children[0].children[0];
5151
+ delete mi.attributes.mathvariant;
5152
+ for (let i = 1; i < mathGroup.children.length; i++) {
5153
+ mi.children[0].text += mathGroup.children[i].type === "mn"
5154
+ ? mathGroup.children[i].children[0].text
5155
+ : mathGroup.children[i].children[0].children[0].text;
5156
+ }
5157
+ // Wrap in a <mrow> to prevent the same Firefox bug.
5158
+ const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b"));
5159
+ return new mathMLTree.MathNode("mrow", [bogus, mi])
5160
+ }
5108
5161
  let canConsolidate = mathGroup.children[0].type === "mo";
5109
5162
  for (let i = 1; i < mathGroup.children.length; i++) {
5110
5163
  if (mathGroup.children[i].type === "mo" && font === "boldsymbol") {
@@ -5195,7 +5248,7 @@ defineFunction({
5195
5248
  },
5196
5249
  handler: ({ parser, funcName, breakOnTokenText }, args) => {
5197
5250
  const { mode } = parser;
5198
- const body = parser.parseExpression(true, breakOnTokenText);
5251
+ const body = parser.parseExpression(true, breakOnTokenText, true);
5199
5252
  const fontStyle = `math${funcName.slice(1)}`;
5200
5253
 
5201
5254
  return {
@@ -6156,6 +6209,9 @@ function mathmlBuilder$3(group, style) {
6156
6209
  if (group.isCharacterBox || inner[0].type === "mathord") {
6157
6210
  node = inner[0];
6158
6211
  node.type = "mi";
6212
+ if (node.children.length === 1 && node.children[0].text && node.children[0].text === "∇") {
6213
+ node.setAttribute("mathvariant", "normal");
6214
+ }
6159
6215
  } else {
6160
6216
  node = new mathMLTree.MathNode("mi", inner);
6161
6217
  }
@@ -7143,6 +7199,28 @@ defineFunction({
7143
7199
  }
7144
7200
  });
7145
7201
 
7202
+ defineFunction({
7203
+ type: "reflect",
7204
+ names: ["\\reflectbox"],
7205
+ props: {
7206
+ numArgs: 1,
7207
+ argTypes: ["hbox"],
7208
+ allowedInText: true
7209
+ },
7210
+ handler({ parser }, args) {
7211
+ return {
7212
+ type: "reflect",
7213
+ mode: parser.mode,
7214
+ body: args[0]
7215
+ };
7216
+ },
7217
+ mathmlBuilder(group, style) {
7218
+ const node = buildGroup$1(group.body, style);
7219
+ node.style.transform = "scaleX(-1)";
7220
+ return node
7221
+ }
7222
+ });
7223
+
7146
7224
  defineFunction({
7147
7225
  type: "internal",
7148
7226
  names: ["\\relax"],
@@ -7248,7 +7326,7 @@ defineFunction({
7248
7326
  // eslint-disable-next-line no-console
7249
7327
  console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`);
7250
7328
  }
7251
- const body = parser.parseExpression(false, breakOnTokenText);
7329
+ const body = parser.parseExpression(false, breakOnTokenText, true);
7252
7330
  return {
7253
7331
  type: "sizing",
7254
7332
  mode: parser.mode,
@@ -7381,7 +7459,7 @@ defineFunction({
7381
7459
  },
7382
7460
  handler({ breakOnTokenText, funcName, parser }, args) {
7383
7461
  // parse out the implicit body
7384
- const body = parser.parseExpression(true, breakOnTokenText);
7462
+ const body = parser.parseExpression(true, breakOnTokenText, true);
7385
7463
 
7386
7464
  const scriptLevel = funcName.slice(1, funcName.length - 5);
7387
7465
  return {
@@ -7812,22 +7890,22 @@ const offset = Object.freeze({
7812
7890
  "sans-serif-bold-italic": ch => { return 0x1D5F5 },
7813
7891
  "monospace": ch => { return 0x1D629 }
7814
7892
  },
7815
- upperCaseGreek: { // A-Ω
7893
+ upperCaseGreek: { // A-Ω
7816
7894
  "normal": ch => { return 0 },
7817
- "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 },
7818
- "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 },
7895
+ "bold": ch => { return 0x1D317 },
7896
+ "italic": ch => { return 0x1D351 },
7819
7897
  // \boldsymbol actually returns upright bold for upperCaseGreek
7820
- "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 },
7898
+ "bold-italic": ch => { return 0x1D317 },
7821
7899
  "script": ch => { return 0 },
7822
7900
  "script-bold": ch => { return 0 },
7823
7901
  "fraktur": ch => { return 0 },
7824
7902
  "fraktur-bold": ch => { return 0 },
7825
7903
  "double-struck": ch => { return 0 },
7826
7904
  // Unicode has no code points for regular-weight san-serif Greek. Use bold.
7827
- "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 },
7828
- "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 },
7905
+ "sans-serif": ch => { return 0x1D3C5 },
7906
+ "sans-serif-bold": ch => { return 0x1D3C5 },
7829
7907
  "sans-serif-italic": ch => { return 0 },
7830
- "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF },
7908
+ "sans-serif-bold-italic": ch => { return 0x1D3FF },
7831
7909
  "monospace": ch => { return 0 }
7832
7910
  },
7833
7911
  lowerCaseGreek: { // α-ω
@@ -7887,7 +7965,7 @@ const variantChar = (ch, variant) => {
7887
7965
  ? "upperCaseLatin"
7888
7966
  : 0x60 < codePoint && codePoint < 0x7b
7889
7967
  ? "lowerCaseLatin"
7890
- : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇"
7968
+ : (0x390 < codePoint && codePoint < 0x3AA)
7891
7969
  ? "upperCaseGreek"
7892
7970
  : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5"
7893
7971
  ? "lowerCaseGreek"
@@ -8016,8 +8094,6 @@ defineFunctionBuilders({
8016
8094
  node = new mathMLTree.MathNode("mi", [text]);
8017
8095
  if (text.text === origText && latinRegEx.test(origText)) {
8018
8096
  node.setAttribute("mathvariant", "italic");
8019
- } else if (text.text === "∇" && variant === "normal") {
8020
- node.setAttribute("mathvariant", "normal");
8021
8097
  }
8022
8098
  }
8023
8099
  return node
@@ -8654,6 +8730,24 @@ defineMacro("\\char", function(context) {
8654
8730
  return `\\@char{${number}}`;
8655
8731
  });
8656
8732
 
8733
+ function recreateArgStr(context) {
8734
+ // Recreate the macro's original argument string from the array of parse tokens.
8735
+ const tokens = context.consumeArgs(1)[0];
8736
+ let str = "";
8737
+ let expectedLoc = tokens[tokens.length - 1].loc.start;
8738
+ for (let i = tokens.length - 1; i >= 0; i--) {
8739
+ const actualLoc = tokens[i].loc.start;
8740
+ if (actualLoc > expectedLoc) {
8741
+ // context.consumeArgs has eaten a space.
8742
+ str += " ";
8743
+ expectedLoc = actualLoc;
8744
+ }
8745
+ str += tokens[i].text;
8746
+ expectedLoc += tokens[i].text.length;
8747
+ }
8748
+ return str
8749
+ }
8750
+
8657
8751
  // The Latin Modern font renders <mi>√</mi> at the wrong vertical alignment.
8658
8752
  // This macro provides a better rendering.
8659
8753
  defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
@@ -8661,10 +8755,6 @@ defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
8661
8755
  // See comment for \oplus in symbols.js.
8662
8756
  defineMacro("\u2295", "\\oplus");
8663
8757
 
8664
- // Per TeXbook p.122, "/" gets zero operator spacing.
8665
- // And MDN recommends using U+2044 instead of / for inline
8666
- defineMacro("/", "{\u2044}");
8667
-
8668
8758
  // Since Temml has no \par, ignore \long.
8669
8759
  defineMacro("\\long", "");
8670
8760
 
@@ -9042,6 +9132,11 @@ defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
9042
9132
  defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
9043
9133
  defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}");
9044
9134
 
9135
+ //////////////////////////////////////////////////////////////////////
9136
+ // MnSymbol.sty
9137
+
9138
+ defineMacro("\\leftmodels", "\\mathop{\\reflectbox{$\\models$}}");
9139
+
9045
9140
  //////////////////////////////////////////////////////////////////////
9046
9141
  // braket.sty
9047
9142
  // http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
@@ -9051,56 +9146,33 @@ defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
9051
9146
  defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
9052
9147
  defineMacro("\\Bra", "\\left\\langle#1\\right|");
9053
9148
  defineMacro("\\Ket", "\\left|#1\\right\\rangle");
9054
- const braketHelper = (one) => (context) => {
9055
- const left = context.consumeArg().tokens;
9056
- const middle = context.consumeArg().tokens;
9057
- const middleDouble = context.consumeArg().tokens;
9058
- const right = context.consumeArg().tokens;
9059
- const oldMiddle = context.macros.get("|");
9060
- const oldMiddleDouble = context.macros.get("\\|");
9061
- context.macros.beginGroup();
9062
- const midMacro = (double) => (context) => {
9063
- if (one) {
9064
- // Only modify the first instance of | or \|
9065
- context.macros.set("|", oldMiddle);
9066
- if (middleDouble.length) {
9067
- context.macros.set("\\|", oldMiddleDouble);
9068
- }
9069
- }
9070
- let doubled = double;
9071
- if (!double && middleDouble.length) {
9072
- // Mimic \@ifnextchar
9073
- const nextToken = context.future();
9074
- if (nextToken.text === "|") {
9075
- context.popToken();
9076
- doubled = true;
9077
- }
9078
- }
9079
- return {
9080
- tokens: doubled ? middleDouble : middle,
9081
- numArgs: 0
9082
- };
9083
- };
9084
- context.macros.set("|", midMacro(false));
9085
- if (middleDouble.length) {
9086
- context.macros.set("\\|", midMacro(true));
9087
- }
9088
- const arg = context.consumeArg().tokens;
9089
- const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed
9090
- context.macros.endGroup();
9091
- return {
9092
- tokens: expanded.reverse(),
9093
- numArgs: 0
9094
- };
9149
+ // A helper for \Braket and \Set
9150
+ const replaceVert = (argStr, match) => {
9151
+ const ch = match[0] === "|" ? "\\vert" : "\\Vert";
9152
+ const replaceStr = `}\\,\\middle${ch}\\,{`;
9153
+ return argStr.slice(0, match.index) + replaceStr + argStr.slice(match.index + match[0].length)
9095
9154
  };
9096
- defineMacro("\\bra@ket", braketHelper(false));
9097
- defineMacro("\\bra@set", braketHelper(true));
9098
- defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" +
9099
- "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");
9100
- defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" +
9101
- "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");
9102
- defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");
9103
- // has no support for special || or \|
9155
+ defineMacro("\\Braket", function(context) {
9156
+ let argStr = recreateArgStr(context);
9157
+ const regEx = /\|\||\||\\\|/g;
9158
+ let match;
9159
+ while ((match = regEx.exec(argStr)) !== null) {
9160
+ argStr = replaceVert(argStr, match);
9161
+ }
9162
+ return "\\left\\langle{" + argStr + "}\\right\\rangle"
9163
+ });
9164
+ defineMacro("\\Set", function(context) {
9165
+ let argStr = recreateArgStr(context);
9166
+ const match = /\|\||\||\\\|/.exec(argStr);
9167
+ if (match) {
9168
+ argStr = replaceVert(argStr, match);
9169
+ }
9170
+ return "\\left\\{\\:{" + argStr + "}\\:\\right\\}"
9171
+ });
9172
+ defineMacro("\\set", function(context) {
9173
+ const argStr = recreateArgStr(context);
9174
+ return "\\{{" + argStr.replace(/\|/, "}\\mid{") + "}\\}"
9175
+ });
9104
9176
 
9105
9177
  //////////////////////////////////////////////////////////////////////
9106
9178
  // actuarialangle.dtx
@@ -12149,8 +12221,12 @@ class Parser {
12149
12221
  * `breakOnTokenText`: The text of the token that the expression should end
12150
12222
  * with, or `null` if something else should end the
12151
12223
  * expression.
12224
+ *
12225
+ * `breakOnMiddle`: \color, \over, and old styling functions work on an implicit group.
12226
+ * These groups end just before the usual tokens, but they also
12227
+ * end just before `\middle`.
12152
12228
  */
12153
- parseExpression(breakOnInfix, breakOnTokenText) {
12229
+ parseExpression(breakOnInfix, breakOnTokenText, breakOnMiddle) {
12154
12230
  const body = [];
12155
12231
  // Keep adding atoms to the body until we can't parse any more atoms (either
12156
12232
  // we reached the end, a }, or a \right)
@@ -12166,6 +12242,9 @@ class Parser {
12166
12242
  if (breakOnTokenText && lex.text === breakOnTokenText) {
12167
12243
  break;
12168
12244
  }
12245
+ if (breakOnMiddle && lex.text === "\\middle") {
12246
+ break
12247
+ }
12169
12248
  if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
12170
12249
  break;
12171
12250
  }
@@ -13144,7 +13223,7 @@ class Style {
13144
13223
  * https://mit-license.org/
13145
13224
  */
13146
13225
 
13147
- const version = "0.10.21";
13226
+ const version = "0.10.23";
13148
13227
 
13149
13228
  function postProcess(block) {
13150
13229
  const labelMap = {};
package/dist/temml.d.ts CHANGED
@@ -41,7 +41,7 @@ declare class ParseError {
41
41
  constructor(
42
42
  message: string, // The error message
43
43
  token: any, // An object providing position information
44
- ) {}
44
+ );
45
45
  }
46
46
 
47
47
  declare const Temml: {