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.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,6 +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
1729
+ defineSymbol(text, textord, "\u22ee", "\\varvdots");
1695
1730
  defineSymbol(math, accent, "\u02ca", "\\acute");
1696
1731
  defineSymbol(math, accent, "\u0060", "\\grave");
1697
1732
  defineSymbol(math, accent, "\u00a8", "\\ddot");
@@ -2144,61 +2179,6 @@ const consolidateText = mrow => {
2144
2179
  }
2145
2180
  };
2146
2181
 
2147
- const numberRegEx$1 = /^[0-9]$/;
2148
- const isDotOrComma = (node, followingNode) => {
2149
- return ((node.type === "textord" && node.text === ".") ||
2150
- (node.type === "atom" && node.text === ",")) &&
2151
- // Don't consolidate if there is a space after the comma.
2152
- node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
2153
- };
2154
- const consolidateNumbers = expression => {
2155
- // Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
2156
- // not <mn>1</mn><mo>,</mo><mn>5</mn><mn>0</mn><mn>6</mn><mi>.</mi><mn>3</mn>
2157
- if (expression.length < 2) { return }
2158
- const nums = [];
2159
- let inNum = false;
2160
- // Find adjacent numerals
2161
- for (let i = 0; i < expression.length; i++) {
2162
- const node = expression[i];
2163
- if (node.type === "textord" && numberRegEx$1.test(node.text)) {
2164
- if (!inNum) { nums.push({ start: i }); }
2165
- inNum = true;
2166
- } else {
2167
- if (inNum) { nums[nums.length - 1].end = i - 1; }
2168
- inNum = false;
2169
- }
2170
- }
2171
- if (inNum) { nums[nums.length - 1].end = expression.length - 1; }
2172
-
2173
- // Determine if numeral groups are separated by a comma or dot.
2174
- for (let i = nums.length - 1; i > 0; i--) {
2175
- if (nums[i - 1].end === nums[i].start - 2 &&
2176
- isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
2177
- // Merge the two groups.
2178
- nums[i - 1].end = nums[i].end;
2179
- nums.splice(i, 1);
2180
- }
2181
- }
2182
-
2183
- // Consolidate the number nodes
2184
- for (let i = nums.length - 1; i >= 0; i--) {
2185
- for (let j = nums[i].start + 1; j <= nums[i].end; j++) {
2186
- expression[nums[i].start].text += expression[j].text;
2187
- }
2188
- expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
2189
- // Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
2190
- // If so, merge the first <mn> into the base.
2191
- if (expression.length > nums[i].start + 1) {
2192
- const nextTerm = expression[nums[i].start + 1];
2193
- if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
2194
- numberRegEx$1.test(nextTerm.base.text)) {
2195
- nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
2196
- expression.splice(nums[i].start, 1);
2197
- }
2198
- }
2199
- }
2200
- };
2201
-
2202
2182
  /**
2203
2183
  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
2204
2184
  * unless the array has length 1. Always returns a single node.
@@ -2221,6 +2201,39 @@ const makeRow = function(body, semisimple = false) {
2221
2201
  return new mathMLTree.MathNode("mrow", body);
2222
2202
  };
2223
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
+
2224
2237
  const isRel = item => {
2225
2238
  return (item.type === "atom" && item.family === "rel") ||
2226
2239
  (item.type === "mclass" && item.mclass === "mrel")
@@ -2244,11 +2257,16 @@ const buildExpression = function(expression, style, semisimple = false) {
2244
2257
  return [group];
2245
2258
  }
2246
2259
 
2247
- consolidateNumbers(expression);
2248
-
2249
2260
  const groups = [];
2261
+ const groupArray = [];
2262
+ let lastGroup;
2250
2263
  for (let i = 0; i < expression.length; i++) {
2251
- 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
+
2252
2270
  // Suppress spacing between adjacent relations
2253
2271
  if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) {
2254
2272
  group.setAttribute("rspace", "0em");
@@ -2256,9 +2274,39 @@ const buildExpression = function(expression, style, semisimple = false) {
2256
2274
  if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) {
2257
2275
  group.setAttribute("lspace", "0em");
2258
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
+ }
2259
2306
  groups.push(group);
2307
+ lastGroup = group;
2260
2308
  }
2261
- return groups;
2309
+ return groups
2262
2310
  };
2263
2311
 
2264
2312
  /**
@@ -2320,6 +2368,11 @@ function buildMathML(tree, texExpression, style, settings) {
2320
2368
  }
2321
2369
 
2322
2370
  const expression = buildExpression(tree, style);
2371
+
2372
+ if (expression.length === 1 && expression[0] instanceof AnchorNode) {
2373
+ return expression[0]
2374
+ }
2375
+
2323
2376
  const wrap = (settings.displayMode || settings.annotate) ? "none" : settings.wrap;
2324
2377
 
2325
2378
  const n1 = expression.length === 0 ? null : expression[0];
@@ -2344,6 +2397,9 @@ function buildMathML(tree, texExpression, style, settings) {
2344
2397
  if (settings.xml) {
2345
2398
  math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
2346
2399
  }
2400
+ if (wrapper.style.width) {
2401
+ math.style.width = "100%";
2402
+ }
2347
2403
  if (settings.displayMode) {
2348
2404
  math.setAttribute("display", "block");
2349
2405
  math.style.display = "block math"; // necessary in Chromium.
@@ -2675,12 +2731,19 @@ const padding$2 = width => {
2675
2731
  return node
2676
2732
  };
2677
2733
 
2678
- const paddedNode = (group, lspace = 0.3, rspace = 0) => {
2734
+ const paddedNode = (group, lspace = 0.3, rspace = 0, mustSmash = false) => {
2679
2735
  if (group == null && rspace === 0) { return padding$2(lspace) }
2680
2736
  const row = group ? [group] : [];
2681
2737
  if (lspace !== 0) { row.unshift(padding$2(lspace)); }
2682
2738
  if (rspace > 0) { row.push(padding$2(rspace)); }
2683
- 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
+ }
2684
2747
  };
2685
2748
 
2686
2749
  const labelSize = (size, scriptLevel) => Number(size) / emScale(scriptLevel);
@@ -2720,7 +2783,8 @@ const munderoverNode = (fName, body, below, style) => {
2720
2783
  (body.body.body || body.body.length > 0));
2721
2784
  if (gotUpper) {
2722
2785
  let label = buildGroup$1(body, labelStyle);
2723
- label = paddedNode(label, space, space);
2786
+ const mustSmash = (fName === "\\\\cdrightarrow" || fName === "\\\\cdleftarrow");
2787
+ label = paddedNode(label, space, space, mustSmash);
2724
2788
  // Since Firefox does not support minsize, stack a invisible node
2725
2789
  // on top of the label. Its width will serve as a min-width.
2726
2790
  // TODO: Refactor this after Firefox supports minsize.
@@ -3143,18 +3207,23 @@ defineFunction({
3143
3207
  };
3144
3208
  },
3145
3209
  mathmlBuilder(group, style) {
3146
- let label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, style)]);
3147
- label = new mathMLTree.MathNode("mpadded", [label]);
3148
- label.setAttribute("width", "0");
3149
- if (group.side === "left") {
3150
- label.setAttribute("lspace", "-1width");
3210
+ if (group.label.body.length === 0) {
3211
+ return new mathMLTree.MathNode("mrow", style) // empty label
3151
3212
  }
3152
- // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
3153
- // But we don't know the height or depth of the label.
3154
- label.setAttribute("voffset", "0.7em");
3155
- 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");
3156
3221
  label.setAttribute("displaystyle", "false");
3157
3222
  label.setAttribute("scriptlevel", "1");
3223
+ if (group.side === "left") {
3224
+ label.style.display = "flex";
3225
+ label.style.justifyContent = "flex-end";
3226
+ }
3158
3227
  return label;
3159
3228
  }
3160
3229
  });
@@ -3744,10 +3813,13 @@ defineFunction({
3744
3813
  // replacement text, enclosed in '{' and '}' and properly nested
3745
3814
  const { tokens } = parser.gullet.consumeArg();
3746
3815
 
3747
- parser.gullet.macros.set(
3748
- name,
3749
- { tokens, numArgs }
3750
- );
3816
+ if (!(funcName === "\\providecommand" && parser.gullet.macros.has(name))) {
3817
+ // Ignore \providecommand
3818
+ parser.gullet.macros.set(
3819
+ name,
3820
+ { tokens, numArgs }
3821
+ );
3822
+ }
3751
3823
 
3752
3824
  return { type: "internal", mode: parser.mode };
3753
3825
 
@@ -3841,6 +3913,7 @@ const delimiters = [
3841
3913
  "\\vert",
3842
3914
  "\\|",
3843
3915
  "\\Vert",
3916
+ "\u2016",
3844
3917
  "\\uparrow",
3845
3918
  "\\Uparrow",
3846
3919
  "\\downarrow",
@@ -8073,6 +8146,7 @@ defineFunction({
8073
8146
  "\\mathfrak",
8074
8147
  "\\mathscr",
8075
8148
  "\\mathsf",
8149
+ "\\mathsfit",
8076
8150
  "\\mathtt",
8077
8151
 
8078
8152
  // aliases
@@ -8142,10 +8216,19 @@ const mathmlBuilder$5 = (group, style) => {
8142
8216
  ? style.withLevel(StyleLevel.SCRIPT)
8143
8217
  : style.withLevel(StyleLevel.SCRIPTSCRIPT);
8144
8218
 
8145
- let node = new mathMLTree.MathNode("mfrac", [
8146
- buildGroup$1(group.numer, childOptions),
8147
- buildGroup$1(group.denom, childOptions)
8148
- ]);
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]);
8149
8232
 
8150
8233
  if (!group.hasBarLine) {
8151
8234
  node.setAttribute("linethickness", "0px");
@@ -8538,12 +8621,9 @@ defineFunction({
8538
8621
  };
8539
8622
  },
8540
8623
  mathmlBuilder: (group, style) => {
8541
- let math = buildExpressionRow(group.body, style);
8542
- if (!(math instanceof MathNode)) {
8543
- math = new MathNode("mrow", [math]);
8544
- }
8545
- math.setAttribute("href", group.href);
8546
- return math;
8624
+ const math = new MathNode("math", [buildExpressionRow(group.body, style)]);
8625
+ const anchorNode = new AnchorNode(group.href, [], [math]);
8626
+ return anchorNode
8547
8627
  }
8548
8628
  });
8549
8629
 
@@ -9415,13 +9495,6 @@ const mathmlBuilder$2 = (group, style) => {
9415
9495
  node = new MathNode("mo", [makeText(group.name, group.mode)]);
9416
9496
  if (noSuccessor.includes(group.name)) {
9417
9497
  node.setAttribute("largeop", "false");
9418
- } else if (group.limits) {
9419
- // This is a workaround for a MathML/Chromium bug.
9420
- // This is being applied to singleCharBigOps, which are not really stretchy.
9421
- // But by setting the stretchy attribute, Chromium will vertically center
9422
- // big ops around the math axis. This is needed since STIX TWO does not do so.
9423
- // TODO: Remove this hack when MathML & Chromium fix their problem.
9424
- node.setAttribute("stretchy", "true");
9425
9498
  } else {
9426
9499
  node.setAttribute("movablelimits", "false");
9427
9500
  }
@@ -10056,12 +10129,10 @@ defineFunction({
10056
10129
  };
10057
10130
  },
10058
10131
  mathmlBuilder(group, style) {
10059
- // Create an empty text node. Set a class and an href.
10132
+ // Create an empty <a> node. Set a class and an href attribute.
10060
10133
  // The post-processor will populate with the target's tag or equation number.
10061
10134
  const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"];
10062
- const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes);
10063
- node.setAttribute("href", "#" + group.string);
10064
- return node
10135
+ return new AnchorNode("#" + group.string, classes, null)
10065
10136
  }
10066
10137
  });
10067
10138
 
@@ -10108,6 +10179,8 @@ defineFunction({
10108
10179
  props: {
10109
10180
  numArgs: 2,
10110
10181
  numOptionalArgs: 1,
10182
+ allowedInText: true,
10183
+ allowedInMath: true,
10111
10184
  argTypes: ["size", "size", "size"]
10112
10185
  },
10113
10186
  handler({ parser }, args, optArgs) {
@@ -10400,16 +10473,25 @@ defineFunctionBuilders({
10400
10473
  ? [buildGroup$1(group.base.body[0], style)]
10401
10474
  : [buildGroup$1(group.base, style)];
10402
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
+
10403
10482
  const childStyle = style.inSubOrSup();
10404
10483
  if (group.sub) {
10405
- 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);
10406
10487
  }
10407
10488
 
10408
10489
  if (group.sup) {
10409
10490
  const sup = buildGroup$1(group.sup, childStyle);
10491
+ if (style.level === 3) { sup.setAttribute("scriptlevel", "2"); }
10410
10492
  const testNode = sup.type === "mrow" ? sup.children[0] : sup;
10411
10493
  if ((testNode && testNode.type === "mo" && testNode.classes.includes("tml-prime"))
10412
- && group.base && group.base.text && group.base.text === "f") {
10494
+ && group.base && group.base.text && "fF".indexOf(group.base.text) > -1) {
10413
10495
  // Chromium does not address italic correction on prime. Prevent f′ from overlapping.
10414
10496
  testNode.classes.push("prime-pad");
10415
10497
  }
@@ -10636,6 +10718,8 @@ const getVariant = function(group, style) {
10636
10718
  return "script"
10637
10719
  case "mathsf":
10638
10720
  return "sans-serif"
10721
+ case "mathsfit":
10722
+ return "sans-serif-italic"
10639
10723
  case "mathtt":
10640
10724
  return "monospace"
10641
10725
  }
@@ -11100,6 +11184,32 @@ defineFunction({
11100
11184
  }
11101
11185
  });
11102
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
+
11103
11213
  defineFunction({
11104
11214
  type: "verb",
11105
11215
  names: ["\\verb"],
@@ -13366,9 +13476,11 @@ class Style {
13366
13476
  constructor(data) {
13367
13477
  // Style.level can be 0 | 1 | 2 | 3, which correspond to
13368
13478
  // displaystyle, textstyle, scriptstyle, and scriptscriptstyle.
13369
- // style.level does not directly set MathML's script level. MathML does that itself.
13370
- // We use style.level to track, not set, math style so that we can get the
13371
- // 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.
13372
13484
  this.level = data.level;
13373
13485
  this.color = data.color; // string | void
13374
13486
  // A font family applies to a group of fonts (i.e. SansSerif), while a font
@@ -13492,39 +13604,47 @@ class Style {
13492
13604
  }
13493
13605
 
13494
13606
  /* Temml Post Process
13495
- * Perform two tasks not done by Temml when it created each individual Temml <math> element.
13496
- * Given a block,
13497
- * 1. At each AMS auto-numbered environment, assign an id.
13498
- * 2. Populate the text contents of each \ref & \eqref
13607
+ * Populate the text contents of each \ref & \eqref
13499
13608
  *
13500
13609
  * As with other Temml code, this file is released under terms of the MIT license.
13501
13610
  * https://mit-license.org/
13502
13611
  */
13503
13612
 
13504
- const version = "0.10.31";
13613
+ const version = "0.10.33";
13505
13614
 
13506
13615
  function postProcess(block) {
13507
13616
  const labelMap = {};
13508
13617
  let i = 0;
13509
13618
 
13510
13619
  // Get a collection of the parents of each \tag & auto-numbered equation
13511
- const parents = block.getElementsByClassName("tml-tageqn");
13512
- for (const parent of parents) {
13513
- const eqns = parent.getElementsByClassName("tml-eqn");
13514
- if (eqns. length > 0 ) {
13515
- // AMS automatically numbered equation.
13516
- // Assign an id.
13517
- i += 1;
13518
- eqns[0].id = "tml-eqn-" + i;
13519
- // No need to write a number into the text content of the element.
13520
- // 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
+ }
13521
13640
  }
13522
- // 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) {
13523
13646
  const labels = parent.getElementsByClassName("tml-label");
13524
- if (labels.length === 0) { continue }
13525
- if (eqns.length > 0) {
13526
- labelMap[labels[0].id] = String(i);
13527
- } else {
13647
+ if (labels.length > 0) {
13528
13648
  const tags = parent.getElementsByClassName("tml-tag");
13529
13649
  if (tags.length > 0) {
13530
13650
  labelMap[labels[0].id] = tags[0].textContent;
@@ -13535,17 +13655,22 @@ function postProcess(block) {
13535
13655
  // Populate \ref & \eqref text content
13536
13656
  const refs = block.getElementsByClassName("tml-ref");
13537
13657
  [...refs].forEach(ref => {
13538
- let str = labelMap[ref.getAttribute("href").slice(1)];
13658
+ const attr = ref.getAttribute("href");
13659
+ let str = labelMap[attr.slice(1)];
13539
13660
  if (ref.className.indexOf("tml-eqref") === -1) {
13540
13661
  // \ref. Omit parens.
13541
13662
  str = str.replace(/^\(/, "");
13542
- str = str.replace(/\($/, "");
13543
- } {
13663
+ str = str.replace(/\)$/, "");
13664
+ } else {
13544
13665
  // \eqref. Include parens
13545
13666
  if (str.charAt(0) !== "(") { str = "(" + str; }
13546
13667
  if (str.slice(-1) !== ")") { str = str + ")"; }
13547
13668
  }
13548
- 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);
13549
13674
  });
13550
13675
  }
13551
13676