temml 0.10.32 → 0.10.33

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.
package/dist/temml.mjs CHANGED
@@ -499,6 +499,40 @@ let TextNode$1 = class TextNode {
499
499
  }
500
500
  };
501
501
 
502
+ // Create an <a href="…"> node.
503
+ class AnchorNode {
504
+ constructor(href, classes, children) {
505
+ this.href = href;
506
+ this.classes = classes;
507
+ this.children = children || [];
508
+ }
509
+
510
+ toNode() {
511
+ const node = document.createElement("a");
512
+ node.setAttribute("href", this.href);
513
+ if (this.classes.length > 0) {
514
+ node.className = createClass(this.classes);
515
+ }
516
+ for (let i = 0; i < this.children.length; i++) {
517
+ node.appendChild(this.children[i].toNode());
518
+ }
519
+ return node
520
+ }
521
+
522
+ toMarkup() {
523
+ let markup = `<a href='${utils.escape(this.href)}'`;
524
+ if (this.classes.length > 0) {
525
+ markup += ` class="${utils.escape(createClass(this.classes))}"`;
526
+ }
527
+ markup += ">";
528
+ for (let i = 0; i < this.children.length; i++) {
529
+ markup += this.children[i].toMarkup();
530
+ }
531
+ markup += "</a>";
532
+ return markup
533
+ }
534
+ }
535
+
502
536
  /*
503
537
  * This node represents an image embed (<img>) element.
504
538
  */
@@ -1528,7 +1562,7 @@ defineSymbol(math, open, "\u27e8", "\\langle", true);
1528
1562
  defineSymbol(math, open, "\u27ea", "\\lAngle", true);
1529
1563
  defineSymbol(math, open, "\u2989", "\\llangle", true);
1530
1564
  defineSymbol(math, open, "|", "\\lvert");
1531
- defineSymbol(math, open, "\u2016", "\\lVert");
1565
+ defineSymbol(math, open, "\u2016", "\\lVert", true);
1532
1566
  defineSymbol(math, textord, "!", "\\oc"); // cmll package
1533
1567
  defineSymbol(math, textord, "?", "\\wn");
1534
1568
  defineSymbol(math, textord, "\u2193", "\\shpos");
@@ -1692,7 +1726,7 @@ defineSymbol(math, inner, "\u22f0", "\\iddots", true);
1692
1726
  defineSymbol(math, inner, "\u22ef", "\\@cdots", true);
1693
1727
  defineSymbol(math, inner, "\u22f1", "\\ddots", true);
1694
1728
  defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
1695
- defineSymbol(text, textord, "\u22ee", "\\textvdots");
1729
+ defineSymbol(text, textord, "\u22ee", "\\varvdots");
1696
1730
  defineSymbol(math, accent, "\u02ca", "\\acute");
1697
1731
  defineSymbol(math, accent, "\u0060", "\\grave");
1698
1732
  defineSymbol(math, accent, "\u00a8", "\\ddot");
@@ -2145,61 +2179,6 @@ const consolidateText = mrow => {
2145
2179
  }
2146
2180
  };
2147
2181
 
2148
- const numberRegEx$1 = /^[0-9]$/;
2149
- const isDotOrComma = (node, followingNode) => {
2150
- return ((node.type === "textord" && node.text === ".") ||
2151
- (node.type === "atom" && node.text === ",")) &&
2152
- // Don't consolidate if there is a space after the comma.
2153
- node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
2154
- };
2155
- const consolidateNumbers = expression => {
2156
- // Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
2157
- // not <mn>1</mn><mo>,</mo><mn>5</mn><mn>0</mn><mn>6</mn><mi>.</mi><mn>3</mn>
2158
- if (expression.length < 2) { return }
2159
- const nums = [];
2160
- let inNum = false;
2161
- // Find adjacent numerals
2162
- for (let i = 0; i < expression.length; i++) {
2163
- const node = expression[i];
2164
- if (node.type === "textord" && numberRegEx$1.test(node.text)) {
2165
- if (!inNum) { nums.push({ start: i }); }
2166
- inNum = true;
2167
- } else {
2168
- if (inNum) { nums[nums.length - 1].end = i - 1; }
2169
- inNum = false;
2170
- }
2171
- }
2172
- if (inNum) { nums[nums.length - 1].end = expression.length - 1; }
2173
-
2174
- // Determine if numeral groups are separated by a comma or dot.
2175
- for (let i = nums.length - 1; i > 0; i--) {
2176
- if (nums[i - 1].end === nums[i].start - 2 &&
2177
- isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
2178
- // Merge the two groups.
2179
- nums[i - 1].end = nums[i].end;
2180
- nums.splice(i, 1);
2181
- }
2182
- }
2183
-
2184
- // Consolidate the number nodes
2185
- for (let i = nums.length - 1; i >= 0; i--) {
2186
- for (let j = nums[i].start + 1; j <= nums[i].end; j++) {
2187
- expression[nums[i].start].text += expression[j].text;
2188
- }
2189
- expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
2190
- // Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
2191
- // If so, merge the first <mn> into the base.
2192
- if (expression.length > nums[i].start + 1) {
2193
- const nextTerm = expression[nums[i].start + 1];
2194
- if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
2195
- numberRegEx$1.test(nextTerm.base.text)) {
2196
- nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
2197
- expression.splice(nums[i].start, 1);
2198
- }
2199
- }
2200
- }
2201
- };
2202
-
2203
2182
  /**
2204
2183
  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
2205
2184
  * unless the array has length 1. Always returns a single node.
@@ -2222,6 +2201,39 @@ const makeRow = function(body, semisimple = false) {
2222
2201
  return new mathMLTree.MathNode("mrow", body);
2223
2202
  };
2224
2203
 
2204
+ /**
2205
+ * Check for <mi>.</mi> which is how a dot renders in MathML,
2206
+ * or <mo separator="true" lspace="0em" rspace="0em">,</mo>
2207
+ * which is how a braced comma {,} renders in MathML
2208
+ */
2209
+ function isNumberPunctuation(group) {
2210
+ if (!group) {
2211
+ return false
2212
+ }
2213
+ if (group.type === 'mi' && group.children.length === 1) {
2214
+ const child = group.children[0];
2215
+ return child instanceof TextNode && child.text === '.'
2216
+ } else if (group.type === "mtext" && group.children.length === 1) {
2217
+ const child = group.children[0];
2218
+ return child instanceof TextNode && child.text === '\u2008' // punctuation space
2219
+ } else if (group.type === 'mo' && group.children.length === 1 &&
2220
+ group.getAttribute('separator') === 'true' &&
2221
+ group.getAttribute('lspace') === '0em' &&
2222
+ group.getAttribute('rspace') === '0em') {
2223
+ const child = group.children[0];
2224
+ return child instanceof TextNode && child.text === ','
2225
+ } else {
2226
+ return false
2227
+ }
2228
+ }
2229
+ const isComma = (expression, i) => {
2230
+ const node = expression[i];
2231
+ const followingNode = expression[i + 1];
2232
+ return (node.type === "atom" && node.text === ",") &&
2233
+ // Don't consolidate if there is a space after the comma.
2234
+ node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
2235
+ };
2236
+
2225
2237
  const isRel = item => {
2226
2238
  return (item.type === "atom" && item.family === "rel") ||
2227
2239
  (item.type === "mclass" && item.mclass === "mrel")
@@ -2245,11 +2257,16 @@ const buildExpression = function(expression, style, semisimple = false) {
2245
2257
  return [group];
2246
2258
  }
2247
2259
 
2248
- consolidateNumbers(expression);
2249
-
2250
2260
  const groups = [];
2261
+ const groupArray = [];
2262
+ let lastGroup;
2251
2263
  for (let i = 0; i < expression.length; i++) {
2252
- const group = buildGroup$1(expression[i], style);
2264
+ groupArray.push(buildGroup$1(expression[i], style));
2265
+ }
2266
+
2267
+ for (let i = 0; i < groupArray.length; i++) {
2268
+ const group = groupArray[i];
2269
+
2253
2270
  // Suppress spacing between adjacent relations
2254
2271
  if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) {
2255
2272
  group.setAttribute("rspace", "0em");
@@ -2257,9 +2274,39 @@ const buildExpression = function(expression, style, semisimple = false) {
2257
2274
  if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) {
2258
2275
  group.setAttribute("lspace", "0em");
2259
2276
  }
2277
+
2278
+ // Concatenate numbers
2279
+ if (group.type === 'mn' && lastGroup && lastGroup.type === 'mn') {
2280
+ // Concatenate <mn>...</mn> followed by <mi>.</mi>
2281
+ lastGroup.children.push(...group.children);
2282
+ continue
2283
+ } else if (isNumberPunctuation(group) && lastGroup && lastGroup.type === 'mn') {
2284
+ // Concatenate <mn>...</mn> followed by <mi>.</mi>
2285
+ lastGroup.children.push(...group.children);
2286
+ continue
2287
+ } else if (lastGroup && lastGroup.type === "mn" && i < groupArray.length - 1 &&
2288
+ groupArray[i + 1].type === "mn" && isComma(expression, i)) {
2289
+ lastGroup.children.push(...group.children);
2290
+ continue
2291
+ } else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) {
2292
+ // Concatenate <mi>.</mi> followed by <mn>...</mn>
2293
+ group.children = [...lastGroup.children, ...group.children];
2294
+ groups.pop();
2295
+ } else if ((group.type === 'msup' || group.type === 'msub') &&
2296
+ group.children.length >= 1 && lastGroup &&
2297
+ (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) {
2298
+ // Put preceding <mn>...</mn> or <mi>.</mi> inside base of
2299
+ // <msup><mn>...base...</mn>...exponent...</msup> (or <msub>)
2300
+ const base = group.children[0];
2301
+ if (base instanceof MathNode && base.type === 'mn' && lastGroup) {
2302
+ base.children = [...lastGroup.children, ...base.children];
2303
+ groups.pop();
2304
+ }
2305
+ }
2260
2306
  groups.push(group);
2307
+ lastGroup = group;
2261
2308
  }
2262
- return groups;
2309
+ return groups
2263
2310
  };
2264
2311
 
2265
2312
  /**
@@ -2321,6 +2368,11 @@ function buildMathML(tree, texExpression, style, settings) {
2321
2368
  }
2322
2369
 
2323
2370
  const expression = buildExpression(tree, style);
2371
+
2372
+ if (expression.length === 1 && expression[0] instanceof AnchorNode) {
2373
+ return expression[0]
2374
+ }
2375
+
2324
2376
  const wrap = (settings.displayMode || settings.annotate) ? "none" : settings.wrap;
2325
2377
 
2326
2378
  const n1 = expression.length === 0 ? null : expression[0];
@@ -2345,6 +2397,9 @@ function buildMathML(tree, texExpression, style, settings) {
2345
2397
  if (settings.xml) {
2346
2398
  math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
2347
2399
  }
2400
+ if (wrapper.style.width) {
2401
+ math.style.width = "100%";
2402
+ }
2348
2403
  if (settings.displayMode) {
2349
2404
  math.setAttribute("display", "block");
2350
2405
  math.style.display = "block math"; // necessary in Chromium.
@@ -2676,12 +2731,19 @@ const padding$2 = width => {
2676
2731
  return node
2677
2732
  };
2678
2733
 
2679
- const paddedNode = (group, lspace = 0.3, rspace = 0) => {
2734
+ const paddedNode = (group, lspace = 0.3, rspace = 0, mustSmash = false) => {
2680
2735
  if (group == null && rspace === 0) { return padding$2(lspace) }
2681
2736
  const row = group ? [group] : [];
2682
2737
  if (lspace !== 0) { row.unshift(padding$2(lspace)); }
2683
2738
  if (rspace > 0) { row.push(padding$2(rspace)); }
2684
- return new mathMLTree.MathNode("mrow", row)
2739
+ if (mustSmash) {
2740
+ // Used for the bottom arrow in a {CD} environment
2741
+ const mpadded = new mathMLTree.MathNode("mpadded", row);
2742
+ mpadded.setAttribute("height", "0");
2743
+ return mpadded
2744
+ } else {
2745
+ return new mathMLTree.MathNode("mrow", row)
2746
+ }
2685
2747
  };
2686
2748
 
2687
2749
  const labelSize = (size, scriptLevel) => Number(size) / emScale(scriptLevel);
@@ -2721,7 +2783,8 @@ const munderoverNode = (fName, body, below, style) => {
2721
2783
  (body.body.body || body.body.length > 0));
2722
2784
  if (gotUpper) {
2723
2785
  let label = buildGroup$1(body, labelStyle);
2724
- label = paddedNode(label, space, space);
2786
+ const mustSmash = (fName === "\\\\cdrightarrow" || fName === "\\\\cdleftarrow");
2787
+ label = paddedNode(label, space, space, mustSmash);
2725
2788
  // Since Firefox does not support minsize, stack a invisible node
2726
2789
  // on top of the label. Its width will serve as a min-width.
2727
2790
  // TODO: Refactor this after Firefox supports minsize.
@@ -3144,18 +3207,23 @@ defineFunction({
3144
3207
  };
3145
3208
  },
3146
3209
  mathmlBuilder(group, style) {
3147
- let label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, style)]);
3148
- label = new mathMLTree.MathNode("mpadded", [label]);
3149
- label.setAttribute("width", "0");
3150
- if (group.side === "left") {
3151
- label.setAttribute("lspace", "-1width");
3210
+ if (group.label.body.length === 0) {
3211
+ return new mathMLTree.MathNode("mrow", style) // empty label
3152
3212
  }
3153
- // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
3154
- // But we don't know the height or depth of the label.
3155
- label.setAttribute("voffset", "0.7em");
3156
- label = new mathMLTree.MathNode("mstyle", [label]);
3213
+ // Abuse an <mtable> to create vertically centered content.
3214
+ const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.label, style)]);
3215
+ mtd.style.padding = "0";
3216
+ const mtr = new mathMLTree.MathNode("mtr", [mtd]);
3217
+ const mtable = new mathMLTree.MathNode("mtable", [mtr]);
3218
+ const label = new mathMLTree.MathNode("mpadded", [mtable]);
3219
+ // Set the label width to zero so that the arrow will be centered under the corner cell.
3220
+ label.setAttribute("width", "0");
3157
3221
  label.setAttribute("displaystyle", "false");
3158
3222
  label.setAttribute("scriptlevel", "1");
3223
+ if (group.side === "left") {
3224
+ label.style.display = "flex";
3225
+ label.style.justifyContent = "flex-end";
3226
+ }
3159
3227
  return label;
3160
3228
  }
3161
3229
  });
@@ -3745,10 +3813,13 @@ defineFunction({
3745
3813
  // replacement text, enclosed in '{' and '}' and properly nested
3746
3814
  const { tokens } = parser.gullet.consumeArg();
3747
3815
 
3748
- parser.gullet.macros.set(
3749
- name,
3750
- { tokens, numArgs }
3751
- );
3816
+ if (!(funcName === "\\providecommand" && parser.gullet.macros.has(name))) {
3817
+ // Ignore \providecommand
3818
+ parser.gullet.macros.set(
3819
+ name,
3820
+ { tokens, numArgs }
3821
+ );
3822
+ }
3752
3823
 
3753
3824
  return { type: "internal", mode: parser.mode };
3754
3825
 
@@ -3842,6 +3913,7 @@ const delimiters = [
3842
3913
  "\\vert",
3843
3914
  "\\|",
3844
3915
  "\\Vert",
3916
+ "\u2016",
3845
3917
  "\\uparrow",
3846
3918
  "\\Uparrow",
3847
3919
  "\\downarrow",
@@ -4611,7 +4683,7 @@ defineMacro("\\underbar", "\\underline{\\text{#1}}");
4611
4683
  // \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
4612
4684
  // We'll call \varvdots, which gets a glyph from symbols.js.
4613
4685
  // The zero-width rule gets us an equivalent to the vertical 6pt kern.
4614
- defineMacro("\\vdots", "\\TextOrMath{\\textvdots}{{\\varvdots\\rule{0pt}{15pt}}}\\relax");
4686
+ defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}");
4615
4687
  defineMacro("\u22ee", "\\vdots");
4616
4688
 
4617
4689
  // {array} environment gaps
@@ -8074,6 +8146,7 @@ defineFunction({
8074
8146
  "\\mathfrak",
8075
8147
  "\\mathscr",
8076
8148
  "\\mathsf",
8149
+ "\\mathsfit",
8077
8150
  "\\mathtt",
8078
8151
 
8079
8152
  // aliases
@@ -8143,10 +8216,19 @@ const mathmlBuilder$5 = (group, style) => {
8143
8216
  ? style.withLevel(StyleLevel.SCRIPT)
8144
8217
  : style.withLevel(StyleLevel.SCRIPTSCRIPT);
8145
8218
 
8146
- let node = new mathMLTree.MathNode("mfrac", [
8147
- buildGroup$1(group.numer, childOptions),
8148
- buildGroup$1(group.denom, childOptions)
8149
- ]);
8219
+ // Chromium (wrongly) continues to shrink fractions beyond scriptscriptlevel.
8220
+ // So we check for levels that Chromium shrinks too small.
8221
+ // If necessary, set an explicit fraction depth.
8222
+ const numer = buildGroup$1(group.numer, childOptions);
8223
+ const denom = buildGroup$1(group.denom, childOptions);
8224
+ if (style.level === 3) {
8225
+ numer.style.mathDepth = "2";
8226
+ numer.setAttribute("scriptlevel", "2");
8227
+ denom.style.mathDepth = "2";
8228
+ denom.setAttribute("scriptlevel", "2");
8229
+ }
8230
+
8231
+ let node = new mathMLTree.MathNode("mfrac", [numer, denom]);
8150
8232
 
8151
8233
  if (!group.hasBarLine) {
8152
8234
  node.setAttribute("linethickness", "0px");
@@ -8539,12 +8621,9 @@ defineFunction({
8539
8621
  };
8540
8622
  },
8541
8623
  mathmlBuilder: (group, style) => {
8542
- let math = buildExpressionRow(group.body, style);
8543
- if (!(math instanceof MathNode)) {
8544
- math = new MathNode("mrow", [math]);
8545
- }
8546
- math.setAttribute("href", group.href);
8547
- return math;
8624
+ const math = new MathNode("math", [buildExpressionRow(group.body, style)]);
8625
+ const anchorNode = new AnchorNode(group.href, [], [math]);
8626
+ return anchorNode
8548
8627
  }
8549
8628
  });
8550
8629
 
@@ -9416,13 +9495,6 @@ const mathmlBuilder$2 = (group, style) => {
9416
9495
  node = new MathNode("mo", [makeText(group.name, group.mode)]);
9417
9496
  if (noSuccessor.includes(group.name)) {
9418
9497
  node.setAttribute("largeop", "false");
9419
- } else if (group.limits) {
9420
- // This is a workaround for a MathML/Chromium bug.
9421
- // This is being applied to singleCharBigOps, which are not really stretchy.
9422
- // But by setting the stretchy attribute, Chromium will vertically center
9423
- // big ops around the math axis. This is needed since STIX TWO does not do so.
9424
- // TODO: Remove this hack when MathML & Chromium fix their problem.
9425
- node.setAttribute("stretchy", "true");
9426
9498
  } else {
9427
9499
  node.setAttribute("movablelimits", "false");
9428
9500
  }
@@ -10057,12 +10129,10 @@ defineFunction({
10057
10129
  };
10058
10130
  },
10059
10131
  mathmlBuilder(group, style) {
10060
- // Create an empty text node. Set a class and an href.
10132
+ // Create an empty <a> node. Set a class and an href attribute.
10061
10133
  // The post-processor will populate with the target's tag or equation number.
10062
10134
  const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"];
10063
- const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes);
10064
- node.setAttribute("href", "#" + group.string);
10065
- return node
10135
+ return new AnchorNode("#" + group.string, classes, null)
10066
10136
  }
10067
10137
  });
10068
10138
 
@@ -10109,6 +10179,8 @@ defineFunction({
10109
10179
  props: {
10110
10180
  numArgs: 2,
10111
10181
  numOptionalArgs: 1,
10182
+ allowedInText: true,
10183
+ allowedInMath: true,
10112
10184
  argTypes: ["size", "size", "size"]
10113
10185
  },
10114
10186
  handler({ parser }, args, optArgs) {
@@ -10401,16 +10473,25 @@ defineFunctionBuilders({
10401
10473
  ? [buildGroup$1(group.base.body[0], style)]
10402
10474
  : [buildGroup$1(group.base, style)];
10403
10475
 
10476
+ // Note regarding scriptstyle level.
10477
+ // (Sub|super)scripts should not shrink beyond MathML scriptlevel 2 aka \scriptscriptstyle
10478
+ // Ref: https://w3c.github.io/mathml-core/#the-displaystyle-and-scriptlevel-attributes
10479
+ // (BTW, MathML scriptlevel 2 is equal to Temml level 3.)
10480
+ // But Chromium continues to shrink the (sub|super)scripts. So we explicitly set scriptlevel 2.
10481
+
10404
10482
  const childStyle = style.inSubOrSup();
10405
10483
  if (group.sub) {
10406
- children.push(buildGroup$1(group.sub, childStyle));
10484
+ const sub = buildGroup$1(group.sub, childStyle);
10485
+ if (style.level === 3) { sub.setAttribute("scriptlevel", "2"); }
10486
+ children.push(sub);
10407
10487
  }
10408
10488
 
10409
10489
  if (group.sup) {
10410
10490
  const sup = buildGroup$1(group.sup, childStyle);
10491
+ if (style.level === 3) { sup.setAttribute("scriptlevel", "2"); }
10411
10492
  const testNode = sup.type === "mrow" ? sup.children[0] : sup;
10412
10493
  if ((testNode && testNode.type === "mo" && testNode.classes.includes("tml-prime"))
10413
- && group.base && group.base.text && group.base.text === "f") {
10494
+ && group.base && group.base.text && "fF".indexOf(group.base.text) > -1) {
10414
10495
  // Chromium does not address italic correction on prime. Prevent f′ from overlapping.
10415
10496
  testNode.classes.push("prime-pad");
10416
10497
  }
@@ -10637,6 +10718,8 @@ const getVariant = function(group, style) {
10637
10718
  return "script"
10638
10719
  case "mathsf":
10639
10720
  return "sans-serif"
10721
+ case "mathsfit":
10722
+ return "sans-serif-italic"
10640
10723
  case "mathtt":
10641
10724
  return "monospace"
10642
10725
  }
@@ -11101,6 +11184,32 @@ defineFunction({
11101
11184
  }
11102
11185
  });
11103
11186
 
11187
+ // \vcenter: Vertically center the argument group on the math axis.
11188
+
11189
+ defineFunction({
11190
+ type: "vcenter",
11191
+ names: ["\\vcenter"],
11192
+ props: {
11193
+ numArgs: 1,
11194
+ argTypes: ["original"],
11195
+ allowedInText: false
11196
+ },
11197
+ handler({ parser }, args) {
11198
+ return {
11199
+ type: "vcenter",
11200
+ mode: parser.mode,
11201
+ body: args[0]
11202
+ };
11203
+ },
11204
+ mathmlBuilder(group, style) {
11205
+ // Use a math table to create vertically centered content.
11206
+ const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.body, style)]);
11207
+ mtd.style.padding = "0";
11208
+ const mtr = new mathMLTree.MathNode("mtr", [mtd]);
11209
+ return new mathMLTree.MathNode("mtable", [mtr])
11210
+ }
11211
+ });
11212
+
11104
11213
  defineFunction({
11105
11214
  type: "verb",
11106
11215
  names: ["\\verb"],
@@ -13367,9 +13476,11 @@ class Style {
13367
13476
  constructor(data) {
13368
13477
  // Style.level can be 0 | 1 | 2 | 3, which correspond to
13369
13478
  // displaystyle, textstyle, scriptstyle, and scriptscriptstyle.
13370
- // style.level does not directly set MathML's script level. MathML does that itself.
13371
- // We use style.level to track, not set, math style so that we can get the
13372
- // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em.
13479
+ // style.level usually does not directly set MathML's script level. MathML does that itself.
13480
+ // However, Chromium does not stop shrinking after scriptscriptstyle, so we do explicitly
13481
+ // set a scriptlevel attribute in those conditions.
13482
+ // We also use style.level to track math style so that we can get the correct
13483
+ // scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em.
13373
13484
  this.level = data.level;
13374
13485
  this.color = data.color; // string | void
13375
13486
  // A font family applies to a group of fonts (i.e. SansSerif), while a font
@@ -13493,39 +13604,47 @@ class Style {
13493
13604
  }
13494
13605
 
13495
13606
  /* Temml Post Process
13496
- * Perform two tasks not done by Temml when it created each individual Temml <math> element.
13497
- * Given a block,
13498
- * 1. At each AMS auto-numbered environment, assign an id.
13499
- * 2. Populate the text contents of each \ref & \eqref
13607
+ * Populate the text contents of each \ref & \eqref
13500
13608
  *
13501
13609
  * As with other Temml code, this file is released under terms of the MIT license.
13502
13610
  * https://mit-license.org/
13503
13611
  */
13504
13612
 
13505
- const version = "0.10.32";
13613
+ const version = "0.10.33";
13506
13614
 
13507
13615
  function postProcess(block) {
13508
13616
  const labelMap = {};
13509
13617
  let i = 0;
13510
13618
 
13511
13619
  // Get a collection of the parents of each \tag & auto-numbered equation
13512
- const parents = block.getElementsByClassName("tml-tageqn");
13513
- for (const parent of parents) {
13514
- const eqns = parent.getElementsByClassName("tml-eqn");
13515
- if (eqns. length > 0 ) {
13516
- // AMS automatically numbered equation.
13517
- // Assign an id.
13518
- i += 1;
13519
- eqns[0].id = "tml-eqn-" + i;
13520
- // No need to write a number into the text content of the element.
13521
- // A CSS counter does that even if this postProcess() function is not used.
13620
+ const amsEqns = document.getElementsByClassName('tml-eqn');
13621
+ for (let parent of amsEqns) {
13622
+ // AMS automatically numbered equation.
13623
+ // Assign an id.
13624
+ i += 1;
13625
+ parent.setAttribute("id", "tml-eqn-" + String(i));
13626
+ // No need to write a number into the text content of the element.
13627
+ // A CSS counter has done that even if this postProcess() function is not used.
13628
+
13629
+ // Find any \label that refers to an AMS eqn number.
13630
+ while (true) {
13631
+ const labels = parent.getElementsByClassName("tml-label");
13632
+ if (labels.length > 0) {
13633
+ parent.setAttribute("id", labels[0].id);
13634
+ labelMap[labels[0].id] = String(i);
13635
+ break
13636
+ } else {
13637
+ if (parent.tagName === "mtable") { break }
13638
+ parent = parent.parentElement;
13639
+ }
13522
13640
  }
13523
- // If there is a \label, add it to labelMap
13641
+ }
13642
+
13643
+ // Find \labels associated with \tag
13644
+ const taggedEqns = document.getElementsByClassName('tml-tageqn');
13645
+ for (const parent of taggedEqns) {
13524
13646
  const labels = parent.getElementsByClassName("tml-label");
13525
- if (labels.length === 0) { continue }
13526
- if (eqns.length > 0) {
13527
- labelMap[labels[0].id] = String(i);
13528
- } else {
13647
+ if (labels.length > 0) {
13529
13648
  const tags = parent.getElementsByClassName("tml-tag");
13530
13649
  if (tags.length > 0) {
13531
13650
  labelMap[labels[0].id] = tags[0].textContent;
@@ -13536,17 +13655,22 @@ function postProcess(block) {
13536
13655
  // Populate \ref & \eqref text content
13537
13656
  const refs = block.getElementsByClassName("tml-ref");
13538
13657
  [...refs].forEach(ref => {
13539
- let str = labelMap[ref.getAttribute("href").slice(1)];
13658
+ const attr = ref.getAttribute("href");
13659
+ let str = labelMap[attr.slice(1)];
13540
13660
  if (ref.className.indexOf("tml-eqref") === -1) {
13541
13661
  // \ref. Omit parens.
13542
13662
  str = str.replace(/^\(/, "");
13543
- str = str.replace(/\($/, "");
13544
- } {
13663
+ str = str.replace(/\)$/, "");
13664
+ } else {
13545
13665
  // \eqref. Include parens
13546
13666
  if (str.charAt(0) !== "(") { str = "(" + str; }
13547
13667
  if (str.slice(-1) !== ")") { str = str + ")"; }
13548
13668
  }
13549
- ref.textContent = str;
13669
+ const mtext = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mtext");
13670
+ mtext.appendChild(document.createTextNode(str));
13671
+ const math = document.createElementNS("http://www.w3.org/1998/Math/MathML", "math");
13672
+ math.appendChild(mtext);
13673
+ ref.appendChild(math);
13550
13674
  });
13551
13675
  }
13552
13676