temml 0.12.1 → 0.12.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.
package/dist/temml.mjs CHANGED
@@ -179,6 +179,9 @@ const round = function(n) {
179
179
  return +n.toFixed(4);
180
180
  };
181
181
 
182
+ // Identify short letters. Used for accents and \cancelto.
183
+ const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳";
184
+
182
185
  /**
183
186
  * This is a module for storing settings passed into Temml. It correctly handles
184
187
  * default settings.
@@ -794,6 +797,8 @@ const stretchyCodePoint = {
794
797
  xrightarrow: "\u2192",
795
798
  underbrace: "\u23df",
796
799
  overbrace: "\u23de",
800
+ overbracket: "\u23b4",
801
+ underbracket: "\u23b5",
797
802
  overgroup: "\u23e0",
798
803
  overparen: "⏜",
799
804
  undergroup: "\u23e1",
@@ -2449,9 +2454,6 @@ function buildMathML(tree, texExpression, style, settings) {
2449
2454
  return math;
2450
2455
  }
2451
2456
 
2452
- // Identify letters to which we'll attach a combining accent character
2453
- const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳";
2454
-
2455
2457
  // From the KaTeX font metrics, identify letters whose accents need a italic correction.
2456
2458
  const smallNudge = "DHKLUcegorsuvxyzΠΥΨαδηιμνοτυχϵ";
2457
2459
  const mediumNudge = "BCEGIMNOPQRSTXZlpqtwΓΘΞΣΦΩβεζθξρςφψϑϕϱ";
@@ -6432,6 +6434,7 @@ const mathmlBuilder$9 = function(group, style) {
6432
6434
  const tbl = [];
6433
6435
  const numRows = group.body.length;
6434
6436
  const hlines = group.hLinesBeforeRow;
6437
+ const tagIsPresent = (group.tags && group.tags.some((tag) => tag));
6435
6438
 
6436
6439
  for (let i = 0; i < numRows; i++) {
6437
6440
  const rw = group.body[i];
@@ -6461,7 +6464,7 @@ const mathmlBuilder$9 = function(group, style) {
6461
6464
  for (let k = 0; k < numColumns - rw.length; k++) {
6462
6465
  row.push(new MathNode("mtd", [], [], style));
6463
6466
  }
6464
- if (group.autoTag) {
6467
+ if (tagIsPresent) {
6465
6468
  const tag = group.tags[i];
6466
6469
  let tagElement;
6467
6470
  if (tag === true) { // automatic numbering
@@ -6573,7 +6576,7 @@ const mathmlBuilder$9 = function(group, style) {
6573
6576
  if (j === numCols - 1 && hand === 1) { return "0" }
6574
6577
  if (group.envClasses[0] !== "align") { return sidePadding }
6575
6578
  if (hand === 1) { return "0" }
6576
- if (group.autoTag) {
6579
+ if (tagIsPresent) {
6577
6580
  return (j % 2) ? "1" : "0"
6578
6581
  } else {
6579
6582
  return (j % 2) ? "0" : "1"
@@ -6609,7 +6612,7 @@ const mathmlBuilder$9 = function(group, style) {
6609
6612
  // TODO: Remove -webkit- when Chromium no longer needs it.
6610
6613
  row.children[j].classes = ["tml-" + (j % 2 ? "left" : "right")];
6611
6614
  }
6612
- if (group.autoTag) {
6615
+ if (tagIsPresent) {
6613
6616
  const k = group.leqno ? 0 : row.children.length - 1;
6614
6617
  row.children[k].classes = []; // Default is center.
6615
6618
  }
@@ -6666,7 +6669,7 @@ const mathmlBuilder$9 = function(group, style) {
6666
6669
  row.children[0].style.borderLeft = sep;
6667
6670
  }
6668
6671
  }
6669
- let iCol = group.autoTag ? 0 : -1;
6672
+ let iCol = tagIsPresent ? 0 : -1;
6670
6673
  for (let i = iStart; i < iEnd; i++) {
6671
6674
  if (cols[i].type === "align") {
6672
6675
  const colAlign = alignMap[cols[i].align];
@@ -7192,6 +7195,78 @@ defineFunction({
7192
7195
  }
7193
7196
  });
7194
7197
 
7198
+ defineFunction({
7199
+ type: "cancelto",
7200
+ names: ["\\cancelto"],
7201
+ props: {
7202
+ numArgs: 2
7203
+ },
7204
+ handler({ parser }, args) {
7205
+ const to = args[0];
7206
+ const body = args[1];
7207
+ return {
7208
+ type: "cancelto",
7209
+ mode: parser.mode,
7210
+ body,
7211
+ to,
7212
+ isCharacterBox: isCharacterBox(body)
7213
+ };
7214
+ },
7215
+ mathmlBuilder(group, style) {
7216
+ const fromNode = new MathNode(
7217
+ "mrow",
7218
+ [buildGroup$1(group.body, style)],
7219
+ ["ff-narrow"] // A zero-width mrow.
7220
+ );
7221
+ // Write the arrow in a node written after the content.
7222
+ // That way, the arrow will be an overlay on the content.
7223
+ const phantom = new MathNode("mphantom", [buildGroup$1(group.body, style)]);
7224
+ const arrow = new MathNode("mrow", [phantom], ["tml-cancelto"]);
7225
+ if (group.isCharacterBox && smalls.indexOf(group.body.body[0].text) > -1) {
7226
+ arrow.style.left = "0.1em";
7227
+ arrow.style.width = "90%";
7228
+ }
7229
+ const node = new MathNode("mrow", [fromNode, arrow], ["menclose"]);
7230
+ if (!group.isCharacterBox || /[f∫∑]/.test(group.body.body[0].text)) {
7231
+ // Add 0.2em space to right of content to make room for the arrowhead.
7232
+ phantom.style.paddingRight = "0.2em";
7233
+ } else {
7234
+ phantom.style.padding = "0.5ex 0.1em 0 0";
7235
+ const strut = new MathNode('mspace', []);
7236
+ strut.setAttribute('height', "0.85em");
7237
+ fromNode.children.push(strut);
7238
+ }
7239
+
7240
+ // Create the "to" value above and to the right of the arrow.
7241
+ // First, we want a dummy node with the same height as the `from` content.
7242
+ // We'll place the `to` node above the dummy to get the correct vertical alignment.
7243
+ let dummyNode;
7244
+ if (group.isCharacterBox) {
7245
+ dummyNode = new MathNode('mspace', []);
7246
+ dummyNode.setAttribute('height', "1em");
7247
+ } else {
7248
+ // Create a phantom node with the same content as the body.
7249
+ const inner = buildGroup$1(group.body, style);
7250
+ // The phantom node will be zero-width, so it won't affect horizontal spacing.
7251
+ const zeroWidthNode = new MathNode("mpadded", [inner]);
7252
+ zeroWidthNode.setAttribute("width", "0.1px"); // Don't use 0. WebKit would omit it.
7253
+ dummyNode = new MathNode("mphantom", [zeroWidthNode]); // Hide it.
7254
+ }
7255
+ const toNode = buildGroup$1(group.to, style);
7256
+ const zeroWidthToNode = new MathNode("mpadded", [toNode]);
7257
+ if (!group.isCharacterBox || /[f∫∑]/.test(group.body.body[0].text)) {
7258
+ const w = new MathNode("mspace", []);
7259
+ w.setAttribute('width', "0.2em");
7260
+ zeroWidthToNode.children.unshift(w);
7261
+ }
7262
+ zeroWidthToNode.setAttribute("width", "0.1px"); // Don't use 0. WebKit would hide it.
7263
+ const mover = new MathNode("mover", [dummyNode, zeroWidthToNode]);
7264
+ // Fix Firefox positioning.
7265
+ const nudgeLeft = new MathNode('mrow', [], ["ff-nudge-left"]);
7266
+ return newDocumentFragment([makeRow([node, mover]), nudgeLeft])
7267
+ }
7268
+ });
7269
+
7195
7270
  // \@char is an internal function that takes a grouped decimal argument like
7196
7271
  // {123} and converts into symbol with code 123. It is used by the *macro*
7197
7272
  // \char defined in macros.js.
@@ -8118,8 +8193,10 @@ defineFunction({
8118
8193
  }
8119
8194
  });
8120
8195
 
8196
+ const boxTags = ["\\boxed", "\\fcolorbox", "\\colorbox"];
8197
+
8121
8198
  const mathmlBuilder$7 = (group, style) => {
8122
- const tag = group.label === "\\boxed" ? "mrow" : "menclose";
8199
+ const tag = boxTags.includes(group.label) ? "mrow" : "menclose";
8123
8200
  const node = new MathNode(tag, [buildGroup$1(group.body, style)]);
8124
8201
  switch (group.label) {
8125
8202
  case "\\overline":
@@ -8146,6 +8223,7 @@ const mathmlBuilder$7 = (group, style) => {
8146
8223
  node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
8147
8224
  node.classes.push("tml-xcancel");
8148
8225
  break
8226
+ // cancelto is handled in cancelto.js
8149
8227
  case "\\longdiv":
8150
8228
  node.setAttribute("notation", "longdiv");
8151
8229
  node.classes.push("longdiv-top");
@@ -8178,13 +8256,8 @@ const mathmlBuilder$7 = (group, style) => {
8178
8256
  break
8179
8257
  case "\\fcolorbox":
8180
8258
  case "\\colorbox": {
8181
- // <menclose> doesn't have a good notation option for \colorbox.
8182
- // So use <mpadded> instead. Set some attributes that come
8183
- // included with <menclose>.
8184
- //const fboxsep = 3; // 3 pt from LaTeX source2e
8185
- //node.setAttribute("height", `+${2 * fboxsep}pt`)
8186
- //node.setAttribute("voffset", `${fboxsep}pt`)
8187
- node.style.padding = "3pt";
8259
+ // Don't use <menclose>. WebKit would show a radical.
8260
+ node.style.padding = "0.3em"; // 3 pt from LaTeX source2e for a 10pt font
8188
8261
  if (group.label === "\\fcolorbox") {
8189
8262
  node.style.border = "0.0667em solid " + String(group.borderColor);
8190
8263
  }
@@ -8953,16 +9026,16 @@ const mathmlBuilder$4 = (group, style) => {
8953
9026
  ]);
8954
9027
  };
8955
9028
 
8956
- // Horizontal stretchy braces
9029
+ // Horizontal stretchy brackets
8957
9030
  defineFunction({
8958
- type: "horizBrace",
8959
- names: ["\\overbrace", "\\underbrace"],
9031
+ type: "horizBracket",
9032
+ names: ["\\overbrace", "\\underbrace", "\\overbracket", "\\underbracket"],
8960
9033
  props: {
8961
9034
  numArgs: 1
8962
9035
  },
8963
9036
  handler({ parser, funcName }, args) {
8964
9037
  return {
8965
- type: "horizBrace",
9038
+ type: "horizBracket",
8966
9039
  mode: parser.mode,
8967
9040
  label: funcName,
8968
9041
  isOver: /^\\over/.test(funcName),
@@ -10118,7 +10191,8 @@ defineFunction({
10118
10191
  "\u2a1a"
10119
10192
  ],
10120
10193
  props: {
10121
- numArgs: 0
10194
+ numArgs: 0,
10195
+ allowedInArgument: true
10122
10196
  },
10123
10197
  handler({ parser, funcName }) {
10124
10198
  let fName = funcName;
@@ -10858,18 +10932,18 @@ const largePad = "AJdfΔΛ";
10858
10932
  defineFunctionBuilders({
10859
10933
  type: "supsub",
10860
10934
  mathmlBuilder(group, style) {
10861
- // Is the inner group a relevant horizontal brace?
10862
- let isBrace = false;
10935
+ // Is the inner group a relevant horizontal brace or bracket?
10936
+ let isBracket = false;
10863
10937
  let isOver;
10864
10938
  let isSup;
10865
10939
  let appendApplyFunction = false;
10866
10940
  let appendSpace = false;
10867
10941
  let needsLeadingSpace = false;
10868
10942
 
10869
- if (group.base && group.base.type === "horizBrace") {
10943
+ if (group.base && group.base.type === "horizBracket") {
10870
10944
  isSup = !!group.sup;
10871
10945
  if (isSup === group.base.isOver) {
10872
- isBrace = true;
10946
+ isBracket = true;
10873
10947
  isOver = group.base.isOver;
10874
10948
  }
10875
10949
  }
@@ -10917,7 +10991,7 @@ defineFunctionBuilders({
10917
10991
  }
10918
10992
 
10919
10993
  let nodeType;
10920
- if (isBrace) {
10994
+ if (isBracket) {
10921
10995
  nodeType = isOver ? "mover" : "munder";
10922
10996
  } else if (!group.sub) {
10923
10997
  const base = group.base;
@@ -13987,7 +14061,7 @@ class Style {
13987
14061
  * https://mit-license.org/
13988
14062
  */
13989
14063
 
13990
- const version = "0.12.01";
14064
+ const version = "0.12.02";
13991
14065
 
13992
14066
  function postProcess(block) {
13993
14067
  const labelMap = {};
@@ -11,7 +11,7 @@
11
11
  * https://mit-license.org/
12
12
  */
13
13
 
14
- const version = "0.12.01";
14
+ const version = "0.12.02";
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.12.01",
3
+ "version": "0.12.02",
4
4
  "description": "TeX to MathML conversion in JavaScript.",
5
5
  "main": "dist/temml.js",
6
6
  "engines": {
@@ -0,0 +1,15 @@
1
+ <svg xmlns='http://www.w3.org/2000/svg'>
2
+ <!--See Temml CSS files for minified versions of this arrow.-->
3
+ <defs>
4
+ <marker id='arrowhead'
5
+ markerWidth='7' markerHeight='5'
6
+ refX='7' refY='2.5'
7
+ orient='auto'
8
+ markerUnits='strokeWidth'>
9
+ <path d='M0,0 L7,2.5 L0,5 z' fill='currentColor' stroke='none'/>
10
+ </marker>
11
+ </defs>
12
+ <line y1='100%' x2='100%' stroke='currentColor' stroke-width='0.06em'
13
+ vector-effect='non-scaling-stroke' marker-end='url(#arrowhead)'>
14
+ </line>
15
+ </svg>
@@ -267,6 +267,7 @@ const mathmlBuilder = function(group, style) {
267
267
  const tbl = [];
268
268
  const numRows = group.body.length
269
269
  const hlines = group.hLinesBeforeRow;
270
+ const tagIsPresent = (group.tags && group.tags.some((tag) => tag));
270
271
 
271
272
  for (let i = 0; i < numRows; i++) {
272
273
  const rw = group.body[i];
@@ -296,7 +297,7 @@ const mathmlBuilder = function(group, style) {
296
297
  for (let k = 0; k < numColumns - rw.length; k++) {
297
298
  row.push(new mathMLTree.MathNode("mtd", [], [], style))
298
299
  }
299
- if (group.autoTag) {
300
+ if (tagIsPresent) {
300
301
  const tag = group.tags[i];
301
302
  let tagElement
302
303
  if (tag === true) { // automatic numbering
@@ -408,7 +409,7 @@ const mathmlBuilder = function(group, style) {
408
409
  if (j === numCols - 1 && hand === 1) { return "0" }
409
410
  if (group.envClasses[0] !== "align") { return sidePadding }
410
411
  if (hand === 1) { return "0" }
411
- if (group.autoTag) {
412
+ if (tagIsPresent) {
412
413
  return (j % 2) ? "1" : "0"
413
414
  } else {
414
415
  return (j % 2) ? "0" : "1"
@@ -444,7 +445,7 @@ const mathmlBuilder = function(group, style) {
444
445
  // TODO: Remove -webkit- when Chromium no longer needs it.
445
446
  row.children[j].classes = ["tml-" + (j % 2 ? "left" : "right")]
446
447
  }
447
- if (group.autoTag) {
448
+ if (tagIsPresent) {
448
449
  const k = group.leqno ? 0 : row.children.length - 1
449
450
  row.children[k].classes = []; // Default is center.
450
451
  }
@@ -501,7 +502,7 @@ const mathmlBuilder = function(group, style) {
501
502
  row.children[0].style.borderLeft = sep
502
503
  }
503
504
  }
504
- let iCol = group.autoTag ? 0 : -1
505
+ let iCol = tagIsPresent ? 0 : -1
505
506
  for (let i = iStart; i < iEnd; i++) {
506
507
  if (cols[i].type === "align") {
507
508
  const colAlign = alignMap[cols[i].align];
@@ -2,9 +2,8 @@ import defineFunction, { normalizeArgument } from "../defineFunction"
2
2
  import * as mathMLTree from "../mathMLTree"
3
3
  import * as stretchy from "../stretchy"
4
4
  import * as mml from "../buildMathML"
5
+ import { smalls } from "../utils"
5
6
 
6
- // Identify letters to which we'll attach a combining accent character
7
- const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳"
8
7
 
9
8
  // From the KaTeX font metrics, identify letters whose accents need a italic correction.
10
9
  const smallNudge = "DHKLUcegorsuvxyzΠΥΨαδηιμνοτυχϵ"
@@ -1,6 +1,7 @@
1
1
  import defineFunction from "../defineFunction";
2
2
  import * as mathMLTree from "../mathMLTree";
3
3
  import * as mml from "../buildMathML";
4
+ import { isCharacterBox, smalls } from "../utils";
4
5
 
5
6
  defineFunction({
6
7
  type: "cancelto",
@@ -9,28 +10,67 @@ defineFunction({
9
10
  numArgs: 2
10
11
  },
11
12
  handler({ parser }, args) {
13
+ const to = args[0];
14
+ const body = args[1];
12
15
  return {
13
16
  type: "cancelto",
14
17
  mode: parser.mode,
15
- value: args[0],
16
- expression: args[1]
18
+ body,
19
+ to,
20
+ isCharacterBox: isCharacterBox(body)
17
21
  };
18
22
  },
19
23
  mathmlBuilder(group, style) {
20
- const value = new mathMLTree.MathNode(
21
- "mpadded",
22
- [mml.buildGroup(group.value, style)]
24
+ const fromNode = new mathMLTree.MathNode(
25
+ "mrow",
26
+ [mml.buildGroup(group.body, style)],
27
+ ["ff-narrow"] // A zero-width mrow.
23
28
  )
24
- value.setAttribute("depth", `-0.1em`)
25
- value.setAttribute("height", `+0.1em`)
26
- value.setAttribute("voffset", `0.1em`)
29
+ // Write the arrow in a node written after the content.
30
+ // That way, the arrow will be an overlay on the content.
31
+ const phantom = new mathMLTree.MathNode("mphantom", [mml.buildGroup(group.body, style)])
32
+ const arrow = new mathMLTree.MathNode("mrow", [phantom], ["tml-cancelto"])
33
+ if (group.isCharacterBox && smalls.indexOf(group.body.body[0].text) > -1) {
34
+ arrow.style.left = "0.1em"
35
+ arrow.style.width = "90%"
36
+ }
37
+ const node = new mathMLTree.MathNode("mrow", [fromNode, arrow], ["menclose"])
38
+ if (!group.isCharacterBox || /[f∫∑]/.test(group.body.body[0].text)) {
39
+ // Add 0.2em space to right of content to make room for the arrowhead.
40
+ phantom.style.paddingRight = "0.2em"
41
+ } else {
42
+ phantom.style.padding = "0.5ex 0.1em 0 0"
43
+ const strut = new mathMLTree.MathNode('mspace', [])
44
+ strut.setAttribute('height', "0.85em")
45
+ fromNode.children.push(strut)
46
+ }
27
47
 
28
- const expression = new mathMLTree.MathNode(
29
- "menclose",
30
- [mml.buildGroup(group.expression, style)]
31
- )
32
- expression.setAttribute("notation", `updiagonalarrow`)
33
-
34
- return new mathMLTree.MathNode("msup", [expression, value])
48
+ // Create the "to" value above and to the right of the arrow.
49
+ // First, we want a dummy node with the same height as the `from` content.
50
+ // We'll place the `to` node above the dummy to get the correct vertical alignment.
51
+ let dummyNode
52
+ if (group.isCharacterBox) {
53
+ dummyNode = new mathMLTree.MathNode('mspace', [])
54
+ dummyNode.setAttribute('height', "1em")
55
+ } else {
56
+ // Create a phantom node with the same content as the body.
57
+ const inner = mml.buildGroup(group.body, style)
58
+ // The phantom node will be zero-width, so it won't affect horizontal spacing.
59
+ const zeroWidthNode = new mathMLTree.MathNode("mpadded", [inner])
60
+ zeroWidthNode.setAttribute("width", "0.1px") // Don't use 0. WebKit would omit it.
61
+ dummyNode = new mathMLTree.MathNode("mphantom", [zeroWidthNode]) // Hide it.
62
+ }
63
+ const toNode = mml.buildGroup(group.to, style)
64
+ const zeroWidthToNode = new mathMLTree.MathNode("mpadded", [toNode])
65
+ if (!group.isCharacterBox || /[f∫∑]/.test(group.body.body[0].text)) {
66
+ const w = new mathMLTree.MathNode("mspace", [])
67
+ w.setAttribute('width', "0.2em")
68
+ zeroWidthToNode.children.unshift(w)
69
+ }
70
+ zeroWidthToNode.setAttribute("width", "0.1px") // Don't use 0. WebKit would hide it.
71
+ const mover = new mathMLTree.MathNode("mover", [dummyNode, zeroWidthToNode])
72
+ // Fix Firefox positioning.
73
+ const nudgeLeft = new mathMLTree.MathNode('mrow', [], ["ff-nudge-left"])
74
+ return mathMLTree.newDocumentFragment([mml.makeRow([node, mover]), nudgeLeft])
35
75
  }
36
76
  })
@@ -4,8 +4,10 @@ import { assertNodeType } from "../parseNode";
4
4
  import { colorFromSpec, validateColor } from "./color"
5
5
  import * as mml from "../buildMathML";
6
6
 
7
+ const boxTags = ["\\boxed", "\\fcolorbox", "\\colorbox"];
8
+
7
9
  const mathmlBuilder = (group, style) => {
8
- const tag = group.label === "\\boxed" ? "mrow" : "menclose"
10
+ const tag = boxTags.includes(group.label) ? "mrow" : "menclose"
9
11
  const node = new mathMLTree.MathNode(tag, [mml.buildGroup(group.body, style)])
10
12
  switch (group.label) {
11
13
  case "\\overline":
@@ -32,6 +34,7 @@ const mathmlBuilder = (group, style) => {
32
34
  node.setAttribute("notation", "updiagonalstrike downdiagonalstrike")
33
35
  node.classes.push("tml-xcancel")
34
36
  break
37
+ // cancelto is handled in cancelto.js
35
38
  case "\\longdiv":
36
39
  node.setAttribute("notation", "longdiv")
37
40
  node.classes.push("longdiv-top")
@@ -64,13 +67,8 @@ const mathmlBuilder = (group, style) => {
64
67
  break
65
68
  case "\\fcolorbox":
66
69
  case "\\colorbox": {
67
- // <menclose> doesn't have a good notation option for \colorbox.
68
- // So use <mpadded> instead. Set some attributes that come
69
- // included with <menclose>.
70
- //const fboxsep = 3; // 3 pt from LaTeX source2e
71
- //node.setAttribute("height", `+${2 * fboxsep}pt`)
72
- //node.setAttribute("voffset", `${fboxsep}pt`)
73
- node.style.padding = "3pt"
70
+ // Don't use <menclose>. WebKit would show a radical.
71
+ node.style.padding = "0.3em" // 3 pt from LaTeX source2e for a 10pt font
74
72
  if (group.label === "\\fcolorbox") {
75
73
  node.style.border = "0.0667em solid " + String(group.borderColor)
76
74
  }
@@ -12,16 +12,16 @@ const mathmlBuilder = (group, style) => {
12
12
  ]);
13
13
  };
14
14
 
15
- // Horizontal stretchy braces
15
+ // Horizontal stretchy brackets
16
16
  defineFunction({
17
- type: "horizBrace",
18
- names: ["\\overbrace", "\\underbrace"],
17
+ type: "horizBracket",
18
+ names: ["\\overbrace", "\\underbrace", "\\overbracket", "\\underbracket"],
19
19
  props: {
20
20
  numArgs: 1
21
21
  },
22
22
  handler({ parser, funcName }, args) {
23
23
  return {
24
- type: "horizBrace",
24
+ type: "horizBracket",
25
25
  mode: parser.mode,
26
26
  label: funcName,
27
27
  isOver: /^\\over/.test(funcName),
@@ -337,7 +337,8 @@ defineFunction({
337
337
  "\u2a1a"
338
338
  ],
339
339
  props: {
340
- numArgs: 0
340
+ numArgs: 0,
341
+ allowedInArgument: true
341
342
  },
342
343
  handler({ parser, funcName }) {
343
344
  let fName = funcName;
@@ -24,18 +24,18 @@ const largePad = "AJdfΔΛ"
24
24
  defineFunctionBuilders({
25
25
  type: "supsub",
26
26
  mathmlBuilder(group, style) {
27
- // Is the inner group a relevant horizontal brace?
28
- let isBrace = false
27
+ // Is the inner group a relevant horizontal brace or bracket?
28
+ let isBracket = false
29
29
  let isOver
30
30
  let isSup
31
31
  let appendApplyFunction = false
32
32
  let appendSpace = false
33
33
  let needsLeadingSpace = false
34
34
 
35
- if (group.base && group.base.type === "horizBrace") {
35
+ if (group.base && group.base.type === "horizBracket") {
36
36
  isSup = !!group.sup
37
37
  if (isSup === group.base.isOver) {
38
- isBrace = true
38
+ isBracket = true
39
39
  isOver = group.base.isOver
40
40
  }
41
41
  }
@@ -83,7 +83,7 @@ defineFunctionBuilders({
83
83
  }
84
84
 
85
85
  let nodeType;
86
- if (isBrace) {
86
+ if (isBracket) {
87
87
  nodeType = isOver ? "mover" : "munder"
88
88
  } else if (!group.sub) {
89
89
  const base = group.base
package/src/functions.js CHANGED
@@ -10,7 +10,7 @@ import "./functions/accent";
10
10
  import "./functions/accentunder";
11
11
  import "./functions/arrow";
12
12
  import "./functions/bordermatrix"
13
- //import "./functions/cancelto";
13
+ import "./functions/cancelto";
14
14
  import "./environments/cd";
15
15
  import "./functions/char";
16
16
  import "./functions/color";
@@ -23,7 +23,7 @@ import "./functions/envTag";
23
23
  import "./functions/font";
24
24
  import "./functions/genfrac";
25
25
  import "./functions/hbox";
26
- import "./functions/horizBrace";
26
+ import "./functions/horizBracket";
27
27
  import "./functions/html";
28
28
  import "./functions/includegraphics";
29
29
  import "./functions/kern";
@@ -5,7 +5,7 @@
5
5
  * https://mit-license.org/
6
6
  */
7
7
 
8
- export const version = "0.12.01";
8
+ export const version = "0.12.02";
9
9
 
10
10
  export function postProcess(block) {
11
11
  const labelMap = {}
package/src/stretchy.js CHANGED
@@ -48,6 +48,8 @@ const stretchyCodePoint = {
48
48
  xrightarrow: "\u2192",
49
49
  underbrace: "\u23df",
50
50
  overbrace: "\u23de",
51
+ overbracket: "\u23b4",
52
+ underbracket: "\u23b5",
51
53
  overgroup: "\u23e0",
52
54
  overparen: "⏜",
53
55
  undergroup: "\u23e1",
package/src/utils.js CHANGED
@@ -115,3 +115,6 @@ export const protocolFromUrl = function(url) {
115
115
  export const round = function(n) {
116
116
  return +n.toFixed(4);
117
117
  };
118
+
119
+ // Identify short letters. Used for accents and \cancelto.
120
+ export const smalls = "acegıȷmnopqrsuvwxyzαγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳"