katex 0.15.6 → 0.16.2

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.
Files changed (44) hide show
  1. package/README.md +3 -3
  2. package/contrib/auto-render/auto-render.js +20 -1
  3. package/contrib/auto-render/test/auto-render-spec.js +88 -17
  4. package/contrib/copy-tex/README.md +9 -19
  5. package/contrib/copy-tex/copy-tex.js +39 -12
  6. package/contrib/copy-tex/katex2tex.js +16 -7
  7. package/contrib/mathtex-script-type/README.md +5 -5
  8. package/contrib/mhchem/README.md +1 -1
  9. package/contrib/render-a11y-string/render-a11y-string.js +5 -0
  10. package/dist/README.md +3 -3
  11. package/dist/contrib/auto-render.js +23 -1
  12. package/dist/contrib/auto-render.min.js +1 -1
  13. package/dist/contrib/auto-render.mjs +23 -1
  14. package/dist/contrib/copy-tex.js +38 -24
  15. package/dist/contrib/copy-tex.min.js +1 -1
  16. package/dist/contrib/copy-tex.mjs +35 -16
  17. package/dist/contrib/render-a11y-string.js +6 -0
  18. package/dist/contrib/render-a11y-string.min.js +1 -1
  19. package/dist/contrib/render-a11y-string.mjs +6 -0
  20. package/dist/katex.css +1 -1
  21. package/dist/katex.js +322 -199
  22. package/dist/katex.min.css +1 -1
  23. package/dist/katex.min.js +1 -1
  24. package/dist/katex.mjs +363 -241
  25. package/package.json +3 -3
  26. package/src/Parser.js +1 -1
  27. package/src/buildCommon.js +1 -1
  28. package/src/buildMathML.js +2 -2
  29. package/src/delimiter.js +68 -25
  30. package/src/domTree.js +1 -0
  31. package/src/environments/array.js +1 -1
  32. package/src/functions/enclose.js +1 -1
  33. package/src/functions/mclass.js +1 -1
  34. package/src/functions/op.js +1 -1
  35. package/src/functions/pmb.js +44 -0
  36. package/src/functions.js +1 -0
  37. package/src/macros.js +1 -9
  38. package/src/parseNode.js +7 -0
  39. package/src/stretchy.js +1 -1
  40. package/src/svgGeometry.js +56 -0
  41. package/contrib/copy-tex/copy-tex.css +0 -10
  42. package/contrib/copy-tex/copy-tex.webpack.js +0 -6
  43. package/dist/contrib/copy-tex.css +0 -13
  44. package/dist/contrib/copy-tex.min.css +0 -1
package/dist/katex.mjs CHANGED
@@ -941,6 +941,43 @@ var path = {
941
941
  shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",
942
942
  shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"
943
943
  };
944
+ var tallDelim = function tallDelim(label, midHeight) {
945
+ switch (label) {
946
+ case "lbrack":
947
+ return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + midHeight + " v1759 h84z";
948
+
949
+ case "rbrack":
950
+ return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + midHeight + " v1759 h84z";
951
+
952
+ case "vert":
953
+ return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z";
954
+
955
+ case "doublevert":
956
+ return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z\nM367 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + midHeight + " v585 h43z";
957
+
958
+ case "lfloor":
959
+ return "M319 602 V0 H403 V602 v" + midHeight + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z";
960
+
961
+ case "rfloor":
962
+ return "M319 602 V0 H403 V602 v" + midHeight + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z";
963
+
964
+ case "lceil":
965
+ return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v602 h84z\nM403 1759 V0 H319 V1759 v" + midHeight + " v602 h84z";
966
+
967
+ case "rceil":
968
+ return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + midHeight + " v602 h84z";
969
+
970
+ case "lparen":
971
+ return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (midHeight + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (midHeight + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z";
972
+
973
+ case "rparen":
974
+ return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (midHeight + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (midHeight + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z";
975
+
976
+ default:
977
+ // We should not ever get here.
978
+ throw new Error("Unknown stretchy delimiter.");
979
+ }
980
+ };
944
981
 
945
982
  /**
946
983
  * This node represents a document fragment, which contains elements, but when
@@ -5428,7 +5465,7 @@ var makeOrd = function makeOrd(group, options, type) {
5428
5465
 
5429
5466
  if (lookupSymbol(text, fontName, mode).metrics) {
5430
5467
  return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
5431
- } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") {
5468
+ } else if (ligatures.hasOwnProperty(text) && fontName.slice(0, 10) === "Typewriter") {
5432
5469
  // Deconstruct ligatures in monospace fonts (\texttt, \tt).
5433
5470
  var parts = [];
5434
5471
 
@@ -6762,7 +6799,7 @@ var mathMLTree = {
6762
6799
  * optional replacement from symbols.js.
6763
6800
  */
6764
6801
  var makeText = function makeText(text, mode, options) {
6765
- if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.substr(4, 2) === "tt" || options.font && options.font.substr(4, 2) === "tt"))) {
6802
+ if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.slice(4, 6) === "tt" || options.font && options.font.slice(4, 6) === "tt"))) {
6766
6803
  text = symbols[mode][text].replace;
6767
6804
  }
6768
6805
 
@@ -7196,7 +7233,7 @@ var svgSpan = function svgSpan(group, options) {
7196
7233
  function buildSvgSpan_() {
7197
7234
  var viewBoxWidth = 400000; // default
7198
7235
 
7199
- var label = group.label.substr(1);
7236
+ var label = group.label.slice(1);
7200
7237
 
7201
7238
  if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) {
7202
7239
  // Each type in the `if` statement corresponds to one of the ParseNode
@@ -7845,6 +7882,217 @@ defineFunction({
7845
7882
 
7846
7883
  });
7847
7884
 
7885
+ var makeSpan = buildCommon.makeSpan;
7886
+
7887
+ function htmlBuilder$9(group, options) {
7888
+ var elements = buildExpression$1(group.body, options, true);
7889
+ return makeSpan([group.mclass], elements, options);
7890
+ }
7891
+
7892
+ function mathmlBuilder$8(group, options) {
7893
+ var node;
7894
+ var inner = buildExpression(group.body, options);
7895
+
7896
+ if (group.mclass === "minner") {
7897
+ node = new mathMLTree.MathNode("mpadded", inner);
7898
+ } else if (group.mclass === "mord") {
7899
+ if (group.isCharacterBox) {
7900
+ node = inner[0];
7901
+ node.type = "mi";
7902
+ } else {
7903
+ node = new mathMLTree.MathNode("mi", inner);
7904
+ }
7905
+ } else {
7906
+ if (group.isCharacterBox) {
7907
+ node = inner[0];
7908
+ node.type = "mo";
7909
+ } else {
7910
+ node = new mathMLTree.MathNode("mo", inner);
7911
+ } // Set spacing based on what is the most likely adjacent atom type.
7912
+ // See TeXbook p170.
7913
+
7914
+
7915
+ if (group.mclass === "mbin") {
7916
+ node.attributes.lspace = "0.22em"; // medium space
7917
+
7918
+ node.attributes.rspace = "0.22em";
7919
+ } else if (group.mclass === "mpunct") {
7920
+ node.attributes.lspace = "0em";
7921
+ node.attributes.rspace = "0.17em"; // thinspace
7922
+ } else if (group.mclass === "mopen" || group.mclass === "mclose") {
7923
+ node.attributes.lspace = "0em";
7924
+ node.attributes.rspace = "0em";
7925
+ } else if (group.mclass === "minner") {
7926
+ node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option
7927
+
7928
+ node.attributes.width = "+0.1111em";
7929
+ } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
7930
+ // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
7931
+
7932
+ }
7933
+
7934
+ return node;
7935
+ } // Math class commands except \mathop
7936
+
7937
+
7938
+ defineFunction({
7939
+ type: "mclass",
7940
+ names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
7941
+ props: {
7942
+ numArgs: 1,
7943
+ primitive: true
7944
+ },
7945
+
7946
+ handler(_ref, args) {
7947
+ var {
7948
+ parser,
7949
+ funcName
7950
+ } = _ref;
7951
+ var body = args[0];
7952
+ return {
7953
+ type: "mclass",
7954
+ mode: parser.mode,
7955
+ mclass: "m" + funcName.slice(5),
7956
+ // TODO(kevinb): don't prefix with 'm'
7957
+ body: ordargument(body),
7958
+ isCharacterBox: utils.isCharacterBox(body)
7959
+ };
7960
+ },
7961
+
7962
+ htmlBuilder: htmlBuilder$9,
7963
+ mathmlBuilder: mathmlBuilder$8
7964
+ });
7965
+ var binrelClass = arg => {
7966
+ // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
7967
+ // (by rendering separately and with {}s before and after, and measuring
7968
+ // the change in spacing). We'll do roughly the same by detecting the
7969
+ // atom type directly.
7970
+ var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
7971
+
7972
+ if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
7973
+ return "m" + atom.family;
7974
+ } else {
7975
+ return "mord";
7976
+ }
7977
+ }; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
7978
+ // This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
7979
+
7980
+ defineFunction({
7981
+ type: "mclass",
7982
+ names: ["\\@binrel"],
7983
+ props: {
7984
+ numArgs: 2
7985
+ },
7986
+
7987
+ handler(_ref2, args) {
7988
+ var {
7989
+ parser
7990
+ } = _ref2;
7991
+ return {
7992
+ type: "mclass",
7993
+ mode: parser.mode,
7994
+ mclass: binrelClass(args[0]),
7995
+ body: ordargument(args[1]),
7996
+ isCharacterBox: utils.isCharacterBox(args[1])
7997
+ };
7998
+ }
7999
+
8000
+ }); // Build a relation or stacked op by placing one symbol on top of another
8001
+
8002
+ defineFunction({
8003
+ type: "mclass",
8004
+ names: ["\\stackrel", "\\overset", "\\underset"],
8005
+ props: {
8006
+ numArgs: 2
8007
+ },
8008
+
8009
+ handler(_ref3, args) {
8010
+ var {
8011
+ parser,
8012
+ funcName
8013
+ } = _ref3;
8014
+ var baseArg = args[1];
8015
+ var shiftedArg = args[0];
8016
+ var mclass;
8017
+
8018
+ if (funcName !== "\\stackrel") {
8019
+ // LaTeX applies \binrel spacing to \overset and \underset.
8020
+ mclass = binrelClass(baseArg);
8021
+ } else {
8022
+ mclass = "mrel"; // for \stackrel
8023
+ }
8024
+
8025
+ var baseOp = {
8026
+ type: "op",
8027
+ mode: baseArg.mode,
8028
+ limits: true,
8029
+ alwaysHandleSupSub: true,
8030
+ parentIsSupSub: false,
8031
+ symbol: false,
8032
+ suppressBaseShift: funcName !== "\\stackrel",
8033
+ body: ordargument(baseArg)
8034
+ };
8035
+ var supsub = {
8036
+ type: "supsub",
8037
+ mode: shiftedArg.mode,
8038
+ base: baseOp,
8039
+ sup: funcName === "\\underset" ? null : shiftedArg,
8040
+ sub: funcName === "\\underset" ? shiftedArg : null
8041
+ };
8042
+ return {
8043
+ type: "mclass",
8044
+ mode: parser.mode,
8045
+ mclass,
8046
+ body: [supsub],
8047
+ isCharacterBox: utils.isCharacterBox(supsub)
8048
+ };
8049
+ },
8050
+
8051
+ htmlBuilder: htmlBuilder$9,
8052
+ mathmlBuilder: mathmlBuilder$8
8053
+ });
8054
+
8055
+ // \pmb is a simulation of bold font.
8056
+ // The version of \pmb in ambsy.sty works by typesetting three copies
8057
+ // with small offsets. We use CSS text-shadow.
8058
+ // It's a hack. Not as good as a real bold font. Better than nothing.
8059
+ defineFunction({
8060
+ type: "pmb",
8061
+ names: ["\\pmb"],
8062
+ props: {
8063
+ numArgs: 1,
8064
+ allowedInText: true
8065
+ },
8066
+
8067
+ handler(_ref, args) {
8068
+ var {
8069
+ parser
8070
+ } = _ref;
8071
+ return {
8072
+ type: "pmb",
8073
+ mode: parser.mode,
8074
+ mclass: binrelClass(args[0]),
8075
+ body: ordargument(args[0])
8076
+ };
8077
+ },
8078
+
8079
+ htmlBuilder(group, options) {
8080
+ var elements = buildExpression$1(group.body, options, true);
8081
+ var node = buildCommon.makeSpan([group.mclass], elements, options);
8082
+ node.style.textShadow = "0.02em 0.01em 0.04px";
8083
+ return node;
8084
+ },
8085
+
8086
+ mathmlBuilder(group, style) {
8087
+ var inner = buildExpression(group.body, style); // Wrap with an <mstyle> element.
8088
+
8089
+ var node = new mathMLTree.MathNode("mstyle", inner);
8090
+ node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px");
8091
+ return node;
8092
+ }
8093
+
8094
+ });
8095
+
7848
8096
  var cdArrowFunctionName = {
7849
8097
  ">": "\\\\cdrightarrow",
7850
8098
  "<": "\\\\cdleftarrow",
@@ -8218,7 +8466,7 @@ defineFunction({
8218
8466
 
8219
8467
  });
8220
8468
 
8221
- var htmlBuilder$9 = (group, options) => {
8469
+ var htmlBuilder$8 = (group, options) => {
8222
8470
  var elements = buildExpression$1(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains.
8223
8471
  // To accomplish this, we wrap the results in a fragment, so the inner
8224
8472
  // elements will be able to directly interact with their neighbors. For
@@ -8227,7 +8475,7 @@ var htmlBuilder$9 = (group, options) => {
8227
8475
  return buildCommon.makeFragment(elements);
8228
8476
  };
8229
8477
 
8230
- var mathmlBuilder$8 = (group, options) => {
8478
+ var mathmlBuilder$7 = (group, options) => {
8231
8479
  var inner = buildExpression(group.body, options.withColor(group.color));
8232
8480
  var node = new mathMLTree.MathNode("mstyle", inner);
8233
8481
  node.setAttribute("mathcolor", group.color);
@@ -8257,8 +8505,8 @@ defineFunction({
8257
8505
  };
8258
8506
  },
8259
8507
 
8260
- htmlBuilder: htmlBuilder$9,
8261
- mathmlBuilder: mathmlBuilder$8
8508
+ htmlBuilder: htmlBuilder$8,
8509
+ mathmlBuilder: mathmlBuilder$7
8262
8510
  });
8263
8511
  defineFunction({
8264
8512
  type: "color",
@@ -8290,8 +8538,8 @@ defineFunction({
8290
8538
  };
8291
8539
  },
8292
8540
 
8293
- htmlBuilder: htmlBuilder$9,
8294
- mathmlBuilder: mathmlBuilder$8
8541
+ htmlBuilder: htmlBuilder$8,
8542
+ mathmlBuilder: mathmlBuilder$7
8295
8543
  });
8296
8544
 
8297
8545
  // Row breaks within tabular environments, and line breaks at top level
@@ -8762,6 +9010,8 @@ var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, opt
8762
9010
  var middle;
8763
9011
  var repeat;
8764
9012
  var bottom;
9013
+ var svgLabel = "";
9014
+ var viewBoxWidth = 0;
8765
9015
  top = repeat = bottom = delim;
8766
9016
  middle = null; // Also keep track of what font the delimiters are in
8767
9017
 
@@ -8787,44 +9037,64 @@ var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, opt
8787
9037
  bottom = "\\Downarrow";
8788
9038
  } else if (utils.contains(verts, delim)) {
8789
9039
  repeat = "\u2223";
9040
+ svgLabel = "vert";
9041
+ viewBoxWidth = 333;
8790
9042
  } else if (utils.contains(doubleVerts, delim)) {
8791
9043
  repeat = "\u2225";
9044
+ svgLabel = "doublevert";
9045
+ viewBoxWidth = 556;
8792
9046
  } else if (delim === "[" || delim === "\\lbrack") {
8793
9047
  top = "\u23a1";
8794
9048
  repeat = "\u23a2";
8795
9049
  bottom = "\u23a3";
8796
9050
  font = "Size4-Regular";
9051
+ svgLabel = "lbrack";
9052
+ viewBoxWidth = 667;
8797
9053
  } else if (delim === "]" || delim === "\\rbrack") {
8798
9054
  top = "\u23a4";
8799
9055
  repeat = "\u23a5";
8800
9056
  bottom = "\u23a6";
8801
9057
  font = "Size4-Regular";
9058
+ svgLabel = "rbrack";
9059
+ viewBoxWidth = 667;
8802
9060
  } else if (delim === "\\lfloor" || delim === "\u230a") {
8803
9061
  repeat = top = "\u23a2";
8804
9062
  bottom = "\u23a3";
8805
9063
  font = "Size4-Regular";
9064
+ svgLabel = "lfloor";
9065
+ viewBoxWidth = 667;
8806
9066
  } else if (delim === "\\lceil" || delim === "\u2308") {
8807
9067
  top = "\u23a1";
8808
9068
  repeat = bottom = "\u23a2";
8809
9069
  font = "Size4-Regular";
9070
+ svgLabel = "lceil";
9071
+ viewBoxWidth = 667;
8810
9072
  } else if (delim === "\\rfloor" || delim === "\u230b") {
8811
9073
  repeat = top = "\u23a5";
8812
9074
  bottom = "\u23a6";
8813
9075
  font = "Size4-Regular";
9076
+ svgLabel = "rfloor";
9077
+ viewBoxWidth = 667;
8814
9078
  } else if (delim === "\\rceil" || delim === "\u2309") {
8815
9079
  top = "\u23a4";
8816
9080
  repeat = bottom = "\u23a5";
8817
9081
  font = "Size4-Regular";
9082
+ svgLabel = "rceil";
9083
+ viewBoxWidth = 667;
8818
9084
  } else if (delim === "(" || delim === "\\lparen") {
8819
9085
  top = "\u239b";
8820
9086
  repeat = "\u239c";
8821
9087
  bottom = "\u239d";
8822
9088
  font = "Size4-Regular";
9089
+ svgLabel = "lparen";
9090
+ viewBoxWidth = 875;
8823
9091
  } else if (delim === ")" || delim === "\\rparen") {
8824
9092
  top = "\u239e";
8825
9093
  repeat = "\u239f";
8826
9094
  bottom = "\u23a0";
8827
9095
  font = "Size4-Regular";
9096
+ svgLabel = "rparen";
9097
+ viewBoxWidth = 875;
8828
9098
  } else if (delim === "\\{" || delim === "\\lbrace") {
8829
9099
  top = "\u23a7";
8830
9100
  middle = "\u23a8";
@@ -8896,32 +9166,59 @@ var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, opt
8896
9166
  var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist
8897
9167
  // Keep a list of the pieces of the stacked delimiter
8898
9168
 
8899
- var stack = []; // Add the bottom symbol
9169
+ var stack = [];
9170
+
9171
+ if (svgLabel.length > 0) {
9172
+ // Instead of stacking glyphs, create a single SVG.
9173
+ // This evades browser problems with imprecise positioning of spans.
9174
+ var midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
9175
+ var viewBoxHeight = Math.round(realHeightTotal * 1000);
9176
+ var pathStr = tallDelim(svgLabel, Math.round(midHeight * 1000));
9177
+ var path = new PathNode(svgLabel, pathStr);
9178
+ var width = (viewBoxWidth / 1000).toFixed(3) + "em";
9179
+ var height = (viewBoxHeight / 1000).toFixed(3) + "em";
9180
+ var svg = new SvgNode([path], {
9181
+ "width": width,
9182
+ "height": height,
9183
+ "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight
9184
+ });
9185
+ var wrapper = buildCommon.makeSvgSpan([], [svg], options);
9186
+ wrapper.height = viewBoxHeight / 1000;
9187
+ wrapper.style.width = width;
9188
+ wrapper.style.height = height;
9189
+ stack.push({
9190
+ type: "elem",
9191
+ elem: wrapper
9192
+ });
9193
+ } else {
9194
+ // Stack glyphs
9195
+ // Start by adding the bottom symbol
9196
+ stack.push(makeGlyphSpan(bottom, font, mode));
9197
+ stack.push(lap); // overlap
9198
+
9199
+ if (middle === null) {
9200
+ // The middle section will be an SVG. Make it an extra 0.016em tall.
9201
+ // We'll overlap by 0.008em at top and bottom.
9202
+ var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
9203
+ stack.push(makeInner(repeat, innerHeight, options));
9204
+ } else {
9205
+ // When there is a middle bit, we need the middle part and two repeated
9206
+ // sections
9207
+ var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
8900
9208
 
8901
- stack.push(makeGlyphSpan(bottom, font, mode));
8902
- stack.push(lap); // overlap
9209
+ stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace.
8903
9210
 
8904
- if (middle === null) {
8905
- // The middle section will be an SVG. Make it an extra 0.016em tall.
8906
- // We'll overlap by 0.008em at top and bottom.
8907
- var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
8908
- stack.push(makeInner(repeat, innerHeight, options));
8909
- } else {
8910
- // When there is a middle bit, we need the middle part and two repeated
8911
- // sections
8912
- var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
9211
+ stack.push(lap);
9212
+ stack.push(makeGlyphSpan(middle, font, mode));
9213
+ stack.push(lap);
9214
+ stack.push(makeInner(repeat, _innerHeight, options));
9215
+ } // Add the top symbol
8913
9216
 
8914
- stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace.
8915
9217
 
8916
9218
  stack.push(lap);
8917
- stack.push(makeGlyphSpan(middle, font, mode));
8918
- stack.push(lap);
8919
- stack.push(makeInner(repeat, _innerHeight, options));
8920
- } // Add the top symbol
8921
-
9219
+ stack.push(makeGlyphSpan(top, font, mode));
9220
+ } // Finally, build the vlist
8922
9221
 
8923
- stack.push(lap);
8924
- stack.push(makeGlyphSpan(top, font, mode)); // Finally, build the vlist
8925
9222
 
8926
9223
  var newOptions = options.havingBaseStyle(Style$1.TEXT);
8927
9224
  var inner = buildCommon.makeVList({
@@ -9603,12 +9900,12 @@ defineFunction({
9603
9900
  }
9604
9901
  });
9605
9902
 
9606
- var htmlBuilder$8 = (group, options) => {
9903
+ var htmlBuilder$7 = (group, options) => {
9607
9904
  // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
9608
9905
  // Some groups can return document fragments. Handle those by wrapping
9609
9906
  // them in a span.
9610
9907
  var inner = buildCommon.wrapFragment(buildGroup$1(group.body, options), options);
9611
- var label = group.label.substr(1);
9908
+ var label = group.label.slice(1);
9612
9909
  var scale = options.sizeMultiplier;
9613
9910
  var img;
9614
9911
  var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different
@@ -9755,7 +10052,7 @@ var htmlBuilder$8 = (group, options) => {
9755
10052
  }
9756
10053
  };
9757
10054
 
9758
- var mathmlBuilder$7 = (group, options) => {
10055
+ var mathmlBuilder$6 = (group, options) => {
9759
10056
  var fboxsep = 0;
9760
10057
  var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup(group.body, options)]);
9761
10058
 
@@ -9841,8 +10138,8 @@ defineFunction({
9841
10138
  };
9842
10139
  },
9843
10140
 
9844
- htmlBuilder: htmlBuilder$8,
9845
- mathmlBuilder: mathmlBuilder$7
10141
+ htmlBuilder: htmlBuilder$7,
10142
+ mathmlBuilder: mathmlBuilder$6
9846
10143
  });
9847
10144
  defineFunction({
9848
10145
  type: "enclose",
@@ -9871,8 +10168,8 @@ defineFunction({
9871
10168
  };
9872
10169
  },
9873
10170
 
9874
- htmlBuilder: htmlBuilder$8,
9875
- mathmlBuilder: mathmlBuilder$7
10171
+ htmlBuilder: htmlBuilder$7,
10172
+ mathmlBuilder: mathmlBuilder$6
9876
10173
  });
9877
10174
  defineFunction({
9878
10175
  type: "enclose",
@@ -9917,8 +10214,8 @@ defineFunction({
9917
10214
  };
9918
10215
  },
9919
10216
 
9920
- htmlBuilder: htmlBuilder$8,
9921
- mathmlBuilder: mathmlBuilder$7
10217
+ htmlBuilder: htmlBuilder$7,
10218
+ mathmlBuilder: mathmlBuilder$6
9922
10219
  });
9923
10220
  defineFunction({
9924
10221
  type: "enclose",
@@ -10205,14 +10502,14 @@ function parseArray(parser, _ref, style) {
10205
10502
 
10206
10503
 
10207
10504
  function dCellStyle(envName) {
10208
- if (envName.substr(0, 1) === "d") {
10505
+ if (envName.slice(0, 1) === "d") {
10209
10506
  return "display";
10210
10507
  } else {
10211
10508
  return "text";
10212
10509
  }
10213
10510
  }
10214
10511
 
10215
- var htmlBuilder$7 = function htmlBuilder(group, options) {
10512
+ var htmlBuilder$6 = function htmlBuilder(group, options) {
10216
10513
  var r;
10217
10514
  var c;
10218
10515
  var nr = group.body.length;
@@ -10515,7 +10812,7 @@ var alignMap = {
10515
10812
  r: "right "
10516
10813
  };
10517
10814
 
10518
- var mathmlBuilder$6 = function mathmlBuilder(group, options) {
10815
+ var mathmlBuilder$5 = function mathmlBuilder(group, options) {
10519
10816
  var tbl = [];
10520
10817
  var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]);
10521
10818
  var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]);
@@ -10799,8 +11096,8 @@ defineEnvironment({
10799
11096
  return parseArray(context.parser, res, dCellStyle(context.envName));
10800
11097
  },
10801
11098
 
10802
- htmlBuilder: htmlBuilder$7,
10803
- mathmlBuilder: mathmlBuilder$6
11099
+ htmlBuilder: htmlBuilder$6,
11100
+ mathmlBuilder: mathmlBuilder$5
10804
11101
  }); // The matrix environments of amsmath builds on the array environment
10805
11102
  // of LaTeX, which is discussed above.
10806
11103
  // The mathtools package adds starred versions of the same environments.
@@ -10876,8 +11173,8 @@ defineEnvironment({
10876
11173
  } : res;
10877
11174
  },
10878
11175
 
10879
- htmlBuilder: htmlBuilder$7,
10880
- mathmlBuilder: mathmlBuilder$6
11176
+ htmlBuilder: htmlBuilder$6,
11177
+ mathmlBuilder: mathmlBuilder$5
10881
11178
  });
10882
11179
  defineEnvironment({
10883
11180
  type: "array",
@@ -10895,8 +11192,8 @@ defineEnvironment({
10895
11192
  return res;
10896
11193
  },
10897
11194
 
10898
- htmlBuilder: htmlBuilder$7,
10899
- mathmlBuilder: mathmlBuilder$6
11195
+ htmlBuilder: htmlBuilder$6,
11196
+ mathmlBuilder: mathmlBuilder$5
10900
11197
  });
10901
11198
  defineEnvironment({
10902
11199
  type: "array",
@@ -10941,8 +11238,8 @@ defineEnvironment({
10941
11238
  return res;
10942
11239
  },
10943
11240
 
10944
- htmlBuilder: htmlBuilder$7,
10945
- mathmlBuilder: mathmlBuilder$6
11241
+ htmlBuilder: htmlBuilder$6,
11242
+ mathmlBuilder: mathmlBuilder$5
10946
11243
  }); // A cases environment (in amsmath.sty) is almost equivalent to
10947
11244
  // \def\arraystretch{1.2}%
10948
11245
  // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
@@ -10989,8 +11286,8 @@ defineEnvironment({
10989
11286
  };
10990
11287
  },
10991
11288
 
10992
- htmlBuilder: htmlBuilder$7,
10993
- mathmlBuilder: mathmlBuilder$6
11289
+ htmlBuilder: htmlBuilder$6,
11290
+ mathmlBuilder: mathmlBuilder$5
10994
11291
  }); // In the align environment, one uses ampersands, &, to specify number of
10995
11292
  // columns in each row, and to locate spacing between each column.
10996
11293
  // align gets automatic numbering. align* and aligned do not.
@@ -11005,8 +11302,8 @@ defineEnvironment({
11005
11302
  numArgs: 0
11006
11303
  },
11007
11304
  handler: alignedHandler,
11008
- htmlBuilder: htmlBuilder$7,
11009
- mathmlBuilder: mathmlBuilder$6
11305
+ htmlBuilder: htmlBuilder$6,
11306
+ mathmlBuilder: mathmlBuilder$5
11010
11307
  }); // A gathered environment is like an array environment with one centered
11011
11308
  // column, but where rows are considered lines so get \jot line spacing
11012
11309
  // and contents are set in \displaystyle.
@@ -11037,8 +11334,8 @@ defineEnvironment({
11037
11334
  return parseArray(context.parser, res, "display");
11038
11335
  },
11039
11336
 
11040
- htmlBuilder: htmlBuilder$7,
11041
- mathmlBuilder: mathmlBuilder$6
11337
+ htmlBuilder: htmlBuilder$6,
11338
+ mathmlBuilder: mathmlBuilder$5
11042
11339
  }); // alignat environment is like an align environment, but one must explicitly
11043
11340
  // specify maximum number of columns in each row, and can adjust spacing between
11044
11341
  // each columns.
@@ -11050,8 +11347,8 @@ defineEnvironment({
11050
11347
  numArgs: 1
11051
11348
  },
11052
11349
  handler: alignedHandler,
11053
- htmlBuilder: htmlBuilder$7,
11054
- mathmlBuilder: mathmlBuilder$6
11350
+ htmlBuilder: htmlBuilder$6,
11351
+ mathmlBuilder: mathmlBuilder$5
11055
11352
  });
11056
11353
  defineEnvironment({
11057
11354
  type: "array",
@@ -11072,8 +11369,8 @@ defineEnvironment({
11072
11369
  return parseArray(context.parser, res, "display");
11073
11370
  },
11074
11371
 
11075
- htmlBuilder: htmlBuilder$7,
11076
- mathmlBuilder: mathmlBuilder$6
11372
+ htmlBuilder: htmlBuilder$6,
11373
+ mathmlBuilder: mathmlBuilder$5
11077
11374
  });
11078
11375
  defineEnvironment({
11079
11376
  type: "array",
@@ -11087,8 +11384,8 @@ defineEnvironment({
11087
11384
  return parseCD(context.parser);
11088
11385
  },
11089
11386
 
11090
- htmlBuilder: htmlBuilder$7,
11091
- mathmlBuilder: mathmlBuilder$6
11387
+ htmlBuilder: htmlBuilder$6,
11388
+ mathmlBuilder: mathmlBuilder$5
11092
11389
  });
11093
11390
  defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");
11094
11391
  defineMacro("\\notag", "\\nonumber"); // Catch \hline outside array environment
@@ -11179,176 +11476,6 @@ defineFunction({
11179
11476
 
11180
11477
  });
11181
11478
 
11182
- var makeSpan = buildCommon.makeSpan;
11183
-
11184
- function htmlBuilder$6(group, options) {
11185
- var elements = buildExpression$1(group.body, options, true);
11186
- return makeSpan([group.mclass], elements, options);
11187
- }
11188
-
11189
- function mathmlBuilder$5(group, options) {
11190
- var node;
11191
- var inner = buildExpression(group.body, options);
11192
-
11193
- if (group.mclass === "minner") {
11194
- node = new mathMLTree.MathNode("mpadded", inner);
11195
- } else if (group.mclass === "mord") {
11196
- if (group.isCharacterBox) {
11197
- node = inner[0];
11198
- node.type = "mi";
11199
- } else {
11200
- node = new mathMLTree.MathNode("mi", inner);
11201
- }
11202
- } else {
11203
- if (group.isCharacterBox) {
11204
- node = inner[0];
11205
- node.type = "mo";
11206
- } else {
11207
- node = new mathMLTree.MathNode("mo", inner);
11208
- } // Set spacing based on what is the most likely adjacent atom type.
11209
- // See TeXbook p170.
11210
-
11211
-
11212
- if (group.mclass === "mbin") {
11213
- node.attributes.lspace = "0.22em"; // medium space
11214
-
11215
- node.attributes.rspace = "0.22em";
11216
- } else if (group.mclass === "mpunct") {
11217
- node.attributes.lspace = "0em";
11218
- node.attributes.rspace = "0.17em"; // thinspace
11219
- } else if (group.mclass === "mopen" || group.mclass === "mclose") {
11220
- node.attributes.lspace = "0em";
11221
- node.attributes.rspace = "0em";
11222
- } else if (group.mclass === "minner") {
11223
- node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option
11224
-
11225
- node.attributes.width = "+0.1111em";
11226
- } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
11227
- // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
11228
-
11229
- }
11230
-
11231
- return node;
11232
- } // Math class commands except \mathop
11233
-
11234
-
11235
- defineFunction({
11236
- type: "mclass",
11237
- names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
11238
- props: {
11239
- numArgs: 1,
11240
- primitive: true
11241
- },
11242
-
11243
- handler(_ref, args) {
11244
- var {
11245
- parser,
11246
- funcName
11247
- } = _ref;
11248
- var body = args[0];
11249
- return {
11250
- type: "mclass",
11251
- mode: parser.mode,
11252
- mclass: "m" + funcName.substr(5),
11253
- // TODO(kevinb): don't prefix with 'm'
11254
- body: ordargument(body),
11255
- isCharacterBox: utils.isCharacterBox(body)
11256
- };
11257
- },
11258
-
11259
- htmlBuilder: htmlBuilder$6,
11260
- mathmlBuilder: mathmlBuilder$5
11261
- });
11262
- var binrelClass = arg => {
11263
- // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
11264
- // (by rendering separately and with {}s before and after, and measuring
11265
- // the change in spacing). We'll do roughly the same by detecting the
11266
- // atom type directly.
11267
- var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
11268
-
11269
- if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
11270
- return "m" + atom.family;
11271
- } else {
11272
- return "mord";
11273
- }
11274
- }; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
11275
- // This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
11276
-
11277
- defineFunction({
11278
- type: "mclass",
11279
- names: ["\\@binrel"],
11280
- props: {
11281
- numArgs: 2
11282
- },
11283
-
11284
- handler(_ref2, args) {
11285
- var {
11286
- parser
11287
- } = _ref2;
11288
- return {
11289
- type: "mclass",
11290
- mode: parser.mode,
11291
- mclass: binrelClass(args[0]),
11292
- body: ordargument(args[1]),
11293
- isCharacterBox: utils.isCharacterBox(args[1])
11294
- };
11295
- }
11296
-
11297
- }); // Build a relation or stacked op by placing one symbol on top of another
11298
-
11299
- defineFunction({
11300
- type: "mclass",
11301
- names: ["\\stackrel", "\\overset", "\\underset"],
11302
- props: {
11303
- numArgs: 2
11304
- },
11305
-
11306
- handler(_ref3, args) {
11307
- var {
11308
- parser,
11309
- funcName
11310
- } = _ref3;
11311
- var baseArg = args[1];
11312
- var shiftedArg = args[0];
11313
- var mclass;
11314
-
11315
- if (funcName !== "\\stackrel") {
11316
- // LaTeX applies \binrel spacing to \overset and \underset.
11317
- mclass = binrelClass(baseArg);
11318
- } else {
11319
- mclass = "mrel"; // for \stackrel
11320
- }
11321
-
11322
- var baseOp = {
11323
- type: "op",
11324
- mode: baseArg.mode,
11325
- limits: true,
11326
- alwaysHandleSupSub: true,
11327
- parentIsSupSub: false,
11328
- symbol: false,
11329
- suppressBaseShift: funcName !== "\\stackrel",
11330
- body: ordargument(baseArg)
11331
- };
11332
- var supsub = {
11333
- type: "supsub",
11334
- mode: shiftedArg.mode,
11335
- base: baseOp,
11336
- sup: funcName === "\\underset" ? null : shiftedArg,
11337
- sub: funcName === "\\underset" ? shiftedArg : null
11338
- };
11339
- return {
11340
- type: "mclass",
11341
- mode: parser.mode,
11342
- mclass,
11343
- body: [supsub],
11344
- isCharacterBox: utils.isCharacterBox(supsub)
11345
- };
11346
- },
11347
-
11348
- htmlBuilder: htmlBuilder$6,
11349
- mathmlBuilder: mathmlBuilder$5
11350
- });
11351
-
11352
11479
  // TODO(kevinb): implement \\sl and \\sc
11353
11480
 
11354
11481
  var htmlBuilder$5 = (group, options) => {
@@ -12946,7 +13073,7 @@ var htmlBuilder$2 = (grp, options) => {
12946
13073
  if (group.name === "\\oiint" || group.name === "\\oiiint") {
12947
13074
  // No font glyphs yet, so use a glyph w/o the oval.
12948
13075
  // TODO: When font glyphs are available, delete this code.
12949
- stash = group.name.substr(1);
13076
+ stash = group.name.slice(1);
12950
13077
  group.name = stash === "oiint" ? "\\iint" : "\\iiint";
12951
13078
  }
12952
13079
 
@@ -15407,7 +15534,7 @@ defineMacro("\\dots", function (context) {
15407
15534
 
15408
15535
  if (next in dotsByToken) {
15409
15536
  thedots = dotsByToken[next];
15410
- } else if (next.substr(0, 4) === '\\not') {
15537
+ } else if (next.slice(0, 4) === '\\not') {
15411
15538
  thedots = '\\dotsb';
15412
15539
  } else if (next in symbols.math) {
15413
15540
  if (utils.contains(['bin', 'rel'], symbols.math[next].group)) {
@@ -15544,12 +15671,7 @@ defineMacro("\\tag@literal", context => {
15544
15671
  defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
15545
15672
  defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
15546
15673
  defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
15547
- defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb -- A simulation of bold.
15548
- // The version in ambsy.sty works by typesetting three copies of the argument
15549
- // with small offsets. We use two copies. We omit the vertical offset because
15550
- // of rendering problems that makeVList encounters in Safari.
15551
-
15552
- defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); //////////////////////////////////////////////////////////////////////
15674
+ defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); //////////////////////////////////////////////////////////////////////
15553
15675
  // LaTeX source2e
15554
15676
  // \expandafter\let\expandafter\@normalcr
15555
15677
  // \csname\expandafter\@gobble\string\\ \endcsname
@@ -17922,7 +18044,7 @@ class Parser {
17922
18044
  this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
17923
18045
  }
17924
18046
 
17925
- text = unicodeSymbols[text[0]] + text.substr(1);
18047
+ text = unicodeSymbols[text[0]] + text.slice(1);
17926
18048
  } // Strip off any combining characters
17927
18049
 
17928
18050
 
@@ -18168,7 +18290,7 @@ var katex = {
18168
18290
  /**
18169
18291
  * Current KaTeX version
18170
18292
  */
18171
- version: "0.15.6",
18293
+ version: "0.16.2",
18172
18294
 
18173
18295
  /**
18174
18296
  * Renders the given LaTeX into an HTML+MathML combination, and adds