temml 0.10.20 → 0.10.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }
@@ -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);
@@ -1408,6 +1410,7 @@ defineSymbol(math, mathord, "\u2aeb", "\\Bot");
1408
1410
  defineSymbol(math, bin, "\u2217", "\u2217", true);
1409
1411
  defineSymbol(math, bin, "+", "+");
1410
1412
  defineSymbol(math, bin, "*", "*");
1413
+ defineSymbol(math, bin, "\u2044", "/", true);
1411
1414
  defineSymbol(math, bin, "\u2044", "\u2044");
1412
1415
  defineSymbol(math, bin, "\u2212", "-", true);
1413
1416
  defineSymbol(math, bin, "\u22c5", "\\cdot", true);
@@ -1864,7 +1867,8 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
1864
1867
  continue
1865
1868
  }
1866
1869
  block.push(node);
1867
- if (node.type && node.type === "mo" && node.children.length === 1) {
1870
+ if (node.type && node.type === "mo" && node.children.length === 1 &&
1871
+ !Object.hasOwn(node.attributes, "movablelimits")) {
1868
1872
  const ch = node.children[0].text;
1869
1873
  if (openDelims.indexOf(ch) > -1) {
1870
1874
  level += 1;
@@ -1879,7 +1883,7 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
1879
1883
  mrows.push(element);
1880
1884
  block = [node];
1881
1885
  }
1882
- } else if (level === 0 && wrapMode === "tex") {
1886
+ } else if (level === 0 && wrapMode === "tex" && ch !== "∇") {
1883
1887
  // Check if the following node is a \nobreak text node, e.g. "~""
1884
1888
  const next = i < expression.length - 1 ? expression[i + 1] : null;
1885
1889
  let glueIsFreeOfNobreak = true;
@@ -3247,7 +3251,7 @@ defineFunction({
3247
3251
  allowedInText: true,
3248
3252
  argTypes: ["raw", "raw"]
3249
3253
  },
3250
- handler({ parser, token }, args, optArgs) {
3254
+ handler({ parser, breakOnTokenText, token }, args, optArgs) {
3251
3255
  const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string;
3252
3256
  let color = "";
3253
3257
  if (model) {
@@ -3257,15 +3261,8 @@ defineFunction({
3257
3261
  color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token);
3258
3262
  }
3259
3263
 
3260
- // Set macro \current@color in current namespace to store the current
3261
- // color, mimicking the behavior of color.sty.
3262
- // This is currently used just to correctly color a \right
3263
- // that follows a \color command.
3264
- parser.gullet.macros.set("\\current@color", color);
3265
-
3266
3264
  // Parse out the implicit body that should be colored.
3267
- // Since \color nodes should not be nested, break on \color.
3268
- const body = parser.parseExpression(true, "\\color");
3265
+ const body = parser.parseExpression(true, breakOnTokenText, true);
3269
3266
 
3270
3267
  return {
3271
3268
  type: "color",
@@ -3707,17 +3704,13 @@ const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
3707
3704
 
3708
3705
  // Delimiter functions
3709
3706
  function checkDelimiter(delim, context) {
3710
- if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") {
3711
- // Recover "/" from the zero spacing group. (See macros.js)
3712
- delim = { type: "textord", text: "/", mode: "math" };
3713
- }
3714
3707
  const symDelim = checkSymbolNodeType(delim);
3715
3708
  if (symDelim && delimiters.includes(symDelim.text)) {
3716
3709
  // If a character is not in the MathML operator dictionary, it will not stretch.
3717
3710
  // Replace such characters w/characters that will stretch.
3711
+ if (["/", "\u2044"].includes(symDelim.text)) { symDelim.text = "\u2215"; }
3718
3712
  if (["<", "\\lt"].includes(symDelim.text)) { symDelim.text = "⟨"; }
3719
3713
  if ([">", "\\gt"].includes(symDelim.text)) { symDelim.text = "⟩"; }
3720
- if (symDelim.text === "/") { symDelim.text = "\u2215"; }
3721
3714
  if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; }
3722
3715
  return symDelim;
3723
3716
  } else if (symDelim) {
@@ -3805,18 +3798,10 @@ defineFunction({
3805
3798
  argTypes: ["primitive"]
3806
3799
  },
3807
3800
  handler: (context, args) => {
3808
- // \left case below triggers parsing of \right in
3809
- // `const right = parser.parseFunction();`
3810
- // uses this return value.
3811
- const color = context.parser.gullet.macros.get("\\current@color");
3812
- if (color && typeof color !== "string") {
3813
- throw new ParseError("\\current@color set to non-string in \\right");
3814
- }
3815
3801
  return {
3816
3802
  type: "leftright-right",
3817
3803
  mode: context.parser.mode,
3818
- delim: checkDelimiter(args[0], context).text,
3819
- color // undefined if not set via \color
3804
+ delim: checkDelimiter(args[0], context).text
3820
3805
  };
3821
3806
  }
3822
3807
  });
@@ -3834,8 +3819,26 @@ defineFunction({
3834
3819
  const parser = context.parser;
3835
3820
  // Parse out the implicit body
3836
3821
  ++parser.leftrightDepth;
3837
- // parseExpression stops before '\\right'
3838
- const body = parser.parseExpression(false);
3822
+ // parseExpression stops before '\\right' or `\\middle`
3823
+ let body = parser.parseExpression(false, null, true);
3824
+ let nextToken = parser.fetch();
3825
+ while (nextToken.text === "\\middle") {
3826
+ // `\middle`, from the ε-TeX package, ends one group and starts another group.
3827
+ // We had to parse this expression with `breakOnMiddle` enabled in order
3828
+ // to get TeX-compliant parsing of \over.
3829
+ // But we do not want, at this point, to end on \middle, so continue
3830
+ // to parse until we fetch a `\right`.
3831
+ parser.consume();
3832
+ const middle = parser.fetch().text;
3833
+ if (!symbols.math[middle]) {
3834
+ throw new ParseError(`Invalid delimiter '${middle}' after '\\middle'`);
3835
+ }
3836
+ checkDelimiter({ type: "atom", mode: "math", text: middle }, { funcName: "\\middle" });
3837
+ body.push({ type: "middle", mode: "math", delim: middle });
3838
+ parser.consume();
3839
+ body = body.concat(parser.parseExpression(false, null, true));
3840
+ nextToken = parser.fetch();
3841
+ }
3839
3842
  --parser.leftrightDepth;
3840
3843
  // Check the next token
3841
3844
  parser.expect("\\right", false);
@@ -3845,8 +3848,7 @@ defineFunction({
3845
3848
  mode: parser.mode,
3846
3849
  body,
3847
3850
  left: delim.text,
3848
- right: right.delim,
3849
- rightColor: right.color
3851
+ right: right.delim
3850
3852
  };
3851
3853
  },
3852
3854
  mathmlBuilder: (group, style) => {
@@ -3869,7 +3871,6 @@ defineFunction({
3869
3871
  if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
3870
3872
  rightNode.setAttribute("stretchy", "true");
3871
3873
  }
3872
- if (group.rightColor) { rightNode.style.color = group.rightColor; }
3873
3874
  inner.push(rightNode);
3874
3875
 
3875
3876
  return makeRow(inner);
@@ -5212,7 +5213,7 @@ defineFunction({
5212
5213
  },
5213
5214
  handler: ({ parser, funcName, breakOnTokenText }, args) => {
5214
5215
  const { mode } = parser;
5215
- const body = parser.parseExpression(true, breakOnTokenText);
5216
+ const body = parser.parseExpression(true, breakOnTokenText, true);
5216
5217
  const fontStyle = `math${funcName.slice(1)}`;
5217
5218
 
5218
5219
  return {
@@ -6173,6 +6174,9 @@ function mathmlBuilder$3(group, style) {
6173
6174
  if (group.isCharacterBox || inner[0].type === "mathord") {
6174
6175
  node = inner[0];
6175
6176
  node.type = "mi";
6177
+ if (node.children.length === 1 && node.children[0].text && node.children[0].text === "∇") {
6178
+ node.setAttribute("mathvariant", "normal");
6179
+ }
6176
6180
  } else {
6177
6181
  node = new mathMLTree.MathNode("mi", inner);
6178
6182
  }
@@ -7160,6 +7164,28 @@ defineFunction({
7160
7164
  }
7161
7165
  });
7162
7166
 
7167
+ defineFunction({
7168
+ type: "reflect",
7169
+ names: ["\\reflectbox"],
7170
+ props: {
7171
+ numArgs: 1,
7172
+ argTypes: ["hbox"],
7173
+ allowedInText: true
7174
+ },
7175
+ handler({ parser }, args) {
7176
+ return {
7177
+ type: "reflect",
7178
+ mode: parser.mode,
7179
+ body: args[0]
7180
+ };
7181
+ },
7182
+ mathmlBuilder(group, style) {
7183
+ const node = buildGroup$1(group.body, style);
7184
+ node.style.transform = "scaleX(-1)";
7185
+ return node
7186
+ }
7187
+ });
7188
+
7163
7189
  defineFunction({
7164
7190
  type: "internal",
7165
7191
  names: ["\\relax"],
@@ -7265,7 +7291,7 @@ defineFunction({
7265
7291
  // eslint-disable-next-line no-console
7266
7292
  console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`);
7267
7293
  }
7268
- const body = parser.parseExpression(false, breakOnTokenText);
7294
+ const body = parser.parseExpression(false, breakOnTokenText, true);
7269
7295
  return {
7270
7296
  type: "sizing",
7271
7297
  mode: parser.mode,
@@ -7398,7 +7424,7 @@ defineFunction({
7398
7424
  },
7399
7425
  handler({ breakOnTokenText, funcName, parser }, args) {
7400
7426
  // parse out the implicit body
7401
- const body = parser.parseExpression(true, breakOnTokenText);
7427
+ const body = parser.parseExpression(true, breakOnTokenText, true);
7402
7428
 
7403
7429
  const scriptLevel = funcName.slice(1, funcName.length - 5);
7404
7430
  return {
@@ -7829,22 +7855,22 @@ const offset = Object.freeze({
7829
7855
  "sans-serif-bold-italic": ch => { return 0x1D5F5 },
7830
7856
  "monospace": ch => { return 0x1D629 }
7831
7857
  },
7832
- upperCaseGreek: { // A-Ω
7858
+ upperCaseGreek: { // A-Ω
7833
7859
  "normal": ch => { return 0 },
7834
- "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 },
7835
- "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 },
7860
+ "bold": ch => { return 0x1D317 },
7861
+ "italic": ch => { return 0x1D351 },
7836
7862
  // \boldsymbol actually returns upright bold for upperCaseGreek
7837
- "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 },
7863
+ "bold-italic": ch => { return 0x1D317 },
7838
7864
  "script": ch => { return 0 },
7839
7865
  "script-bold": ch => { return 0 },
7840
7866
  "fraktur": ch => { return 0 },
7841
7867
  "fraktur-bold": ch => { return 0 },
7842
7868
  "double-struck": ch => { return 0 },
7843
7869
  // Unicode has no code points for regular-weight san-serif Greek. Use bold.
7844
- "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 },
7845
- "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 },
7870
+ "sans-serif": ch => { return 0x1D3C5 },
7871
+ "sans-serif-bold": ch => { return 0x1D3C5 },
7846
7872
  "sans-serif-italic": ch => { return 0 },
7847
- "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF },
7873
+ "sans-serif-bold-italic": ch => { return 0x1D3FF },
7848
7874
  "monospace": ch => { return 0 }
7849
7875
  },
7850
7876
  lowerCaseGreek: { // α-ω
@@ -7904,7 +7930,7 @@ const variantChar = (ch, variant) => {
7904
7930
  ? "upperCaseLatin"
7905
7931
  : 0x60 < codePoint && codePoint < 0x7b
7906
7932
  ? "lowerCaseLatin"
7907
- : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇"
7933
+ : (0x390 < codePoint && codePoint < 0x3AA)
7908
7934
  ? "upperCaseGreek"
7909
7935
  : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5"
7910
7936
  ? "lowerCaseGreek"
@@ -8033,8 +8059,6 @@ defineFunctionBuilders({
8033
8059
  node = new mathMLTree.MathNode("mi", [text]);
8034
8060
  if (text.text === origText && latinRegEx.test(origText)) {
8035
8061
  node.setAttribute("mathvariant", "italic");
8036
- } else if (text.text === "∇" && variant === "normal") {
8037
- node.setAttribute("mathvariant", "normal");
8038
8062
  }
8039
8063
  }
8040
8064
  return node
@@ -8671,6 +8695,24 @@ defineMacro("\\char", function(context) {
8671
8695
  return `\\@char{${number}}`;
8672
8696
  });
8673
8697
 
8698
+ function recreateArgStr(context) {
8699
+ // Recreate the macro's original argument string from the array of parse tokens.
8700
+ const tokens = context.consumeArgs(1)[0];
8701
+ let str = "";
8702
+ let expectedLoc = tokens[tokens.length - 1].loc.start;
8703
+ for (let i = tokens.length - 1; i >= 0; i--) {
8704
+ const actualLoc = tokens[i].loc.start;
8705
+ if (actualLoc > expectedLoc) {
8706
+ // context.consumeArgs has eaten a space.
8707
+ str += " ";
8708
+ expectedLoc = actualLoc;
8709
+ }
8710
+ str += tokens[i].text;
8711
+ expectedLoc += tokens[i].text.length;
8712
+ }
8713
+ return str
8714
+ }
8715
+
8674
8716
  // The Latin Modern font renders <mi>√</mi> at the wrong vertical alignment.
8675
8717
  // This macro provides a better rendering.
8676
8718
  defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
@@ -8678,10 +8720,6 @@ defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
8678
8720
  // See comment for \oplus in symbols.js.
8679
8721
  defineMacro("\u2295", "\\oplus");
8680
8722
 
8681
- // Per TeXbook p.122, "/" gets zero operator spacing.
8682
- // And MDN recommends using U+2044 instead of / for inline
8683
- defineMacro("/", "{\u2044}");
8684
-
8685
8723
  // Since Temml has no \par, ignore \long.
8686
8724
  defineMacro("\\long", "");
8687
8725
 
@@ -9059,6 +9097,11 @@ defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
9059
9097
  defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
9060
9098
  defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}");
9061
9099
 
9100
+ //////////////////////////////////////////////////////////////////////
9101
+ // MnSymbol.sty
9102
+
9103
+ defineMacro("\\leftmodels", "\\mathop{\\reflectbox{$\\models$}}");
9104
+
9062
9105
  //////////////////////////////////////////////////////////////////////
9063
9106
  // braket.sty
9064
9107
  // http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
@@ -9068,56 +9111,33 @@ defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
9068
9111
  defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
9069
9112
  defineMacro("\\Bra", "\\left\\langle#1\\right|");
9070
9113
  defineMacro("\\Ket", "\\left|#1\\right\\rangle");
9071
- const braketHelper = (one) => (context) => {
9072
- const left = context.consumeArg().tokens;
9073
- const middle = context.consumeArg().tokens;
9074
- const middleDouble = context.consumeArg().tokens;
9075
- const right = context.consumeArg().tokens;
9076
- const oldMiddle = context.macros.get("|");
9077
- const oldMiddleDouble = context.macros.get("\\|");
9078
- context.macros.beginGroup();
9079
- const midMacro = (double) => (context) => {
9080
- if (one) {
9081
- // Only modify the first instance of | or \|
9082
- context.macros.set("|", oldMiddle);
9083
- if (middleDouble.length) {
9084
- context.macros.set("\\|", oldMiddleDouble);
9085
- }
9086
- }
9087
- let doubled = double;
9088
- if (!double && middleDouble.length) {
9089
- // Mimic \@ifnextchar
9090
- const nextToken = context.future();
9091
- if (nextToken.text === "|") {
9092
- context.popToken();
9093
- doubled = true;
9094
- }
9095
- }
9096
- return {
9097
- tokens: doubled ? middleDouble : middle,
9098
- numArgs: 0
9099
- };
9100
- };
9101
- context.macros.set("|", midMacro(false));
9102
- if (middleDouble.length) {
9103
- context.macros.set("\\|", midMacro(true));
9104
- }
9105
- const arg = context.consumeArg().tokens;
9106
- const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed
9107
- context.macros.endGroup();
9108
- return {
9109
- tokens: expanded.reverse(),
9110
- numArgs: 0
9111
- };
9114
+ // A helper for \Braket and \Set
9115
+ const replaceVert = (argStr, match) => {
9116
+ const ch = match[0] === "|" ? "\\vert" : "\\Vert";
9117
+ const replaceStr = `}\\,\\middle${ch}\\,{`;
9118
+ return argStr.slice(0, match.index) + replaceStr + argStr.slice(match.index + match[0].length)
9112
9119
  };
9113
- defineMacro("\\bra@ket", braketHelper(false));
9114
- defineMacro("\\bra@set", braketHelper(true));
9115
- defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" +
9116
- "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");
9117
- defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" +
9118
- "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");
9119
- defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");
9120
- // has no support for special || or \|
9120
+ defineMacro("\\Braket", function(context) {
9121
+ let argStr = recreateArgStr(context);
9122
+ const regEx = /\|\||\||\\\|/g;
9123
+ let match;
9124
+ while ((match = regEx.exec(argStr)) !== null) {
9125
+ argStr = replaceVert(argStr, match);
9126
+ }
9127
+ return "\\left\\langle{" + argStr + "}\\right\\rangle"
9128
+ });
9129
+ defineMacro("\\Set", function(context) {
9130
+ let argStr = recreateArgStr(context);
9131
+ const match = /\|\||\||\\\|/.exec(argStr);
9132
+ if (match) {
9133
+ argStr = replaceVert(argStr, match);
9134
+ }
9135
+ return "\\left\\{\\:{" + argStr + "}\\:\\right\\}"
9136
+ });
9137
+ defineMacro("\\set", function(context) {
9138
+ const argStr = recreateArgStr(context);
9139
+ return "\\{{" + argStr.replace(/\|/, "}\\mid{") + "}\\}"
9140
+ });
9121
9141
 
9122
9142
  //////////////////////////////////////////////////////////////////////
9123
9143
  // actuarialangle.dtx
@@ -12166,8 +12186,12 @@ class Parser {
12166
12186
  * `breakOnTokenText`: The text of the token that the expression should end
12167
12187
  * with, or `null` if something else should end the
12168
12188
  * expression.
12189
+ *
12190
+ * `breakOnMiddle`: \color, \over, and old styling functions work on an implicit group.
12191
+ * These groups end just before the usual tokens, but they also
12192
+ * end just before `\middle`.
12169
12193
  */
12170
- parseExpression(breakOnInfix, breakOnTokenText) {
12194
+ parseExpression(breakOnInfix, breakOnTokenText, breakOnMiddle) {
12171
12195
  const body = [];
12172
12196
  // Keep adding atoms to the body until we can't parse any more atoms (either
12173
12197
  // we reached the end, a }, or a \right)
@@ -12183,6 +12207,9 @@ class Parser {
12183
12207
  if (breakOnTokenText && lex.text === breakOnTokenText) {
12184
12208
  break;
12185
12209
  }
12210
+ if (breakOnMiddle && lex.text === "\\middle") {
12211
+ break
12212
+ }
12186
12213
  if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
12187
12214
  break;
12188
12215
  }
@@ -13161,7 +13188,7 @@ class Style {
13161
13188
  * https://mit-license.org/
13162
13189
  */
13163
13190
 
13164
- const version = "0.10.20";
13191
+ const version = "0.10.22";
13165
13192
 
13166
13193
  function postProcess(block) {
13167
13194
  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: {