temml 0.11.7 → 0.11.8

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
@@ -834,6 +834,9 @@ const stretchyCodePoint = {
834
834
  xtwoheadrightarrow: "\u21a0",
835
835
  xlongequal: "=",
836
836
  xrightleftarrows: "\u21c4",
837
+ xtofrom: "\u21c4",
838
+ xleftrightharpoons: "\u21cb",
839
+ xrightleftharpoons: "\u21cc",
837
840
  yields: "\u2192",
838
841
  yieldsLeft: "\u2190",
839
842
  mesomerism: "\u2194",
@@ -843,7 +846,9 @@ const stretchyCodePoint = {
843
846
  eqleftharpoondown: "\u21bd",
844
847
  "\\cdrightarrow": "\u2192",
845
848
  "\\cdleftarrow": "\u2190",
846
- "\\cdlongequal": "="
849
+ "\\cdlongequal": "=",
850
+ yieldsLeftRight: "\u21c4",
851
+ chemequilibrium: "\u21cc"
847
852
  };
848
853
 
849
854
  const mathMLnode = function(label) {
@@ -1771,7 +1776,7 @@ defineSymbol(math, inner, "\u22ef", "\\@cdots", true);
1771
1776
  defineSymbol(math, inner, "\u22f1", "\\ddots", true);
1772
1777
  defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
1773
1778
  defineSymbol(text, textord, "\u22ee", "\\varvdots");
1774
- defineSymbol(math, accent, "\u02ca", "\\acute");
1779
+ defineSymbol(math, accent, "\u00b4", "\\acute");
1775
1780
  defineSymbol(math, accent, "\u0060", "\\grave");
1776
1781
  defineSymbol(math, accent, "\u00a8", "\\ddot");
1777
1782
  defineSymbol(math, accent, "\u2026", "\\dddot");
@@ -1797,7 +1802,7 @@ defineSymbol(math, mathord, "\u00d8", "\\O", true);
1797
1802
  defineSymbol(text, accent, "\u02ca", "\\'"); // acute
1798
1803
  defineSymbol(text, accent, "\u02cb", "\\`"); // grave
1799
1804
  defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex
1800
- defineSymbol(text, accent, "\u02dc", "\\~"); // tilde
1805
+ defineSymbol(text, accent, "\u007e", "\\~"); // tilde
1801
1806
  defineSymbol(text, accent, "\u02c9", "\\="); // macron
1802
1807
  defineSymbol(text, accent, "\u02d8", "\\u"); // breve
1803
1808
  defineSymbol(text, accent, "\u02d9", "\\."); // dot above
@@ -1809,7 +1814,7 @@ defineSymbol(text, accent, "\u02dd", "\\H"); // double acute
1809
1814
  defineSymbol(math, accent, "\u02ca", "\\'"); // acute
1810
1815
  defineSymbol(math, accent, "\u02cb", "\\`"); // grave
1811
1816
  defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex
1812
- defineSymbol(math, accent, "\u02dc", "\\~"); // tilde
1817
+ defineSymbol(math, accent, "\u007e", "\\~"); // tilde
1813
1818
  defineSymbol(math, accent, "\u02c9", "\\="); // macron
1814
1819
  defineSymbol(math, accent, "\u02d8", "\\u"); // breve
1815
1820
  defineSymbol(math, accent, "\u02d9", "\\."); // dot above
@@ -2466,46 +2471,61 @@ function buildMathML(tree, texExpression, style, settings) {
2466
2471
  return math;
2467
2472
  }
2468
2473
 
2474
+ // Identify letters to which we'll attach a combining accent character
2469
2475
  const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳";
2470
- const talls = "ABCDEFGHIJKLMNOPQRSTUVWXYZbdfhkltΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩβδλζφθψ"
2471
- + "𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐛𝐝𝐟𝐡𝐤𝐥𝐭";
2472
- const longSmalls = new Set(["\\alpha", "\\gamma", "\\delta", "\\epsilon", "\\eta", "\\iota",
2473
- "\\kappa", "\\mu", "\\nu", "\\pi", "\\rho", "\\sigma", "\\tau", "\\upsilon", "\\chi", "\\psi",
2474
- "\\omega", "\\imath", "\\jmath"]);
2475
- const longTalls = new Set(["\\Gamma", "\\Delta", "\\Sigma", "\\Omega", "\\beta", "\\delta",
2476
- "\\lambda", "\\theta", "\\psi"]);
2476
+
2477
+ // From the KaTeX font metrics, identify letters whose accents need a italic correction.
2478
+ const smallNudge = "DHKLUcegorsuvxyzΠΥΨαδηιμνοτυχϵ";
2479
+ const mediumNudge = "BCEGIMNOPQRSTXZlpqtwΓΘΞΣΦΩβεζθξρςφψϑϕϱ";
2480
+ const largeNudge = "AFJdfΔΛ";
2477
2481
 
2478
2482
  const mathmlBuilder$a = (group, style) => {
2479
2483
  const accentNode = group.isStretchy
2480
2484
  ? stretchy.accentNode(group)
2481
2485
  : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]);
2482
-
2483
- if (group.label === "\\vec") {
2484
- accentNode.style.transform = "scale(0.75) translate(10%, 30%)";
2485
- } else {
2486
- accentNode.style.mathStyle = "normal";
2487
- accentNode.style.mathDepth = "0";
2488
- if (needWebkitShift.has(group.label) && utils.isCharacterBox(group.base)) {
2489
- let shift = "";
2490
- const ch = group.base.text;
2491
- if (smalls.indexOf(ch) > -1 || longSmalls.has(ch)) { shift = "tml-xshift"; }
2492
- if (talls.indexOf(ch) > -1 || longTalls.has(ch)) { shift = "tml-capshift"; }
2493
- if (shift) { accentNode.classes.push(shift); }
2494
- }
2495
- }
2496
2486
  if (!group.isStretchy) {
2497
- accentNode.setAttribute("stretchy", "false");
2498
- }
2499
-
2500
- const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"),
2501
- [buildGroup$1(group.base, style), accentNode]
2502
- );
2503
-
2487
+ accentNode.setAttribute("stretchy", "false"); // Keep Firefox from stretching \check
2488
+ }
2489
+ if (group.label !== "\\vec") {
2490
+ accentNode.style.mathDepth = "0"; // not scriptstyle
2491
+ // Don't use attribute accent="true" because MathML Core eliminates a needed space.
2492
+ }
2493
+ const tag = group.label === "\\c" ? "munder" : "mover";
2494
+ const needsWbkVertShift = needsWebkitVerticalShift.has(group.label);
2495
+ if (tag === "mover" && group.mode === "math" && (!group.isStretchy) && group.base.text
2496
+ && group.base.text.length === 1) {
2497
+ const text = group.base.text;
2498
+ const isVec = group.label === "\\vec";
2499
+ const vecPostfix = isVec === "\\vec" ? "-vec" : "";
2500
+ if (isVec) {
2501
+ accentNode.classes.push("tml-vec"); // Firefox sizing of \vec arrow
2502
+ }
2503
+ const wbkPostfix = isVec ? "-vec" : needsWbkVertShift ? "-acc" : "";
2504
+ if (smallNudge.indexOf(text) > -1) {
2505
+ accentNode.classes.push(`chr-sml${vecPostfix}`);
2506
+ accentNode.classes.push(`wbk-sml${wbkPostfix}`);
2507
+ } else if (mediumNudge.indexOf(text) > -1) {
2508
+ accentNode.classes.push(`chr-med${vecPostfix}`);
2509
+ accentNode.classes.push(`wbk-med${wbkPostfix}`);
2510
+ } else if (largeNudge.indexOf(text) > -1) {
2511
+ accentNode.classes.push(`chr-lrg${vecPostfix}`);
2512
+ accentNode.classes.push(`wbk-lrg${wbkPostfix}`);
2513
+ } else if (isVec) {
2514
+ accentNode.classes.push(`wbk-vec`);
2515
+ } else if (needsWbkVertShift) {
2516
+ accentNode.classes.push(`wbk-acc`);
2517
+ }
2518
+ } else if (needsWbkVertShift) {
2519
+ // text-mode accents
2520
+ accentNode.classes.push("wbk-acc");
2521
+ }
2522
+ const node = new mathMLTree.MathNode(tag, [buildGroup$1(group.base, style), accentNode]);
2504
2523
  return node;
2505
2524
  };
2506
2525
 
2507
2526
  const nonStretchyAccents = new Set([
2508
2527
  "\\acute",
2528
+ "\\check",
2509
2529
  "\\grave",
2510
2530
  "\\ddot",
2511
2531
  "\\dddot",
@@ -2520,7 +2540,7 @@ const nonStretchyAccents = new Set([
2520
2540
  "\\mathring"
2521
2541
  ]);
2522
2542
 
2523
- const needWebkitShift = new Set([
2543
+ const needsWebkitVerticalShift = new Set([
2524
2544
  "\\acute",
2525
2545
  "\\bar",
2526
2546
  "\\breve",
@@ -2530,7 +2550,7 @@ const needWebkitShift = new Set([
2530
2550
  "\\grave",
2531
2551
  "\\hat",
2532
2552
  "\\mathring",
2533
- "\\'", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"
2553
+ "\\`", "\\'", "\\^", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"
2534
2554
  ]);
2535
2555
 
2536
2556
  const combiningChar = {
@@ -2544,7 +2564,8 @@ const combiningChar = {
2544
2564
  '\\"': "\u0308",
2545
2565
  "\\r": "\u030A",
2546
2566
  "\\H": "\u030B",
2547
- "\\v": "\u030C"
2567
+ "\\v": "\u030C",
2568
+ "\\c": "\u0327"
2548
2569
  };
2549
2570
 
2550
2571
  // Accents
@@ -2589,8 +2610,8 @@ defineFunction({
2589
2610
  type: "accent",
2590
2611
  mode: context.parser.mode,
2591
2612
  label: context.funcName,
2592
- isStretchy: isStretchy,
2593
- base: base
2613
+ isStretchy,
2614
+ base
2594
2615
  };
2595
2616
  },
2596
2617
  mathmlBuilder: mathmlBuilder$a
@@ -2617,21 +2638,25 @@ defineFunction({
2617
2638
  }
2618
2639
 
2619
2640
  if (mode === "text" && base.text && base.text.length === 1
2620
- && context.funcName in combiningChar && smalls.indexOf(base.text) > -1) {
2641
+ && context.funcName in combiningChar && smalls.indexOf(base.text) > -1) {
2621
2642
  // Return a combining accent character
2622
2643
  return {
2623
2644
  type: "textord",
2624
2645
  mode: "text",
2625
2646
  text: base.text + combiningChar[context.funcName]
2626
2647
  }
2648
+ } else if (context.funcName === "\\c" && mode === "text" && base.text
2649
+ && base.text.length === 1) {
2650
+ // combining cedilla
2651
+ return { type: "textord", mode: "text", text: base.text + "\u0327" }
2627
2652
  } else {
2628
2653
  // Build up the accent
2629
2654
  return {
2630
2655
  type: "accent",
2631
- mode: mode,
2656
+ mode,
2632
2657
  label: context.funcName,
2633
2658
  isStretchy: false,
2634
- base: base
2659
+ base
2635
2660
  }
2636
2661
  }
2637
2662
  },
@@ -2889,12 +2914,17 @@ defineFunction({
2889
2914
  "\\xlongequal",
2890
2915
  "\\xtwoheadrightarrow",
2891
2916
  "\\xtwoheadleftarrow",
2892
- // The next 5 functions are here only to support mhchem
2917
+ "\\xtofrom", // expfeil
2918
+ "\\xleftrightharpoons", // mathtools
2919
+ "\\xrightleftharpoons", // mathtools
2920
+ // The next 7 functions are here only to support mhchem
2893
2921
  "\\yields",
2894
2922
  "\\yieldsLeft",
2895
2923
  "\\mesomerism",
2896
2924
  "\\longrightharpoonup",
2897
2925
  "\\longleftharpoondown",
2926
+ "\\yieldsLeftRight",
2927
+ "\\chemequilibrium",
2898
2928
  // The next 3 functions are here only to support the {CD} environment.
2899
2929
  "\\\\cdrightarrow",
2900
2930
  "\\\\cdleftarrow",
@@ -2925,26 +2955,15 @@ defineFunction({
2925
2955
  });
2926
2956
 
2927
2957
  const arrowComponent = {
2928
- "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"],
2929
- "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"],
2930
- "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"],
2931
- "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"],
2932
- // The next three all get the same harpoon glyphs. Only the lengths and paddings differ.
2933
- "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"],
2934
2958
  "\\equilibriumRight": ["\\longrightharpoonup", "\\eqleftharpoondown"],
2935
2959
  "\\equilibriumLeft": ["\\eqrightharpoonup", "\\longleftharpoondown"]
2936
2960
  };
2937
2961
 
2938
- // Browsers are not good at stretching a glyph that contains a pair of stacked arrows such as ⇄.
2939
- // So we stack a pair of single arrows.
2962
+ // Math fonts do not have a single glyph for these two mhchem functions.
2963
+ // So we stack a pair of single harpoons.
2940
2964
  defineFunction({
2941
2965
  type: "stackedArrow",
2942
2966
  names: [
2943
- "\\xtofrom", // expfeil
2944
- "\\xleftrightharpoons", // mathtools
2945
- "\\xrightleftharpoons", // mathtools
2946
- "\\yieldsLeftRight", // mhchem
2947
- "\\equilibrium", // mhchem
2948
2967
  "\\equilibriumRight",
2949
2968
  "\\equilibriumLeft"
2950
2969
  ],
@@ -3451,7 +3470,6 @@ const bordermatrixParseTree = (matrix, delimiters) => {
3451
3470
  alwaysHandleSupSub: true,
3452
3471
  parentIsSupSub: true,
3453
3472
  symbol: false,
3454
- stack: true,
3455
3473
  suppressBaseShift: true,
3456
3474
  body: [container]
3457
3475
  };
@@ -3459,6 +3477,7 @@ const bordermatrixParseTree = (matrix, delimiters) => {
3459
3477
  const mover = {
3460
3478
  type: "supsub", // We're using the MathML equivalent
3461
3479
  mode: "math", // of TeX \overset.
3480
+ stack: true,
3462
3481
  base: base, // That keeps the {pmatrix} aligned with
3463
3482
  sup: topWrapper, // the math centerline.
3464
3483
  sub: null
@@ -5922,8 +5941,8 @@ defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap
5922
5941
  case "<-": return "\\yieldsLeft";
5923
5942
  case "<->": return "\\mesomerism";
5924
5943
  case "<-->": return "\\yieldsLeftRight";
5925
- case "<=>": return "\\equilibrium";
5926
- case "\u21CC": return "\\equilibrium";
5944
+ case "<=>": return "\\chemequilibrium";
5945
+ case "\u21CC": return "\\chemequilibrium";
5927
5946
  case "<=>>": return "\\equilibriumRight";
5928
5947
  case "<<=>": return "\\equilibriumLeft";
5929
5948
  default:
@@ -8186,7 +8205,8 @@ const mathmlBuilder$7 = (group, style) => {
8186
8205
  case "\\boxed":
8187
8206
  // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} from amsmath.sty
8188
8207
  node.setAttribute("notation", "box");
8189
- node.classes.push("tml-box");
8208
+ node.style.padding = "padding: 3pt 0 3pt 0";
8209
+ node.style.border = "1px solid";
8190
8210
  node.setAttribute("scriptlevel", "0");
8191
8211
  node.setAttribute("displaystyle", "true");
8192
8212
  break
@@ -9599,7 +9619,9 @@ const binrelClass = (arg) => {
9599
9619
  // (by rendering separately and with {}s before and after, and measuring
9600
9620
  // the change in spacing). We'll do roughly the same by detecting the
9601
9621
  // atom type directly.
9602
- const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
9622
+ const atom = arg.type === "ordgroup" && arg.body.length && arg.body.length === 1
9623
+ ? arg.body[0]
9624
+ : arg;
9603
9625
  if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
9604
9626
  return "m" + atom.family;
9605
9627
  } else {
@@ -9637,14 +9659,25 @@ defineFunction({
9637
9659
  const baseArg = args[1];
9638
9660
  const shiftedArg = args[0];
9639
9661
 
9662
+ let mclass;
9663
+ if (funcName !== "\\stackrel") {
9664
+ // LaTeX applies \binrel spacing to \overset and \underset.
9665
+ mclass = binrelClass(baseArg);
9666
+ } else {
9667
+ mclass = "mrel"; // for \stackrel
9668
+ }
9669
+
9670
+ const baseType = mclass === "mrel" || mclass === "mbin"
9671
+ ? "op"
9672
+ : "ordgroup";
9673
+
9640
9674
  const baseOp = {
9641
- type: "op",
9675
+ type: baseType,
9642
9676
  mode: baseArg.mode,
9643
9677
  limits: true,
9644
9678
  alwaysHandleSupSub: true,
9645
9679
  parentIsSupSub: false,
9646
9680
  symbol: false,
9647
- stack: true,
9648
9681
  suppressBaseShift: funcName !== "\\stackrel",
9649
9682
  body: ordargument(baseArg)
9650
9683
  };
@@ -9652,6 +9685,7 @@ defineFunction({
9652
9685
  return {
9653
9686
  type: "supsub",
9654
9687
  mode: shiftedArg.mode,
9688
+ stack: true,
9655
9689
  base: baseOp,
9656
9690
  sup: funcName === "\\underset" ? null : shiftedArg,
9657
9691
  sub: funcName === "\\underset" ? shiftedArg : null
@@ -10553,6 +10587,71 @@ defineFunction({
10553
10587
  }
10554
10588
  });
10555
10589
 
10590
+ const numRegEx = /^[0-9]$/;
10591
+ const unicodeNumSubs = {
10592
+ '0': '₀',
10593
+ '1': '₁',
10594
+ '2': '₂',
10595
+ '3': '₃',
10596
+ '4': '₄',
10597
+ '5': '₅',
10598
+ '6': '₆',
10599
+ '7': '₇',
10600
+ '8': '₈',
10601
+ '9': '₉'
10602
+ };
10603
+ const unicodeNumSups = {
10604
+ '0': '⁰',
10605
+ '1': '¹',
10606
+ '2': '²',
10607
+ '3': '³',
10608
+ '4': '⁴',
10609
+ '5': '⁵',
10610
+ '6': '⁶',
10611
+ '7': '⁷',
10612
+ '8': '⁸',
10613
+ '9': '⁹'
10614
+ };
10615
+
10616
+ defineFunction({
10617
+ type: "sfrac",
10618
+ names: ["\\sfrac"],
10619
+ props: {
10620
+ numArgs: 2,
10621
+ allowedInText: true,
10622
+ allowedInMath: true
10623
+ },
10624
+ handler({ parser }, args) {
10625
+ let numerator = "";
10626
+ for (const node of args[0].body) {
10627
+ if (node.type !== "textord" || !numRegEx.test(node.text)) {
10628
+ throw new ParseError("Numerator must be an integer.", node)
10629
+ }
10630
+ numerator += node.text;
10631
+ }
10632
+ let denominator = "";
10633
+ for (const node of args[1].body) {
10634
+ if (node.type !== "textord" || !numRegEx.test(node.text)) {
10635
+ throw new ParseError("Denominator must be an integer.", node)
10636
+ }
10637
+ denominator += node.text;
10638
+ }
10639
+ return {
10640
+ type: "sfrac",
10641
+ mode: parser.mode,
10642
+ numerator,
10643
+ denominator
10644
+ };
10645
+ },
10646
+ mathmlBuilder(group, style) {
10647
+ const numerator = group.numerator.split('').map(c => unicodeNumSups[c]).join('');
10648
+ const denominator = group.denominator.split('').map(c => unicodeNumSubs[c]).join('');
10649
+ // Use a fraction slash.
10650
+ const text = new mathMLTree.TextNode(numerator + "\u2044" + denominator, group.mode, style);
10651
+ return new mathMLTree.MathNode("mn", [text], ["special-fraction"])
10652
+ }
10653
+ });
10654
+
10556
10655
  // The size mappings are taken from TeX with \normalsize=10pt.
10557
10656
  // We don't have to track script level. MathML does that.
10558
10657
  const sizeMap = {
@@ -10770,6 +10869,11 @@ defineFunction({
10770
10869
  // Helpers
10771
10870
  const symbolRegEx = /^m(over|under|underover)$/;
10772
10871
 
10872
+ // From the KaTeX font metrics, identify letters that encroach on a superscript.
10873
+ const smallPad = "DHKLUcegorsuvxyzΠΥΨαδηιμνοτυχϵ";
10874
+ const mediumPad = "BCEFGIMNOPQRSTXZlpqtwΓΘΞΣΦΩβεζθξρςφψϑϕϱ";
10875
+ const largePad = "AJdfΔΛ";
10876
+
10773
10877
  // Super scripts and subscripts, whose precise placement can depend on other
10774
10878
  // functions that precede them.
10775
10879
  defineFunctionBuilders({
@@ -10791,7 +10895,7 @@ defineFunctionBuilders({
10791
10895
  }
10792
10896
  }
10793
10897
 
10794
- if (group.base && !group.base.stack &&
10898
+ if (group.base && !group.stack &&
10795
10899
  (group.base.type === "op" || group.base.type === "operatorname")) {
10796
10900
  group.base.parentIsSupSub = true;
10797
10901
  appendApplyFunction = !group.base.symbol;
@@ -10799,7 +10903,7 @@ defineFunctionBuilders({
10799
10903
  needsLeadingSpace = group.base.needsLeadingSpace;
10800
10904
  }
10801
10905
 
10802
- const children = group.base && group.base.stack
10906
+ const children = group.stack && group.base.body.length === 1
10803
10907
  ? [buildGroup$1(group.base.body[0], style)]
10804
10908
  : [buildGroup$1(group.base, style)];
10805
10909
 
@@ -10819,11 +10923,16 @@ defineFunctionBuilders({
10819
10923
  if (group.sup) {
10820
10924
  const sup = buildGroup$1(group.sup, childStyle);
10821
10925
  if (style.level === 3) { sup.setAttribute("scriptlevel", "2"); }
10822
- const testNode = sup.type === "mrow" ? sup.children[0] : sup;
10823
- if ((testNode && testNode.type === "mo" && testNode.classes.includes("tml-prime"))
10824
- && group.base && group.base.text && "fF".indexOf(group.base.text) > -1) {
10825
- // Chromium does not address italic correction on prime. Prevent f′ from overlapping.
10826
- testNode.classes.push("prime-pad");
10926
+ if (group.base && group.base.text && group.base.text.length === 1) {
10927
+ // Make an italic correction on the superscript.
10928
+ const text = group.base.text;
10929
+ if (smallPad.indexOf(text) > -1) {
10930
+ sup.classes.push("tml-sml-pad");
10931
+ } else if (mediumPad.indexOf(text) > -1) {
10932
+ sup.classes.push("tml-med-pad");
10933
+ } else if (largePad.indexOf(text) > -1) {
10934
+ sup.classes.push("tml-lrg-pad");
10935
+ }
10827
10936
  }
10828
10937
  children.push(sup);
10829
10938
  }
@@ -10852,7 +10961,9 @@ defineFunctionBuilders({
10852
10961
  }
10853
10962
  } else if (!group.sup) {
10854
10963
  const base = group.base;
10855
- if (
10964
+ if (group.stack) {
10965
+ nodeType = "munder";
10966
+ } else if (
10856
10967
  base &&
10857
10968
  base.type === "op" &&
10858
10969
  base.limits &&
@@ -13897,7 +14008,7 @@ class Style {
13897
14008
  * https://mit-license.org/
13898
14009
  */
13899
14010
 
13900
- const version = "0.11.07";
14011
+ const version = "0.11.08";
13901
14012
 
13902
14013
  function postProcess(block) {
13903
14014
  const labelMap = {};
@@ -11,7 +11,7 @@
11
11
  * https://mit-license.org/
12
12
  */
13
13
 
14
- const version = "0.11.07";
14
+ const version = "0.11.08";
15
15
 
16
16
  function postProcess(block) {
17
17
  const labelMap = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "temml",
3
- "version": "0.11.07",
3
+ "version": "0.11.08",
4
4
  "description": "TeX to MathML conversion in JavaScript.",
5
5
  "main": "dist/temml.js",
6
6
  "engines": {
@@ -122,7 +122,6 @@ export const bordermatrixParseTree = (matrix, delimiters) => {
122
122
  alwaysHandleSupSub: true,
123
123
  parentIsSupSub: true,
124
124
  symbol: false,
125
- stack: true,
126
125
  suppressBaseShift: true,
127
126
  body: [container]
128
127
  }
@@ -130,6 +129,7 @@ export const bordermatrixParseTree = (matrix, delimiters) => {
130
129
  const mover = {
131
130
  type: "supsub", // We're using the MathML equivalent
132
131
  mode: "math", // of TeX \overset.
132
+ stack: true,
133
133
  base: base, // That keeps the {pmatrix} aligned with
134
134
  sup: topWrapper, // the math centerline.
135
135
  sub: null
@@ -2,48 +2,62 @@ import defineFunction, { normalizeArgument } from "../defineFunction"
2
2
  import mathMLTree from "../mathMLTree"
3
3
  import stretchy from "../stretchy"
4
4
  import * as mml from "../buildMathML"
5
- import utils from "../utils"
6
5
 
6
+ // Identify letters to which we'll attach a combining accent character
7
7
  const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳"
8
- const talls = "ABCDEFGHIJKLMNOPQRSTUVWXYZbdfhkltΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩβδλζφθψ"
9
- + "𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐛𝐝𝐟𝐡𝐤𝐥𝐭"
10
- const longSmalls = new Set(["\\alpha", "\\gamma", "\\delta", "\\epsilon", "\\eta", "\\iota",
11
- "\\kappa", "\\mu", "\\nu", "\\pi", "\\rho", "\\sigma", "\\tau", "\\upsilon", "\\chi", "\\psi",
12
- "\\omega", "\\imath", "\\jmath"])
13
- const longTalls = new Set(["\\Gamma", "\\Delta", "\\Sigma", "\\Omega", "\\beta", "\\delta",
14
- "\\lambda", "\\theta", "\\psi"])
8
+
9
+ // From the KaTeX font metrics, identify letters whose accents need a italic correction.
10
+ const smallNudge = "DHKLUcegorsuvxyzΠΥΨαδηιμνοτυχϵ"
11
+ const mediumNudge = "BCEGIMNOPQRSTXZlpqtwΓΘΞΣΦΩβεζθξρςφψϑϕϱ"
12
+ const largeNudge = "AFJdfΔΛ"
15
13
 
16
14
  const mathmlBuilder = (group, style) => {
17
15
  const accentNode = group.isStretchy
18
16
  ? stretchy.accentNode(group)
19
17
  : new mathMLTree.MathNode("mo", [mml.makeText(group.label, group.mode)]);
20
-
21
- if (group.label === "\\vec") {
22
- accentNode.style.transform = "scale(0.75) translate(10%, 30%)"
23
- } else {
24
- accentNode.style.mathStyle = "normal"
25
- accentNode.style.mathDepth = "0"
26
- if (needWebkitShift.has(group.label) && utils.isCharacterBox(group.base)) {
27
- let shift = ""
28
- const ch = group.base.text
29
- if (smalls.indexOf(ch) > -1 || longSmalls.has(ch)) { shift = "tml-xshift" }
30
- if (talls.indexOf(ch) > -1 || longTalls.has(ch)) { shift = "tml-capshift" }
31
- if (shift) { accentNode.classes.push(shift) }
32
- }
33
- }
34
18
  if (!group.isStretchy) {
35
- accentNode.setAttribute("stretchy", "false")
19
+ accentNode.setAttribute("stretchy", "false") // Keep Firefox from stretching \check
36
20
  }
37
-
38
- const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"),
39
- [mml.buildGroup(group.base, style), accentNode]
40
- );
41
-
21
+ if (group.label !== "\\vec") {
22
+ accentNode.style.mathDepth = "0" // not scriptstyle
23
+ // Don't use attribute accent="true" because MathML Core eliminates a needed space.
24
+ }
25
+ const tag = group.label === "\\c" ? "munder" : "mover"
26
+ const needsWbkVertShift = needsWebkitVerticalShift.has(group.label)
27
+ if (tag === "mover" && group.mode === "math" && (!group.isStretchy) && group.base.text
28
+ && group.base.text.length === 1) {
29
+ const text = group.base.text
30
+ const isVec = group.label === "\\vec"
31
+ const vecPostfix = isVec === "\\vec" ? "-vec" : ""
32
+ if (isVec) {
33
+ accentNode.classes.push("tml-vec") // Firefox sizing of \vec arrow
34
+ }
35
+ const wbkPostfix = isVec ? "-vec" : needsWbkVertShift ? "-acc" : ""
36
+ if (smallNudge.indexOf(text) > -1) {
37
+ accentNode.classes.push(`chr-sml${vecPostfix}`)
38
+ accentNode.classes.push(`wbk-sml${wbkPostfix}`)
39
+ } else if (mediumNudge.indexOf(text) > -1) {
40
+ accentNode.classes.push(`chr-med${vecPostfix}`)
41
+ accentNode.classes.push(`wbk-med${wbkPostfix}`)
42
+ } else if (largeNudge.indexOf(text) > -1) {
43
+ accentNode.classes.push(`chr-lrg${vecPostfix}`)
44
+ accentNode.classes.push(`wbk-lrg${wbkPostfix}`)
45
+ } else if (isVec) {
46
+ accentNode.classes.push(`wbk-vec`)
47
+ } else if (needsWbkVertShift) {
48
+ accentNode.classes.push(`wbk-acc`)
49
+ }
50
+ } else if (needsWbkVertShift) {
51
+ // text-mode accents
52
+ accentNode.classes.push("wbk-acc")
53
+ }
54
+ const node = new mathMLTree.MathNode(tag, [mml.buildGroup(group.base, style), accentNode]);
42
55
  return node;
43
56
  };
44
57
 
45
58
  const nonStretchyAccents = new Set([
46
59
  "\\acute",
60
+ "\\check",
47
61
  "\\grave",
48
62
  "\\ddot",
49
63
  "\\dddot",
@@ -58,7 +72,7 @@ const nonStretchyAccents = new Set([
58
72
  "\\mathring"
59
73
  ])
60
74
 
61
- const needWebkitShift = new Set([
75
+ const needsWebkitVerticalShift = new Set([
62
76
  "\\acute",
63
77
  "\\bar",
64
78
  "\\breve",
@@ -68,7 +82,7 @@ const needWebkitShift = new Set([
68
82
  "\\grave",
69
83
  "\\hat",
70
84
  "\\mathring",
71
- "\\'", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"
85
+ "\\`", "\\'", "\\^", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"
72
86
  ])
73
87
 
74
88
  const combiningChar = {
@@ -82,7 +96,8 @@ const combiningChar = {
82
96
  '\\"': "\u0308",
83
97
  "\\r": "\u030A",
84
98
  "\\H": "\u030B",
85
- "\\v": "\u030C"
99
+ "\\v": "\u030C",
100
+ "\\c": "\u0327"
86
101
  }
87
102
 
88
103
  // Accents
@@ -127,8 +142,8 @@ defineFunction({
127
142
  type: "accent",
128
143
  mode: context.parser.mode,
129
144
  label: context.funcName,
130
- isStretchy: isStretchy,
131
- base: base
145
+ isStretchy,
146
+ base
132
147
  };
133
148
  },
134
149
  mathmlBuilder
@@ -155,21 +170,25 @@ defineFunction({
155
170
  }
156
171
 
157
172
  if (mode === "text" && base.text && base.text.length === 1
158
- && context.funcName in combiningChar && smalls.indexOf(base.text) > -1) {
173
+ && context.funcName in combiningChar && smalls.indexOf(base.text) > -1) {
159
174
  // Return a combining accent character
160
175
  return {
161
176
  type: "textord",
162
177
  mode: "text",
163
178
  text: base.text + combiningChar[context.funcName]
164
179
  }
180
+ } else if (context.funcName === "\\c" && mode === "text" && base.text
181
+ && base.text.length === 1) {
182
+ // combining cedilla
183
+ return { type: "textord", mode: "text", text: base.text + "\u0327" }
165
184
  } else {
166
185
  // Build up the accent
167
186
  return {
168
187
  type: "accent",
169
- mode: mode,
188
+ mode,
170
189
  label: context.funcName,
171
190
  isStretchy: false,
172
- base: base
191
+ base
173
192
  }
174
193
  }
175
194
  },