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/README.md +1 -1
- package/dist/Temml-Asana.css +28 -0
- package/dist/Temml-Latin-Modern.css +29 -1
- package/dist/Temml-Libertinus.css +28 -0
- package/dist/Temml-Local.css +28 -0
- package/dist/Temml-NotoSans.css +28 -0
- package/dist/Temml-STIX2.css +28 -0
- package/dist/temml.cjs +100 -26
- package/dist/temml.js +100 -26
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +100 -26
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +1 -1
- package/src/canceltoArrow.svg +15 -0
- package/src/environments/array.js +5 -4
- package/src/functions/accent.js +1 -2
- package/src/functions/cancelto.js +55 -15
- package/src/functions/enclose.js +6 -8
- package/src/functions/{horizBrace.js → horizBracket.js} +4 -4
- package/src/functions/op.js +2 -1
- package/src/functions/supsub.js +5 -5
- package/src/functions.js +2 -2
- package/src/postProcess.js +1 -1
- package/src/stretchy.js +2 -0
- package/src/utils.js +3 -0
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 (
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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
|
|
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
|
-
//
|
|
8182
|
-
//
|
|
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
|
|
9029
|
+
// Horizontal stretchy brackets
|
|
8957
9030
|
defineFunction({
|
|
8958
|
-
type: "
|
|
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: "
|
|
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
|
|
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 === "
|
|
10943
|
+
if (group.base && group.base.type === "horizBracket") {
|
|
10870
10944
|
isSup = !!group.sup;
|
|
10871
10945
|
if (isSup === group.base.isOver) {
|
|
10872
|
-
|
|
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 (
|
|
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.
|
|
14064
|
+
const version = "0.12.02";
|
|
13991
14065
|
|
|
13992
14066
|
function postProcess(block) {
|
|
13993
14067
|
const labelMap = {};
|
package/dist/temmlPostProcess.js
CHANGED
package/package.json
CHANGED
|
@@ -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 (
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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];
|
package/src/functions/accent.js
CHANGED
|
@@ -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
|
-
|
|
16
|
-
|
|
18
|
+
body,
|
|
19
|
+
to,
|
|
20
|
+
isCharacterBox: isCharacterBox(body)
|
|
17
21
|
};
|
|
18
22
|
},
|
|
19
23
|
mathmlBuilder(group, style) {
|
|
20
|
-
const
|
|
21
|
-
"
|
|
22
|
-
[mml.buildGroup(group.
|
|
24
|
+
const fromNode = new mathMLTree.MathNode(
|
|
25
|
+
"mrow",
|
|
26
|
+
[mml.buildGroup(group.body, style)],
|
|
27
|
+
["ff-narrow"] // A zero-width mrow.
|
|
23
28
|
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
})
|
package/src/functions/enclose.js
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
68
|
-
//
|
|
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
|
|
15
|
+
// Horizontal stretchy brackets
|
|
16
16
|
defineFunction({
|
|
17
|
-
type: "
|
|
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: "
|
|
24
|
+
type: "horizBracket",
|
|
25
25
|
mode: parser.mode,
|
|
26
26
|
label: funcName,
|
|
27
27
|
isOver: /^\\over/.test(funcName),
|
package/src/functions/op.js
CHANGED
package/src/functions/supsub.js
CHANGED
|
@@ -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
|
|
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 === "
|
|
35
|
+
if (group.base && group.base.type === "horizBracket") {
|
|
36
36
|
isSup = !!group.sup
|
|
37
37
|
if (isSup === group.base.isOver) {
|
|
38
|
-
|
|
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 (
|
|
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
|
-
|
|
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/
|
|
26
|
+
import "./functions/horizBracket";
|
|
27
27
|
import "./functions/html";
|
|
28
28
|
import "./functions/includegraphics";
|
|
29
29
|
import "./functions/kern";
|
package/src/postProcess.js
CHANGED
package/src/stretchy.js
CHANGED
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αγεηικμνοπρςστυχωϕ𝐚𝐜𝐞𝐠𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐮𝐯𝐰𝐱𝐲𝐳"
|