temml 0.10.32 → 0.10.34
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 +16 -1
- package/dist/Temml-Fira.css +16 -1
- package/dist/Temml-Latin-Modern.css +16 -1
- package/dist/Temml-Libertinus.css +16 -1
- package/dist/Temml-Local.css +16 -1
- package/dist/Temml-STIX2.css +16 -1
- package/dist/temml.cjs +473 -283
- package/dist/temml.js +473 -283
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +473 -283
- package/dist/temmlPostProcess.js +39 -25
- package/package.json +1 -1
- package/src/Style.js +5 -3
- package/src/buildMathML.js +104 -62
- package/src/domTree.js +34 -0
- package/src/environments/array.js +119 -82
- package/src/environments/cd.js +17 -10
- package/src/functions/arrow.js +11 -3
- package/src/functions/def.js +7 -4
- package/src/functions/delimsizing.js +1 -0
- package/src/functions/font.js +1 -0
- package/src/functions/genfrac.js +13 -4
- package/src/functions/href.js +4 -6
- package/src/functions/label.js +1 -1
- package/src/functions/op.js +0 -7
- package/src/functions/ref.js +3 -5
- package/src/functions/rule.js +2 -0
- package/src/functions/supsub.js +12 -3
- package/src/functions/vcenter.js +30 -0
- package/src/functions.js +1 -0
- package/src/macros.js +4 -2
- package/src/mathMLTree.js +5 -0
- package/src/postProcess.js +39 -25
- package/src/symbols.js +3 -3
- package/src/variant.js +2 -0
package/dist/temml.js
CHANGED
@@ -502,6 +502,40 @@ var temml = (function () {
|
|
502
502
|
}
|
503
503
|
};
|
504
504
|
|
505
|
+
// Create an <a href="…"> node.
|
506
|
+
class AnchorNode {
|
507
|
+
constructor(href, classes, children) {
|
508
|
+
this.href = href;
|
509
|
+
this.classes = classes;
|
510
|
+
this.children = children || [];
|
511
|
+
}
|
512
|
+
|
513
|
+
toNode() {
|
514
|
+
const node = document.createElement("a");
|
515
|
+
node.setAttribute("href", this.href);
|
516
|
+
if (this.classes.length > 0) {
|
517
|
+
node.className = createClass(this.classes);
|
518
|
+
}
|
519
|
+
for (let i = 0; i < this.children.length; i++) {
|
520
|
+
node.appendChild(this.children[i].toNode());
|
521
|
+
}
|
522
|
+
return node
|
523
|
+
}
|
524
|
+
|
525
|
+
toMarkup() {
|
526
|
+
let markup = `<a href='${utils.escape(this.href)}'`;
|
527
|
+
if (this.classes.length > 0) {
|
528
|
+
markup += ` class="${utils.escape(createClass(this.classes))}"`;
|
529
|
+
}
|
530
|
+
markup += ">";
|
531
|
+
for (let i = 0; i < this.children.length; i++) {
|
532
|
+
markup += this.children[i].toMarkup();
|
533
|
+
}
|
534
|
+
markup += "</a>";
|
535
|
+
return markup
|
536
|
+
}
|
537
|
+
}
|
538
|
+
|
505
539
|
/*
|
506
540
|
* This node represents an image embed (<img>) element.
|
507
541
|
*/
|
@@ -576,6 +610,7 @@ var temml = (function () {
|
|
576
610
|
this.children = children || [];
|
577
611
|
this.classes = classes || [];
|
578
612
|
this.style = style || {}; // Used for <mstyle> elements
|
613
|
+
this.label = "";
|
579
614
|
}
|
580
615
|
|
581
616
|
/**
|
@@ -593,6 +628,10 @@ var temml = (function () {
|
|
593
628
|
return this.attributes[name];
|
594
629
|
}
|
595
630
|
|
631
|
+
setLabel(value) {
|
632
|
+
this.label = value;
|
633
|
+
}
|
634
|
+
|
596
635
|
/**
|
597
636
|
* Converts the math node into a MathML-namespaced DOM element.
|
598
637
|
*/
|
@@ -1509,7 +1548,7 @@ var temml = (function () {
|
|
1509
1548
|
defineSymbol(math, mathord, "\u2aeb", "\\Bot");
|
1510
1549
|
defineSymbol(math, bin, "\u2217", "\u2217", true);
|
1511
1550
|
defineSymbol(math, bin, "+", "+");
|
1512
|
-
defineSymbol(math, bin, "
|
1551
|
+
defineSymbol(math, bin, "\u2217", "*");
|
1513
1552
|
defineSymbol(math, bin, "\u2044", "/", true);
|
1514
1553
|
defineSymbol(math, bin, "\u2044", "\u2044");
|
1515
1554
|
defineSymbol(math, bin, "\u2212", "-", true);
|
@@ -1531,7 +1570,7 @@ var temml = (function () {
|
|
1531
1570
|
defineSymbol(math, open, "\u27ea", "\\lAngle", true);
|
1532
1571
|
defineSymbol(math, open, "\u2989", "\\llangle", true);
|
1533
1572
|
defineSymbol(math, open, "|", "\\lvert");
|
1534
|
-
defineSymbol(math, open, "\u2016", "\\lVert");
|
1573
|
+
defineSymbol(math, open, "\u2016", "\\lVert", true);
|
1535
1574
|
defineSymbol(math, textord, "!", "\\oc"); // cmll package
|
1536
1575
|
defineSymbol(math, textord, "?", "\\wn");
|
1537
1576
|
defineSymbol(math, textord, "\u2193", "\\shpos");
|
@@ -1695,7 +1734,7 @@ var temml = (function () {
|
|
1695
1734
|
defineSymbol(math, inner, "\u22ef", "\\@cdots", true);
|
1696
1735
|
defineSymbol(math, inner, "\u22f1", "\\ddots", true);
|
1697
1736
|
defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
|
1698
|
-
defineSymbol(text, textord, "\u22ee", "\\
|
1737
|
+
defineSymbol(text, textord, "\u22ee", "\\varvdots");
|
1699
1738
|
defineSymbol(math, accent, "\u02ca", "\\acute");
|
1700
1739
|
defineSymbol(math, accent, "\u0060", "\\grave");
|
1701
1740
|
defineSymbol(math, accent, "\u00a8", "\\ddot");
|
@@ -2148,61 +2187,6 @@ var temml = (function () {
|
|
2148
2187
|
}
|
2149
2188
|
};
|
2150
2189
|
|
2151
|
-
const numberRegEx$1 = /^[0-9]$/;
|
2152
|
-
const isDotOrComma = (node, followingNode) => {
|
2153
|
-
return ((node.type === "textord" && node.text === ".") ||
|
2154
|
-
(node.type === "atom" && node.text === ",")) &&
|
2155
|
-
// Don't consolidate if there is a space after the comma.
|
2156
|
-
node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
|
2157
|
-
};
|
2158
|
-
const consolidateNumbers = expression => {
|
2159
|
-
// Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
|
2160
|
-
// not <mn>1</mn><mo>,</mo><mn>5</mn><mn>0</mn><mn>6</mn><mi>.</mi><mn>3</mn>
|
2161
|
-
if (expression.length < 2) { return }
|
2162
|
-
const nums = [];
|
2163
|
-
let inNum = false;
|
2164
|
-
// Find adjacent numerals
|
2165
|
-
for (let i = 0; i < expression.length; i++) {
|
2166
|
-
const node = expression[i];
|
2167
|
-
if (node.type === "textord" && numberRegEx$1.test(node.text)) {
|
2168
|
-
if (!inNum) { nums.push({ start: i }); }
|
2169
|
-
inNum = true;
|
2170
|
-
} else {
|
2171
|
-
if (inNum) { nums[nums.length - 1].end = i - 1; }
|
2172
|
-
inNum = false;
|
2173
|
-
}
|
2174
|
-
}
|
2175
|
-
if (inNum) { nums[nums.length - 1].end = expression.length - 1; }
|
2176
|
-
|
2177
|
-
// Determine if numeral groups are separated by a comma or dot.
|
2178
|
-
for (let i = nums.length - 1; i > 0; i--) {
|
2179
|
-
if (nums[i - 1].end === nums[i].start - 2 &&
|
2180
|
-
isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
|
2181
|
-
// Merge the two groups.
|
2182
|
-
nums[i - 1].end = nums[i].end;
|
2183
|
-
nums.splice(i, 1);
|
2184
|
-
}
|
2185
|
-
}
|
2186
|
-
|
2187
|
-
// Consolidate the number nodes
|
2188
|
-
for (let i = nums.length - 1; i >= 0; i--) {
|
2189
|
-
for (let j = nums[i].start + 1; j <= nums[i].end; j++) {
|
2190
|
-
expression[nums[i].start].text += expression[j].text;
|
2191
|
-
}
|
2192
|
-
expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
|
2193
|
-
// Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
|
2194
|
-
// If so, merge the first <mn> into the base.
|
2195
|
-
if (expression.length > nums[i].start + 1) {
|
2196
|
-
const nextTerm = expression[nums[i].start + 1];
|
2197
|
-
if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
|
2198
|
-
numberRegEx$1.test(nextTerm.base.text)) {
|
2199
|
-
nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
|
2200
|
-
expression.splice(nums[i].start, 1);
|
2201
|
-
}
|
2202
|
-
}
|
2203
|
-
}
|
2204
|
-
};
|
2205
|
-
|
2206
2190
|
/**
|
2207
2191
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
2208
2192
|
* unless the array has length 1. Always returns a single node.
|
@@ -2225,6 +2209,39 @@ var temml = (function () {
|
|
2225
2209
|
return new mathMLTree.MathNode("mrow", body);
|
2226
2210
|
};
|
2227
2211
|
|
2212
|
+
/**
|
2213
|
+
* Check for <mi>.</mi> which is how a dot renders in MathML,
|
2214
|
+
* or <mo separator="true" lspace="0em" rspace="0em">,</mo>
|
2215
|
+
* which is how a braced comma {,} renders in MathML
|
2216
|
+
*/
|
2217
|
+
function isNumberPunctuation(group) {
|
2218
|
+
if (!group) {
|
2219
|
+
return false
|
2220
|
+
}
|
2221
|
+
if (group.type === 'mi' && group.children.length === 1) {
|
2222
|
+
const child = group.children[0];
|
2223
|
+
return child instanceof TextNode && child.text === '.'
|
2224
|
+
} else if (group.type === "mtext" && group.children.length === 1) {
|
2225
|
+
const child = group.children[0];
|
2226
|
+
return child instanceof TextNode && child.text === '\u2008' // punctuation space
|
2227
|
+
} else if (group.type === 'mo' && group.children.length === 1 &&
|
2228
|
+
group.getAttribute('separator') === 'true' &&
|
2229
|
+
group.getAttribute('lspace') === '0em' &&
|
2230
|
+
group.getAttribute('rspace') === '0em') {
|
2231
|
+
const child = group.children[0];
|
2232
|
+
return child instanceof TextNode && child.text === ','
|
2233
|
+
} else {
|
2234
|
+
return false
|
2235
|
+
}
|
2236
|
+
}
|
2237
|
+
const isComma = (expression, i) => {
|
2238
|
+
const node = expression[i];
|
2239
|
+
const followingNode = expression[i + 1];
|
2240
|
+
return (node.type === "atom" && node.text === ",") &&
|
2241
|
+
// Don't consolidate if there is a space after the comma.
|
2242
|
+
node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
|
2243
|
+
};
|
2244
|
+
|
2228
2245
|
const isRel = item => {
|
2229
2246
|
return (item.type === "atom" && item.family === "rel") ||
|
2230
2247
|
(item.type === "mclass" && item.mclass === "mrel")
|
@@ -2248,11 +2265,16 @@ var temml = (function () {
|
|
2248
2265
|
return [group];
|
2249
2266
|
}
|
2250
2267
|
|
2251
|
-
consolidateNumbers(expression);
|
2252
|
-
|
2253
2268
|
const groups = [];
|
2269
|
+
const groupArray = [];
|
2270
|
+
let lastGroup;
|
2254
2271
|
for (let i = 0; i < expression.length; i++) {
|
2255
|
-
|
2272
|
+
groupArray.push(buildGroup$1(expression[i], style));
|
2273
|
+
}
|
2274
|
+
|
2275
|
+
for (let i = 0; i < groupArray.length; i++) {
|
2276
|
+
const group = groupArray[i];
|
2277
|
+
|
2256
2278
|
// Suppress spacing between adjacent relations
|
2257
2279
|
if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) {
|
2258
2280
|
group.setAttribute("rspace", "0em");
|
@@ -2260,9 +2282,39 @@ var temml = (function () {
|
|
2260
2282
|
if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) {
|
2261
2283
|
group.setAttribute("lspace", "0em");
|
2262
2284
|
}
|
2285
|
+
|
2286
|
+
// Concatenate numbers
|
2287
|
+
if (group.type === 'mn' && lastGroup && lastGroup.type === 'mn') {
|
2288
|
+
// Concatenate <mn>...</mn> followed by <mi>.</mi>
|
2289
|
+
lastGroup.children.push(...group.children);
|
2290
|
+
continue
|
2291
|
+
} else if (isNumberPunctuation(group) && lastGroup && lastGroup.type === 'mn') {
|
2292
|
+
// Concatenate <mn>...</mn> followed by <mi>.</mi>
|
2293
|
+
lastGroup.children.push(...group.children);
|
2294
|
+
continue
|
2295
|
+
} else if (lastGroup && lastGroup.type === "mn" && i < groupArray.length - 1 &&
|
2296
|
+
groupArray[i + 1].type === "mn" && isComma(expression, i)) {
|
2297
|
+
lastGroup.children.push(...group.children);
|
2298
|
+
continue
|
2299
|
+
} else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) {
|
2300
|
+
// Concatenate <mi>.</mi> followed by <mn>...</mn>
|
2301
|
+
group.children = [...lastGroup.children, ...group.children];
|
2302
|
+
groups.pop();
|
2303
|
+
} else if ((group.type === 'msup' || group.type === 'msub') &&
|
2304
|
+
group.children.length >= 1 && lastGroup &&
|
2305
|
+
(lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) {
|
2306
|
+
// Put preceding <mn>...</mn> or <mi>.</mi> inside base of
|
2307
|
+
// <msup><mn>...base...</mn>...exponent...</msup> (or <msub>)
|
2308
|
+
const base = group.children[0];
|
2309
|
+
if (base instanceof MathNode && base.type === 'mn' && lastGroup) {
|
2310
|
+
base.children = [...lastGroup.children, ...base.children];
|
2311
|
+
groups.pop();
|
2312
|
+
}
|
2313
|
+
}
|
2263
2314
|
groups.push(group);
|
2315
|
+
lastGroup = group;
|
2264
2316
|
}
|
2265
|
-
return groups
|
2317
|
+
return groups
|
2266
2318
|
};
|
2267
2319
|
|
2268
2320
|
/**
|
@@ -2295,16 +2347,36 @@ var temml = (function () {
|
|
2295
2347
|
return new mathMLTree.MathNode("mtd", [], [], { padding: "0", width: "50%" })
|
2296
2348
|
};
|
2297
2349
|
|
2350
|
+
const labelContainers = ["mrow", "mtd", "mtable", "mtr"];
|
2351
|
+
const getLabel = parent => {
|
2352
|
+
for (const node of parent.children) {
|
2353
|
+
if (node.type && labelContainers.includes(node.type)) {
|
2354
|
+
if (node.classes && node.classes[0] === "tml-label") {
|
2355
|
+
const label = node.label;
|
2356
|
+
return label
|
2357
|
+
} else {
|
2358
|
+
const label = getLabel(node);
|
2359
|
+
if (label) { return label }
|
2360
|
+
}
|
2361
|
+
} else if (!node.type) {
|
2362
|
+
const label = getLabel(node);
|
2363
|
+
if (label) { return label }
|
2364
|
+
}
|
2365
|
+
}
|
2366
|
+
};
|
2367
|
+
|
2298
2368
|
const taggedExpression = (expression, tag, style, leqno) => {
|
2299
2369
|
tag = buildExpressionRow(tag[0].body, style);
|
2300
2370
|
tag = consolidateText(tag);
|
2301
2371
|
tag.classes.push("tml-tag");
|
2302
2372
|
|
2373
|
+
const label = getLabel(expression); // from a \label{} function.
|
2303
2374
|
expression = new mathMLTree.MathNode("mtd", [expression]);
|
2304
2375
|
const rowArray = [glue$1(), expression, glue$1()];
|
2305
2376
|
rowArray[leqno ? 0 : 2].classes.push(leqno ? "tml-left" : "tml-right");
|
2306
2377
|
rowArray[leqno ? 0 : 2].children.push(tag);
|
2307
2378
|
const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]);
|
2379
|
+
if (label) { mtr.setAttribute("id", label); }
|
2308
2380
|
const table = new mathMLTree.MathNode("mtable", [mtr]);
|
2309
2381
|
table.style.width = "100%";
|
2310
2382
|
table.setAttribute("displaystyle", "true");
|
@@ -2324,6 +2396,11 @@ var temml = (function () {
|
|
2324
2396
|
}
|
2325
2397
|
|
2326
2398
|
const expression = buildExpression(tree, style);
|
2399
|
+
|
2400
|
+
if (expression.length === 1 && expression[0] instanceof AnchorNode) {
|
2401
|
+
return expression[0]
|
2402
|
+
}
|
2403
|
+
|
2327
2404
|
const wrap = (settings.displayMode || settings.annotate) ? "none" : settings.wrap;
|
2328
2405
|
|
2329
2406
|
const n1 = expression.length === 0 ? null : expression[0];
|
@@ -2348,6 +2425,9 @@ var temml = (function () {
|
|
2348
2425
|
if (settings.xml) {
|
2349
2426
|
math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
|
2350
2427
|
}
|
2428
|
+
if (wrapper.style.width) {
|
2429
|
+
math.style.width = "100%";
|
2430
|
+
}
|
2351
2431
|
if (settings.displayMode) {
|
2352
2432
|
math.setAttribute("display", "block");
|
2353
2433
|
math.style.display = "block math"; // necessary in Chromium.
|
@@ -2679,12 +2759,19 @@ var temml = (function () {
|
|
2679
2759
|
return node
|
2680
2760
|
};
|
2681
2761
|
|
2682
|
-
const paddedNode = (group, lspace = 0.3, rspace = 0) => {
|
2762
|
+
const paddedNode = (group, lspace = 0.3, rspace = 0, mustSmash = false) => {
|
2683
2763
|
if (group == null && rspace === 0) { return padding$2(lspace) }
|
2684
2764
|
const row = group ? [group] : [];
|
2685
2765
|
if (lspace !== 0) { row.unshift(padding$2(lspace)); }
|
2686
2766
|
if (rspace > 0) { row.push(padding$2(rspace)); }
|
2687
|
-
|
2767
|
+
if (mustSmash) {
|
2768
|
+
// Used for the bottom arrow in a {CD} environment
|
2769
|
+
const mpadded = new mathMLTree.MathNode("mpadded", row);
|
2770
|
+
mpadded.setAttribute("height", "0");
|
2771
|
+
return mpadded
|
2772
|
+
} else {
|
2773
|
+
return new mathMLTree.MathNode("mrow", row)
|
2774
|
+
}
|
2688
2775
|
};
|
2689
2776
|
|
2690
2777
|
const labelSize = (size, scriptLevel) => Number(size) / emScale(scriptLevel);
|
@@ -2724,7 +2811,8 @@ var temml = (function () {
|
|
2724
2811
|
(body.body.body || body.body.length > 0));
|
2725
2812
|
if (gotUpper) {
|
2726
2813
|
let label = buildGroup$1(body, labelStyle);
|
2727
|
-
|
2814
|
+
const mustSmash = (fName === "\\\\cdrightarrow" || fName === "\\\\cdleftarrow");
|
2815
|
+
label = paddedNode(label, space, space, mustSmash);
|
2728
2816
|
// Since Firefox does not support minsize, stack a invisible node
|
2729
2817
|
// on top of the label. Its width will serve as a min-width.
|
2730
2818
|
// TODO: Refactor this after Firefox supports minsize.
|
@@ -3119,6 +3207,8 @@ var temml = (function () {
|
|
3119
3207
|
type: "array",
|
3120
3208
|
mode: "math",
|
3121
3209
|
body,
|
3210
|
+
tags: null,
|
3211
|
+
labels: new Array(body.length + 1).fill(""),
|
3122
3212
|
envClasses: ["jot", "cd"],
|
3123
3213
|
cols: [],
|
3124
3214
|
hLinesBeforeRow: new Array(body.length + 1).fill([])
|
@@ -3147,18 +3237,23 @@ var temml = (function () {
|
|
3147
3237
|
};
|
3148
3238
|
},
|
3149
3239
|
mathmlBuilder(group, style) {
|
3150
|
-
|
3151
|
-
|
3152
|
-
label.setAttribute("width", "0");
|
3153
|
-
if (group.side === "left") {
|
3154
|
-
label.setAttribute("lspace", "-1width");
|
3240
|
+
if (group.label.body.length === 0) {
|
3241
|
+
return new mathMLTree.MathNode("mrow", style) // empty label
|
3155
3242
|
}
|
3156
|
-
//
|
3157
|
-
|
3158
|
-
|
3159
|
-
|
3243
|
+
// Abuse an <mtable> to create vertically centered content.
|
3244
|
+
const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.label, style)]);
|
3245
|
+
mtd.style.padding = "0";
|
3246
|
+
const mtr = new mathMLTree.MathNode("mtr", [mtd]);
|
3247
|
+
const mtable = new mathMLTree.MathNode("mtable", [mtr]);
|
3248
|
+
const label = new mathMLTree.MathNode("mpadded", [mtable]);
|
3249
|
+
// Set the label width to zero so that the arrow will be centered under the corner cell.
|
3250
|
+
label.setAttribute("width", "0");
|
3160
3251
|
label.setAttribute("displaystyle", "false");
|
3161
3252
|
label.setAttribute("scriptlevel", "1");
|
3253
|
+
if (group.side === "left") {
|
3254
|
+
label.style.display = "flex";
|
3255
|
+
label.style.justifyContent = "flex-end";
|
3256
|
+
}
|
3162
3257
|
return label;
|
3163
3258
|
}
|
3164
3259
|
});
|
@@ -3748,10 +3843,13 @@ var temml = (function () {
|
|
3748
3843
|
// replacement text, enclosed in '{' and '}' and properly nested
|
3749
3844
|
const { tokens } = parser.gullet.consumeArg();
|
3750
3845
|
|
3751
|
-
parser.gullet.macros.
|
3752
|
-
|
3753
|
-
|
3754
|
-
|
3846
|
+
if (!(funcName === "\\providecommand" && parser.gullet.macros.has(name))) {
|
3847
|
+
// Ignore \providecommand
|
3848
|
+
parser.gullet.macros.set(
|
3849
|
+
name,
|
3850
|
+
{ tokens, numArgs }
|
3851
|
+
);
|
3852
|
+
}
|
3755
3853
|
|
3756
3854
|
return { type: "internal", mode: parser.mode };
|
3757
3855
|
|
@@ -3845,6 +3943,7 @@ var temml = (function () {
|
|
3845
3943
|
"\\vert",
|
3846
3944
|
"\\|",
|
3847
3945
|
"\\Vert",
|
3946
|
+
"\u2016",
|
3848
3947
|
"\\uparrow",
|
3849
3948
|
"\\Uparrow",
|
3850
3949
|
"\\downarrow",
|
@@ -4350,6 +4449,75 @@ var temml = (function () {
|
|
4350
4449
|
}
|
4351
4450
|
}
|
4352
4451
|
|
4452
|
+
/**
|
4453
|
+
* Lexing or parsing positional information for error reporting.
|
4454
|
+
* This object is immutable.
|
4455
|
+
*/
|
4456
|
+
class SourceLocation {
|
4457
|
+
constructor(lexer, start, end) {
|
4458
|
+
this.lexer = lexer; // Lexer holding the input string.
|
4459
|
+
this.start = start; // Start offset, zero-based inclusive.
|
4460
|
+
this.end = end; // End offset, zero-based exclusive.
|
4461
|
+
}
|
4462
|
+
|
4463
|
+
/**
|
4464
|
+
* Merges two `SourceLocation`s from location providers, given they are
|
4465
|
+
* provided in order of appearance.
|
4466
|
+
* - Returns the first one's location if only the first is provided.
|
4467
|
+
* - Returns a merged range of the first and the last if both are provided
|
4468
|
+
* and their lexers match.
|
4469
|
+
* - Otherwise, returns null.
|
4470
|
+
*/
|
4471
|
+
static range(first, second) {
|
4472
|
+
if (!second) {
|
4473
|
+
return first && first.loc;
|
4474
|
+
} else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
|
4475
|
+
return null;
|
4476
|
+
} else {
|
4477
|
+
return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
|
4478
|
+
}
|
4479
|
+
}
|
4480
|
+
}
|
4481
|
+
|
4482
|
+
/**
|
4483
|
+
* Interface required to break circular dependency between Token, Lexer, and
|
4484
|
+
* ParseError.
|
4485
|
+
*/
|
4486
|
+
|
4487
|
+
/**
|
4488
|
+
* The resulting token returned from `lex`.
|
4489
|
+
*
|
4490
|
+
* It consists of the token text plus some position information.
|
4491
|
+
* The position information is essentially a range in an input string,
|
4492
|
+
* but instead of referencing the bare input string, we refer to the lexer.
|
4493
|
+
* That way it is possible to attach extra metadata to the input string,
|
4494
|
+
* like for example a file name or similar.
|
4495
|
+
*
|
4496
|
+
* The position information is optional, so it is OK to construct synthetic
|
4497
|
+
* tokens if appropriate. Not providing available position information may
|
4498
|
+
* lead to degraded error reporting, though.
|
4499
|
+
*/
|
4500
|
+
class Token {
|
4501
|
+
constructor(
|
4502
|
+
text, // the text of this token
|
4503
|
+
loc
|
4504
|
+
) {
|
4505
|
+
this.text = text;
|
4506
|
+
this.loc = loc;
|
4507
|
+
}
|
4508
|
+
|
4509
|
+
/**
|
4510
|
+
* Given a pair of tokens (this and endToken), compute a `Token` encompassing
|
4511
|
+
* the whole input range enclosed by these two.
|
4512
|
+
*/
|
4513
|
+
range(
|
4514
|
+
endToken, // last token of the range, inclusive
|
4515
|
+
text // the text of the newly constructed token
|
4516
|
+
) {
|
4517
|
+
return new Token(text, SourceLocation.range(this, endToken));
|
4518
|
+
}
|
4519
|
+
}
|
4520
|
+
|
4353
4521
|
// In TeX, there are actually three sets of dimensions, one for each of
|
4354
4522
|
// textstyle, scriptstyle, and scriptscriptstyle. These are
|
4355
4523
|
// provided in the the arrays below, in that order.
|
@@ -4614,7 +4782,7 @@ var temml = (function () {
|
|
4614
4782
|
// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
|
4615
4783
|
// We'll call \varvdots, which gets a glyph from symbols.js.
|
4616
4784
|
// The zero-width rule gets us an equivalent to the vertical 6pt kern.
|
4617
|
-
defineMacro("\\vdots", "
|
4785
|
+
defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}");
|
4618
4786
|
defineMacro("\u22ee", "\\vdots");
|
4619
4787
|
|
4620
4788
|
// {array} environment gaps
|
@@ -4834,8 +5002,10 @@ var temml = (function () {
|
|
4834
5002
|
if (context.macros.get("\\df@tag")) {
|
4835
5003
|
throw new ParseError("Multiple \\tag");
|
4836
5004
|
}
|
4837
|
-
return "\\
|
5005
|
+
return "\\gdef\\df@tag{\\text{#1}}";
|
4838
5006
|
});
|
5007
|
+
defineMacro("\\notag", "\\nonumber");
|
5008
|
+
defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");
|
4839
5009
|
|
4840
5010
|
// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
|
4841
5011
|
// {\operator@font mod}\penalty900
|
@@ -5125,33 +5295,30 @@ var temml = (function () {
|
|
5125
5295
|
return [arraystretch, arraycolsep]
|
5126
5296
|
};
|
5127
5297
|
|
5128
|
-
const
|
5129
|
-
|
5130
|
-
|
5131
|
-
|
5132
|
-
|
5133
|
-
|
5134
|
-
|
5135
|
-
|
5136
|
-
} else {
|
5137
|
-
// \notag. Return an empty span.
|
5138
|
-
tag = new mathMLTree.MathNode("mtext", [], []);
|
5139
|
-
return tag
|
5140
|
-
}
|
5141
|
-
} else if (group.envClasses.includes("multline") &&
|
5142
|
-
((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) {
|
5143
|
-
// A multiline that does not receive a tag. Return an empty cell.
|
5144
|
-
tag = new mathMLTree.MathNode("mtext", [], []);
|
5145
|
-
return tag
|
5146
|
-
} else {
|
5147
|
-
// AMS automatcally numbered equaton.
|
5148
|
-
// Insert a class so the element can be populated by a CSS counter.
|
5149
|
-
// WebKit will display the CSS counter only inside a span.
|
5150
|
-
tag = new mathMLTree.MathNode("mtext", [new Span(["tml-eqn"])]);
|
5298
|
+
const checkCellForLabels = cell => {
|
5299
|
+
// Check if the author wrote a \tag{} inside this cell.
|
5300
|
+
let rowLabel = "";
|
5301
|
+
for (let i = 0; i < cell.length; i++) {
|
5302
|
+
if (cell[i].type === "label") {
|
5303
|
+
if (rowLabel) { throw new ParseError(("Multiple \\labels in one row")) }
|
5304
|
+
rowLabel = cell[i].string;
|
5305
|
+
}
|
5151
5306
|
}
|
5152
|
-
return
|
5307
|
+
return rowLabel
|
5153
5308
|
};
|
5154
5309
|
|
5310
|
+
// autoTag (an argument to parseArray) can be one of three values:
|
5311
|
+
// * undefined: Regular (not-top-level) array; no tags on each row
|
5312
|
+
// * true: Automatic equation numbering, overridable by \tag
|
5313
|
+
// * false: Tags allowed on each row, but no automatic numbering
|
5314
|
+
// This function *doesn't* work with the "split" environment name.
|
5315
|
+
function getAutoTag(name) {
|
5316
|
+
if (name.indexOf("ed") === -1) {
|
5317
|
+
return name.indexOf("*") === -1;
|
5318
|
+
}
|
5319
|
+
// return undefined;
|
5320
|
+
}
|
5321
|
+
|
5155
5322
|
/**
|
5156
5323
|
* Parse the body of the environment, with rows delimited by \\ and
|
5157
5324
|
* columns delimited by &, and create a nested list in row-major order
|
@@ -5163,7 +5330,7 @@ var temml = (function () {
|
|
5163
5330
|
{
|
5164
5331
|
cols, // [{ type: string , align: l|c|r|null }]
|
5165
5332
|
envClasses, // align(ed|at|edat) | array | cases | cd | small | multline
|
5166
|
-
|
5333
|
+
autoTag, // boolean
|
5167
5334
|
singleRow, // boolean
|
5168
5335
|
emptySingleRow, // boolean
|
5169
5336
|
maxNumCols, // number
|
@@ -5179,13 +5346,6 @@ var temml = (function () {
|
|
5179
5346
|
// TODO: provide helpful error when \cr is used outside array environment
|
5180
5347
|
parser.gullet.macros.set("\\cr", "\\\\\\relax");
|
5181
5348
|
}
|
5182
|
-
if (addEqnNum) {
|
5183
|
-
parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren");
|
5184
|
-
parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
|
5185
|
-
parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}");
|
5186
|
-
parser.gullet.macros.set("\\notag", "\\env@notag");
|
5187
|
-
parser.gullet.macros.set("\\nonumber", "\\env@notag");
|
5188
|
-
}
|
5189
5349
|
|
5190
5350
|
// Start group for first cell
|
5191
5351
|
parser.gullet.beginGroup();
|
@@ -5193,29 +5353,39 @@ var temml = (function () {
|
|
5193
5353
|
let row = [];
|
5194
5354
|
const body = [row];
|
5195
5355
|
const rowGaps = [];
|
5196
|
-
const
|
5197
|
-
|
5356
|
+
const labels = [];
|
5357
|
+
|
5198
5358
|
const hLinesBeforeRow = [];
|
5199
5359
|
|
5360
|
+
const tags = (autoTag != null ? [] : undefined);
|
5361
|
+
|
5362
|
+
// amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent
|
5363
|
+
// whether this row should have an equation number. Simulate this with
|
5364
|
+
// a \@eqnsw macro set to 1 or 0.
|
5365
|
+
function beginRow() {
|
5366
|
+
if (autoTag) {
|
5367
|
+
parser.gullet.macros.set("\\@eqnsw", "1", true);
|
5368
|
+
}
|
5369
|
+
}
|
5370
|
+
function endRow() {
|
5371
|
+
if (tags) {
|
5372
|
+
if (parser.gullet.macros.get("\\df@tag")) {
|
5373
|
+
tags.push(parser.subparse([new Token("\\df@tag")]));
|
5374
|
+
parser.gullet.macros.set("\\df@tag", undefined, true);
|
5375
|
+
} else {
|
5376
|
+
tags.push(Boolean(autoTag) &&
|
5377
|
+
parser.gullet.macros.get("\\@eqnsw") === "1");
|
5378
|
+
}
|
5379
|
+
}
|
5380
|
+
}
|
5381
|
+
beginRow();
|
5382
|
+
|
5200
5383
|
// Test for \hline at the top of the array.
|
5201
5384
|
hLinesBeforeRow.push(getHLines(parser));
|
5202
5385
|
|
5203
5386
|
while (true) {
|
5204
5387
|
// Parse each cell in its own group (namespace)
|
5205
5388
|
let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
|
5206
|
-
|
5207
|
-
if (addEqnNum && !rowTag) {
|
5208
|
-
// Check if the author wrote a \tag{} inside this cell.
|
5209
|
-
for (let i = 0; i < cell.length; i++) {
|
5210
|
-
if (cell[i].type === "envTag" || cell[i].type === "noTag") {
|
5211
|
-
// Get the contents of the \text{} nested inside the \env@Tag{}
|
5212
|
-
rowTag = cell[i].type === "envTag"
|
5213
|
-
? cell.splice(i, 1)[0].body.body[0]
|
5214
|
-
: { body: null };
|
5215
|
-
break
|
5216
|
-
}
|
5217
|
-
}
|
5218
|
-
}
|
5219
5389
|
parser.gullet.endGroup();
|
5220
5390
|
parser.gullet.beginGroup();
|
5221
5391
|
|
@@ -5244,6 +5414,7 @@ var temml = (function () {
|
|
5244
5414
|
}
|
5245
5415
|
parser.consume();
|
5246
5416
|
} else if (next === "\\end") {
|
5417
|
+
endRow();
|
5247
5418
|
// Arrays terminate newlines with `\crcr` which consumes a `\cr` if
|
5248
5419
|
// the last line is empty. However, AMS environments keep the
|
5249
5420
|
// empty row if it's the only one.
|
@@ -5251,6 +5422,7 @@ var temml = (function () {
|
|
5251
5422
|
if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) {
|
5252
5423
|
body.pop();
|
5253
5424
|
}
|
5425
|
+
labels.push(checkCellForLabels(cell.body));
|
5254
5426
|
if (hLinesBeforeRow.length < body.length + 1) {
|
5255
5427
|
hLinesBeforeRow.push([]);
|
5256
5428
|
}
|
@@ -5267,15 +5439,16 @@ var temml = (function () {
|
|
5267
5439
|
size = parser.parseSizeGroup(true);
|
5268
5440
|
}
|
5269
5441
|
rowGaps.push(size ? size.value : null);
|
5442
|
+
endRow();
|
5270
5443
|
|
5271
|
-
|
5444
|
+
labels.push(checkCellForLabels(cell.body));
|
5272
5445
|
|
5273
5446
|
// check for \hline(s) following the row separator
|
5274
5447
|
hLinesBeforeRow.push(getHLines(parser));
|
5275
5448
|
|
5276
5449
|
row = [];
|
5277
|
-
rowTag = null;
|
5278
5450
|
body.push(row);
|
5451
|
+
beginRow();
|
5279
5452
|
} else {
|
5280
5453
|
throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
|
5281
5454
|
}
|
@@ -5286,8 +5459,6 @@ var temml = (function () {
|
|
5286
5459
|
// End array group defining \cr
|
5287
5460
|
parser.gullet.endGroup();
|
5288
5461
|
|
5289
|
-
tags.push(rowTag);
|
5290
|
-
|
5291
5462
|
return {
|
5292
5463
|
type: "array",
|
5293
5464
|
mode: parser.mode,
|
@@ -5296,9 +5467,10 @@ var temml = (function () {
|
|
5296
5467
|
rowGaps,
|
5297
5468
|
hLinesBeforeRow,
|
5298
5469
|
envClasses,
|
5299
|
-
|
5470
|
+
autoTag,
|
5300
5471
|
scriptLevel,
|
5301
5472
|
tags,
|
5473
|
+
labels,
|
5302
5474
|
leqno,
|
5303
5475
|
arraystretch,
|
5304
5476
|
arraycolsep
|
@@ -5355,19 +5527,43 @@ var temml = (function () {
|
|
5355
5527
|
}
|
5356
5528
|
row.push(mtd);
|
5357
5529
|
}
|
5358
|
-
|
5359
|
-
|
5360
|
-
|
5361
|
-
|
5362
|
-
|
5363
|
-
|
5364
|
-
|
5365
|
-
|
5366
|
-
|
5367
|
-
|
5530
|
+
const numColumns = group.body[0].length;
|
5531
|
+
// Fill out a short row with empty <mtd> elements.
|
5532
|
+
for (let k = 0; k < numColumns - rw.length; k++) {
|
5533
|
+
row.push(new mathMLTree.MathNode("mtd", [], style));
|
5534
|
+
}
|
5535
|
+
if (group.autoTag) {
|
5536
|
+
const tag = group.tags[i];
|
5537
|
+
let tagElement;
|
5538
|
+
if (tag === true) { // automatic numbering
|
5539
|
+
tagElement = new mathMLTree.MathNode("mtext", [new Span(["tml-eqn"])]);
|
5540
|
+
} else if (tag === false) {
|
5541
|
+
// \nonumber/\notag or starred environment
|
5542
|
+
tagElement = new mathMLTree.MathNode("mtext", [], []);
|
5543
|
+
} else { // manual \tag
|
5544
|
+
tagElement = buildExpressionRow(tag[0].body, style.withLevel(cellLevel), true);
|
5545
|
+
tagElement = consolidateText(tagElement);
|
5546
|
+
tagElement.classes = ["tml-tag"];
|
5547
|
+
}
|
5548
|
+
if (tagElement) {
|
5549
|
+
row.unshift(glue(group));
|
5550
|
+
row.push(glue(group));
|
5551
|
+
if (group.leqno) {
|
5552
|
+
row[0].children.push(tagElement);
|
5553
|
+
row[0].classes.push("tml-left");
|
5554
|
+
} else {
|
5555
|
+
row[row.length - 1].children.push(tagElement);
|
5556
|
+
row[row.length - 1].classes.push("tml-right");
|
5557
|
+
}
|
5368
5558
|
}
|
5369
5559
|
}
|
5370
5560
|
const mtr = new mathMLTree.MathNode("mtr", row, []);
|
5561
|
+
const label = group.labels.shift();
|
5562
|
+
if (label && group.tags && group.tags[i]) {
|
5563
|
+
mtr.setAttribute("id", label);
|
5564
|
+
if (Array.isArray(group.tags[i])) { mtr.classes.push("tml-tageqn"); }
|
5565
|
+
}
|
5566
|
+
|
5371
5567
|
// Write horizontal rules
|
5372
5568
|
if (i === 0 && hlines[0].length > 0) {
|
5373
5569
|
if (hlines[0].length === 2) {
|
@@ -5391,16 +5587,17 @@ var temml = (function () {
|
|
5391
5587
|
}
|
5392
5588
|
|
5393
5589
|
if (group.envClasses.length > 0) {
|
5394
|
-
let pad = group.envClasses.includes("jot")
|
5395
|
-
? "0.7" // 0.5ex + 0.09em top & bot padding
|
5396
|
-
: group.envClasses.includes("small")
|
5397
|
-
? "0.35"
|
5398
|
-
: "0.5"; // 0.5ex default top & bot padding
|
5399
5590
|
if (group.arraystretch && group.arraystretch !== 1) {
|
5400
5591
|
// In LaTeX, \arraystretch is a factor applied to a 12pt strut height.
|
5401
5592
|
// It defines a baseline to baseline distance.
|
5402
5593
|
// Here, we do an approximation of that approach.
|
5403
|
-
pad = String(1.4 * group.arraystretch - 0.8);
|
5594
|
+
const pad = String(1.4 * group.arraystretch - 0.8) + "ex";
|
5595
|
+
for (let i = 0; i < tbl.length; i++) {
|
5596
|
+
for (let j = 0; j < tbl[i].children.length; j++) {
|
5597
|
+
tbl[i].children[j].style.paddingTop = pad;
|
5598
|
+
tbl[i].children[j].style.paddingBottom = pad;
|
5599
|
+
}
|
5600
|
+
}
|
5404
5601
|
}
|
5405
5602
|
let sidePadding = group.envClasses.includes("abut")
|
5406
5603
|
? "0"
|
@@ -5414,7 +5611,7 @@ var temml = (function () {
|
|
5414
5611
|
let sidePadUnit = "em";
|
5415
5612
|
if (group.arraycolsep) {
|
5416
5613
|
const arraySidePad = calculateSize(group.arraycolsep, style);
|
5417
|
-
sidePadding = arraySidePad.number;
|
5614
|
+
sidePadding = arraySidePad.number.toFixed(4);
|
5418
5615
|
sidePadUnit = arraySidePad.unit;
|
5419
5616
|
}
|
5420
5617
|
|
@@ -5425,18 +5622,18 @@ var temml = (function () {
|
|
5425
5622
|
if (j === numCols - 1 && hand === 1) { return "0" }
|
5426
5623
|
if (group.envClasses[0] !== "align") { return sidePadding }
|
5427
5624
|
if (hand === 1) { return "0" }
|
5428
|
-
if (group.
|
5625
|
+
if (group.autoTag) {
|
5429
5626
|
return (j % 2) ? "1" : "0"
|
5430
5627
|
} else {
|
5431
5628
|
return (j % 2) ? "0" : "1"
|
5432
5629
|
}
|
5433
5630
|
};
|
5434
5631
|
|
5435
|
-
//
|
5632
|
+
// Side padding
|
5436
5633
|
for (let i = 0; i < tbl.length; i++) {
|
5437
5634
|
for (let j = 0; j < tbl[i].children.length; j++) {
|
5438
|
-
tbl[i].children[j].style.
|
5439
|
-
|
5635
|
+
tbl[i].children[j].style.paddingLeft = `${sidePad(j, 0)}${sidePadUnit}`;
|
5636
|
+
tbl[i].children[j].style.paddingRight = `${sidePad(j, 1)}${sidePadUnit}`;
|
5440
5637
|
}
|
5441
5638
|
}
|
5442
5639
|
|
@@ -5450,13 +5647,13 @@ var temml = (function () {
|
|
5450
5647
|
// TODO: Remove -webkit- when Chromium no longer needs it.
|
5451
5648
|
row.children[j].classes = ["tml-" + (j % 2 ? "left" : "right")];
|
5452
5649
|
}
|
5453
|
-
if (group.
|
5650
|
+
if (group.autoTag) {
|
5454
5651
|
const k = group.leqno ? 0 : row.children.length - 1;
|
5455
5652
|
row.children[k].classes = ["tml-" + (group.leqno ? "left" : "right")];
|
5456
5653
|
}
|
5457
5654
|
}
|
5458
5655
|
if (row.children.length > 1 && group.envClasses.includes("cases")) {
|
5459
|
-
row.children[1].style.
|
5656
|
+
row.children[1].style.paddingLeft = "1em";
|
5460
5657
|
}
|
5461
5658
|
|
5462
5659
|
if (group.envClasses.includes("cases") || group.envClasses.includes("subarray")) {
|
@@ -5476,9 +5673,17 @@ var temml = (function () {
|
|
5476
5673
|
}
|
5477
5674
|
|
5478
5675
|
let table = new mathMLTree.MathNode("mtable", tbl);
|
5676
|
+
if (group.envClasses.length > 0) {
|
5677
|
+
// Top & bottom padding
|
5678
|
+
if (group.envClasses.includes("jot")) {
|
5679
|
+
table.classes.push("tml-jot");
|
5680
|
+
} else if (group.envClasses.includes("small")) {
|
5681
|
+
table.classes.push("tml-small");
|
5682
|
+
}
|
5683
|
+
}
|
5479
5684
|
if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); }
|
5480
5685
|
|
5481
|
-
if (group.
|
5686
|
+
if (group.autoTag || group.envClasses.includes("multline")) {
|
5482
5687
|
table.style.width = "100%";
|
5483
5688
|
}
|
5484
5689
|
|
@@ -5508,7 +5713,7 @@ var temml = (function () {
|
|
5508
5713
|
row.children[0].style.borderLeft = sep;
|
5509
5714
|
}
|
5510
5715
|
}
|
5511
|
-
let iCol = group.
|
5716
|
+
let iCol = group.autoTag ? 0 : -1;
|
5512
5717
|
for (let i = iStart; i < iEnd; i++) {
|
5513
5718
|
if (cols[i].type === "align") {
|
5514
5719
|
const colAlign = alignMap[cols[i].align];
|
@@ -5550,7 +5755,7 @@ var temml = (function () {
|
|
5550
5755
|
}
|
5551
5756
|
}
|
5552
5757
|
}
|
5553
|
-
if (group.
|
5758
|
+
if (group.autoTag) {
|
5554
5759
|
// allow for glue cells on each side
|
5555
5760
|
align = "left " + (align.length > 0 ? align : "center ") + "right ";
|
5556
5761
|
}
|
@@ -5574,13 +5779,14 @@ var temml = (function () {
|
|
5574
5779
|
if (context.envName.indexOf("ed") === -1) {
|
5575
5780
|
validateAmsEnvironmentContext(context);
|
5576
5781
|
}
|
5782
|
+
const isSplit = context.envName === "split";
|
5577
5783
|
const cols = [];
|
5578
5784
|
const res = parseArray(
|
5579
5785
|
context.parser,
|
5580
5786
|
{
|
5581
5787
|
cols,
|
5582
|
-
addEqnNum: context.envName === "align" || context.envName === "alignat",
|
5583
5788
|
emptySingleRow: true,
|
5789
|
+
autoTag: isSplit ? undefined : getAutoTag(context.envName),
|
5584
5790
|
envClasses: ["abut", "jot"], // set row spacing & provisional column spacing
|
5585
5791
|
maxNumCols: context.envName === "split" ? 2 : undefined,
|
5586
5792
|
leqno: context.parser.settings.leqno
|
@@ -5902,7 +6108,7 @@ var temml = (function () {
|
|
5902
6108
|
const res = {
|
5903
6109
|
cols: [],
|
5904
6110
|
envClasses: ["abut", "jot"],
|
5905
|
-
|
6111
|
+
autoTag: getAutoTag(context.envName),
|
5906
6112
|
emptySingleRow: true,
|
5907
6113
|
leqno: context.parser.settings.leqno
|
5908
6114
|
};
|
@@ -5920,7 +6126,7 @@ var temml = (function () {
|
|
5920
6126
|
handler(context) {
|
5921
6127
|
validateAmsEnvironmentContext(context);
|
5922
6128
|
const res = {
|
5923
|
-
|
6129
|
+
autoTag: getAutoTag(context.envName),
|
5924
6130
|
emptySingleRow: true,
|
5925
6131
|
singleRow: true,
|
5926
6132
|
maxNumCols: 1,
|
@@ -5941,7 +6147,7 @@ var temml = (function () {
|
|
5941
6147
|
handler(context) {
|
5942
6148
|
validateAmsEnvironmentContext(context);
|
5943
6149
|
const res = {
|
5944
|
-
|
6150
|
+
autoTag: context.envName === "multline",
|
5945
6151
|
maxNumCols: 1,
|
5946
6152
|
envClasses: ["jot", "multline"],
|
5947
6153
|
leqno: context.parser.settings.leqno
|
@@ -6163,6 +6369,7 @@ var temml = (function () {
|
|
6163
6369
|
"\\mathfrak",
|
6164
6370
|
"\\mathscr",
|
6165
6371
|
"\\mathsf",
|
6372
|
+
"\\mathsfit",
|
6166
6373
|
"\\mathtt",
|
6167
6374
|
|
6168
6375
|
// aliases
|
@@ -6232,10 +6439,19 @@ var temml = (function () {
|
|
6232
6439
|
? style.withLevel(StyleLevel.SCRIPT)
|
6233
6440
|
: style.withLevel(StyleLevel.SCRIPTSCRIPT);
|
6234
6441
|
|
6235
|
-
|
6236
|
-
|
6237
|
-
|
6238
|
-
|
6442
|
+
// Chromium (wrongly) continues to shrink fractions beyond scriptscriptlevel.
|
6443
|
+
// So we check for levels that Chromium shrinks too small.
|
6444
|
+
// If necessary, set an explicit fraction depth.
|
6445
|
+
const numer = buildGroup$1(group.numer, childOptions);
|
6446
|
+
const denom = buildGroup$1(group.denom, childOptions);
|
6447
|
+
if (style.level === 3) {
|
6448
|
+
numer.style.mathDepth = "2";
|
6449
|
+
numer.setAttribute("scriptlevel", "2");
|
6450
|
+
denom.style.mathDepth = "2";
|
6451
|
+
denom.setAttribute("scriptlevel", "2");
|
6452
|
+
}
|
6453
|
+
|
6454
|
+
let node = new mathMLTree.MathNode("mfrac", [numer, denom]);
|
6239
6455
|
|
6240
6456
|
if (!group.hasBarLine) {
|
6241
6457
|
node.setAttribute("linethickness", "0px");
|
@@ -6628,12 +6844,9 @@ var temml = (function () {
|
|
6628
6844
|
};
|
6629
6845
|
},
|
6630
6846
|
mathmlBuilder: (group, style) => {
|
6631
|
-
|
6632
|
-
|
6633
|
-
|
6634
|
-
}
|
6635
|
-
math.setAttribute("href", group.href);
|
6636
|
-
return math;
|
6847
|
+
const math = new MathNode("math", [buildExpressionRow(group.body, style)]);
|
6848
|
+
const anchorNode = new AnchorNode(group.href, [], [math]);
|
6849
|
+
return anchorNode
|
6637
6850
|
}
|
6638
6851
|
});
|
6639
6852
|
|
@@ -6991,7 +7204,7 @@ var temml = (function () {
|
|
6991
7204
|
// Return a no-width, no-ink element with an HTML id.
|
6992
7205
|
const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]);
|
6993
7206
|
if (group.string.length > 0) {
|
6994
|
-
node.
|
7207
|
+
node.setLabel(group.string);
|
6995
7208
|
}
|
6996
7209
|
return node
|
6997
7210
|
}
|
@@ -7505,13 +7718,6 @@ var temml = (function () {
|
|
7505
7718
|
node = new MathNode("mo", [makeText(group.name, group.mode)]);
|
7506
7719
|
if (noSuccessor.includes(group.name)) {
|
7507
7720
|
node.setAttribute("largeop", "false");
|
7508
|
-
} else if (group.limits) {
|
7509
|
-
// This is a workaround for a MathML/Chromium bug.
|
7510
|
-
// This is being applied to singleCharBigOps, which are not really stretchy.
|
7511
|
-
// But by setting the stretchy attribute, Chromium will vertically center
|
7512
|
-
// big ops around the math axis. This is needed since STIX TWO does not do so.
|
7513
|
-
// TODO: Remove this hack when MathML & Chromium fix their problem.
|
7514
|
-
node.setAttribute("stretchy", "true");
|
7515
7721
|
} else {
|
7516
7722
|
node.setAttribute("movablelimits", "false");
|
7517
7723
|
}
|
@@ -8146,12 +8352,10 @@ var temml = (function () {
|
|
8146
8352
|
};
|
8147
8353
|
},
|
8148
8354
|
mathmlBuilder(group, style) {
|
8149
|
-
// Create an empty
|
8355
|
+
// Create an empty <a> node. Set a class and an href attribute.
|
8150
8356
|
// The post-processor will populate with the target's tag or equation number.
|
8151
8357
|
const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"];
|
8152
|
-
|
8153
|
-
node.setAttribute("href", "#" + group.string);
|
8154
|
-
return node
|
8358
|
+
return new AnchorNode("#" + group.string, classes, null)
|
8155
8359
|
}
|
8156
8360
|
});
|
8157
8361
|
|
@@ -8198,6 +8402,8 @@ var temml = (function () {
|
|
8198
8402
|
props: {
|
8199
8403
|
numArgs: 2,
|
8200
8404
|
numOptionalArgs: 1,
|
8405
|
+
allowedInText: true,
|
8406
|
+
allowedInMath: true,
|
8201
8407
|
argTypes: ["size", "size", "size"]
|
8202
8408
|
},
|
8203
8409
|
handler({ parser }, args, optArgs) {
|
@@ -8490,16 +8696,25 @@ var temml = (function () {
|
|
8490
8696
|
? [buildGroup$1(group.base.body[0], style)]
|
8491
8697
|
: [buildGroup$1(group.base, style)];
|
8492
8698
|
|
8699
|
+
// Note regarding scriptstyle level.
|
8700
|
+
// (Sub|super)scripts should not shrink beyond MathML scriptlevel 2 aka \scriptscriptstyle
|
8701
|
+
// Ref: https://w3c.github.io/mathml-core/#the-displaystyle-and-scriptlevel-attributes
|
8702
|
+
// (BTW, MathML scriptlevel 2 is equal to Temml level 3.)
|
8703
|
+
// But Chromium continues to shrink the (sub|super)scripts. So we explicitly set scriptlevel 2.
|
8704
|
+
|
8493
8705
|
const childStyle = style.inSubOrSup();
|
8494
8706
|
if (group.sub) {
|
8495
|
-
|
8707
|
+
const sub = buildGroup$1(group.sub, childStyle);
|
8708
|
+
if (style.level === 3) { sub.setAttribute("scriptlevel", "2"); }
|
8709
|
+
children.push(sub);
|
8496
8710
|
}
|
8497
8711
|
|
8498
8712
|
if (group.sup) {
|
8499
8713
|
const sup = buildGroup$1(group.sup, childStyle);
|
8714
|
+
if (style.level === 3) { sup.setAttribute("scriptlevel", "2"); }
|
8500
8715
|
const testNode = sup.type === "mrow" ? sup.children[0] : sup;
|
8501
8716
|
if ((testNode && testNode.type === "mo" && testNode.classes.includes("tml-prime"))
|
8502
|
-
&& group.base && group.base.text && group.base.text
|
8717
|
+
&& group.base && group.base.text && "fF".indexOf(group.base.text) > -1) {
|
8503
8718
|
// Chromium does not address italic correction on prime. Prevent f′ from overlapping.
|
8504
8719
|
testNode.classes.push("prime-pad");
|
8505
8720
|
}
|
@@ -8726,6 +8941,8 @@ var temml = (function () {
|
|
8726
8941
|
return "script"
|
8727
8942
|
case "mathsf":
|
8728
8943
|
return "sans-serif"
|
8944
|
+
case "mathsfit":
|
8945
|
+
return "sans-serif-italic"
|
8729
8946
|
case "mathtt":
|
8730
8947
|
return "monospace"
|
8731
8948
|
}
|
@@ -9190,6 +9407,32 @@ var temml = (function () {
|
|
9190
9407
|
}
|
9191
9408
|
});
|
9192
9409
|
|
9410
|
+
// \vcenter: Vertically center the argument group on the math axis.
|
9411
|
+
|
9412
|
+
defineFunction({
|
9413
|
+
type: "vcenter",
|
9414
|
+
names: ["\\vcenter"],
|
9415
|
+
props: {
|
9416
|
+
numArgs: 1,
|
9417
|
+
argTypes: ["original"],
|
9418
|
+
allowedInText: false
|
9419
|
+
},
|
9420
|
+
handler({ parser }, args) {
|
9421
|
+
return {
|
9422
|
+
type: "vcenter",
|
9423
|
+
mode: parser.mode,
|
9424
|
+
body: args[0]
|
9425
|
+
};
|
9426
|
+
},
|
9427
|
+
mathmlBuilder(group, style) {
|
9428
|
+
// Use a math table to create vertically centered content.
|
9429
|
+
const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.body, style)]);
|
9430
|
+
mtd.style.padding = "0";
|
9431
|
+
const mtr = new mathMLTree.MathNode("mtr", [mtd]);
|
9432
|
+
return new mathMLTree.MathNode("mtable", [mtr])
|
9433
|
+
}
|
9434
|
+
});
|
9435
|
+
|
9193
9436
|
defineFunction({
|
9194
9437
|
type: "verb",
|
9195
9438
|
names: ["\\verb"],
|
@@ -9224,75 +9467,6 @@ var temml = (function () {
|
|
9224
9467
|
|
9225
9468
|
const functions = _functions;
|
9226
9469
|
|
9227
|
-
/**
|
9228
|
-
* Lexing or parsing positional information for error reporting.
|
9229
|
-
* This object is immutable.
|
9230
|
-
*/
|
9231
|
-
class SourceLocation {
|
9232
|
-
constructor(lexer, start, end) {
|
9233
|
-
this.lexer = lexer; // Lexer holding the input string.
|
9234
|
-
this.start = start; // Start offset, zero-based inclusive.
|
9235
|
-
this.end = end; // End offset, zero-based exclusive.
|
9236
|
-
}
|
9237
|
-
|
9238
|
-
/**
|
9239
|
-
* Merges two `SourceLocation`s from location providers, given they are
|
9240
|
-
* provided in order of appearance.
|
9241
|
-
* - Returns the first one's location if only the first is provided.
|
9242
|
-
* - Returns a merged range of the first and the last if both are provided
|
9243
|
-
* and their lexers match.
|
9244
|
-
* - Otherwise, returns null.
|
9245
|
-
*/
|
9246
|
-
static range(first, second) {
|
9247
|
-
if (!second) {
|
9248
|
-
return first && first.loc;
|
9249
|
-
} else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
|
9250
|
-
return null;
|
9251
|
-
} else {
|
9252
|
-
return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
|
9253
|
-
}
|
9254
|
-
}
|
9255
|
-
}
|
9256
|
-
|
9257
|
-
/**
|
9258
|
-
* Interface required to break circular dependency between Token, Lexer, and
|
9259
|
-
* ParseError.
|
9260
|
-
*/
|
9261
|
-
|
9262
|
-
/**
|
9263
|
-
* The resulting token returned from `lex`.
|
9264
|
-
*
|
9265
|
-
* It consists of the token text plus some position information.
|
9266
|
-
* The position information is essentially a range in an input string,
|
9267
|
-
* but instead of referencing the bare input string, we refer to the lexer.
|
9268
|
-
* That way it is possible to attach extra metadata to the input string,
|
9269
|
-
* like for example a file name or similar.
|
9270
|
-
*
|
9271
|
-
* The position information is optional, so it is OK to construct synthetic
|
9272
|
-
* tokens if appropriate. Not providing available position information may
|
9273
|
-
* lead to degraded error reporting, though.
|
9274
|
-
*/
|
9275
|
-
class Token {
|
9276
|
-
constructor(
|
9277
|
-
text, // the text of this token
|
9278
|
-
loc
|
9279
|
-
) {
|
9280
|
-
this.text = text;
|
9281
|
-
this.loc = loc;
|
9282
|
-
}
|
9283
|
-
|
9284
|
-
/**
|
9285
|
-
* Given a pair of tokens (this and endToken), compute a `Token` encompassing
|
9286
|
-
* the whole input range enclosed by these two.
|
9287
|
-
*/
|
9288
|
-
range(
|
9289
|
-
endToken, // last token of the range, inclusive
|
9290
|
-
text // the text of the newly constructed token
|
9291
|
-
) {
|
9292
|
-
return new Token(text, SourceLocation.range(this, endToken));
|
9293
|
-
}
|
9294
|
-
}
|
9295
|
-
|
9296
9470
|
/**
|
9297
9471
|
* The Lexer class handles tokenizing the input in various ways. Since our
|
9298
9472
|
* parser expects us to be able to backtrack, the lexer allows lexing from any
|
@@ -11456,9 +11630,11 @@ var temml = (function () {
|
|
11456
11630
|
constructor(data) {
|
11457
11631
|
// Style.level can be 0 | 1 | 2 | 3, which correspond to
|
11458
11632
|
// displaystyle, textstyle, scriptstyle, and scriptscriptstyle.
|
11459
|
-
// style.level does not directly set MathML's script level. MathML does that itself.
|
11460
|
-
//
|
11461
|
-
//
|
11633
|
+
// style.level usually does not directly set MathML's script level. MathML does that itself.
|
11634
|
+
// However, Chromium does not stop shrinking after scriptscriptstyle, so we do explicitly
|
11635
|
+
// set a scriptlevel attribute in those conditions.
|
11636
|
+
// We also use style.level to track math style so that we can get the correct
|
11637
|
+
// scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em.
|
11462
11638
|
this.level = data.level;
|
11463
11639
|
this.color = data.color; // string | void
|
11464
11640
|
// A font family applies to a group of fonts (i.e. SansSerif), while a font
|
@@ -11582,42 +11758,51 @@ var temml = (function () {
|
|
11582
11758
|
}
|
11583
11759
|
|
11584
11760
|
/* Temml Post Process
|
11585
|
-
*
|
11586
|
-
* Given a block,
|
11587
|
-
* 1. At each AMS auto-numbered environment, assign an id.
|
11588
|
-
* 2. Populate the text contents of each \ref & \eqref
|
11761
|
+
* Populate the text contents of each \ref & \eqref
|
11589
11762
|
*
|
11590
11763
|
* As with other Temml code, this file is released under terms of the MIT license.
|
11591
11764
|
* https://mit-license.org/
|
11592
11765
|
*/
|
11593
11766
|
|
11594
|
-
const version = "0.10.
|
11767
|
+
const version = "0.10.34";
|
11595
11768
|
|
11596
11769
|
function postProcess(block) {
|
11597
11770
|
const labelMap = {};
|
11598
11771
|
let i = 0;
|
11599
11772
|
|
11600
11773
|
// Get a collection of the parents of each \tag & auto-numbered equation
|
11601
|
-
const
|
11602
|
-
for (
|
11603
|
-
|
11604
|
-
|
11605
|
-
|
11606
|
-
|
11607
|
-
|
11608
|
-
|
11609
|
-
|
11610
|
-
|
11774
|
+
const amsEqns = document.getElementsByClassName('tml-eqn');
|
11775
|
+
for (let parent of amsEqns) {
|
11776
|
+
// AMS automatically numbered equation.
|
11777
|
+
// Assign an id.
|
11778
|
+
i += 1;
|
11779
|
+
parent.setAttribute("id", "tml-eqn-" + String(i));
|
11780
|
+
// No need to write a number into the text content of the element.
|
11781
|
+
// A CSS counter has done that even if this postProcess() function is not used.
|
11782
|
+
|
11783
|
+
// Find any \label that refers to an AMS automatic eqn number.
|
11784
|
+
while (true) {
|
11785
|
+
if (parent.tagName === "mtable") { break }
|
11786
|
+
const labels = parent.getElementsByClassName("tml-label");
|
11787
|
+
if (labels.length > 0) {
|
11788
|
+
const id = parent.attributes.id.value;
|
11789
|
+
labelMap[id] = String(i);
|
11790
|
+
break
|
11791
|
+
} else {
|
11792
|
+
parent = parent.parentElement;
|
11793
|
+
}
|
11611
11794
|
}
|
11612
|
-
|
11795
|
+
}
|
11796
|
+
|
11797
|
+
// Find \labels associated with \tag
|
11798
|
+
const taggedEqns = document.getElementsByClassName('tml-tageqn');
|
11799
|
+
for (const parent of taggedEqns) {
|
11613
11800
|
const labels = parent.getElementsByClassName("tml-label");
|
11614
|
-
if (labels.length
|
11615
|
-
if (eqns.length > 0) {
|
11616
|
-
labelMap[labels[0].id] = String(i);
|
11617
|
-
} else {
|
11801
|
+
if (labels.length > 0) {
|
11618
11802
|
const tags = parent.getElementsByClassName("tml-tag");
|
11619
11803
|
if (tags.length > 0) {
|
11620
|
-
|
11804
|
+
const id = parent.attributes.id.value;
|
11805
|
+
labelMap[id] = tags[0].textContent;
|
11621
11806
|
}
|
11622
11807
|
}
|
11623
11808
|
}
|
@@ -11625,17 +11810,22 @@ var temml = (function () {
|
|
11625
11810
|
// Populate \ref & \eqref text content
|
11626
11811
|
const refs = block.getElementsByClassName("tml-ref");
|
11627
11812
|
[...refs].forEach(ref => {
|
11628
|
-
|
11813
|
+
const attr = ref.getAttribute("href");
|
11814
|
+
let str = labelMap[attr.slice(1)];
|
11629
11815
|
if (ref.className.indexOf("tml-eqref") === -1) {
|
11630
11816
|
// \ref. Omit parens.
|
11631
11817
|
str = str.replace(/^\(/, "");
|
11632
|
-
str = str.replace(/\
|
11633
|
-
}
|
11818
|
+
str = str.replace(/\)$/, "");
|
11819
|
+
} else {
|
11634
11820
|
// \eqref. Include parens
|
11635
11821
|
if (str.charAt(0) !== "(") { str = "(" + str; }
|
11636
11822
|
if (str.slice(-1) !== ")") { str = str + ")"; }
|
11637
11823
|
}
|
11638
|
-
|
11824
|
+
const mtext = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mtext");
|
11825
|
+
mtext.appendChild(document.createTextNode(str));
|
11826
|
+
const math = document.createElementNS("http://www.w3.org/1998/Math/MathML", "math");
|
11827
|
+
math.appendChild(mtext);
|
11828
|
+
ref.appendChild(math);
|
11639
11829
|
});
|
11640
11830
|
}
|
11641
11831
|
|