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