temml 0.10.32 → 0.10.33
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.cjs +252 -128
- package/dist/temml.js +252 -128
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +252 -128
- package/dist/temmlPostProcess.js +37 -24
- package/package.json +1 -1
- package/src/Style.js +5 -3
- package/src/buildMathML.js +84 -62
- package/src/domTree.js +34 -0
- package/src/environments/cd.js +15 -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/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 +1 -1
- package/src/postProcess.js +37 -24
- package/src/symbols.js +2 -2
- package/src/variant.js +2 -0
package/dist/temml.mjs
CHANGED
@@ -499,6 +499,40 @@ let TextNode$1 = class TextNode {
|
|
499
499
|
}
|
500
500
|
};
|
501
501
|
|
502
|
+
// Create an <a href="…"> node.
|
503
|
+
class AnchorNode {
|
504
|
+
constructor(href, classes, children) {
|
505
|
+
this.href = href;
|
506
|
+
this.classes = classes;
|
507
|
+
this.children = children || [];
|
508
|
+
}
|
509
|
+
|
510
|
+
toNode() {
|
511
|
+
const node = document.createElement("a");
|
512
|
+
node.setAttribute("href", this.href);
|
513
|
+
if (this.classes.length > 0) {
|
514
|
+
node.className = createClass(this.classes);
|
515
|
+
}
|
516
|
+
for (let i = 0; i < this.children.length; i++) {
|
517
|
+
node.appendChild(this.children[i].toNode());
|
518
|
+
}
|
519
|
+
return node
|
520
|
+
}
|
521
|
+
|
522
|
+
toMarkup() {
|
523
|
+
let markup = `<a href='${utils.escape(this.href)}'`;
|
524
|
+
if (this.classes.length > 0) {
|
525
|
+
markup += ` class="${utils.escape(createClass(this.classes))}"`;
|
526
|
+
}
|
527
|
+
markup += ">";
|
528
|
+
for (let i = 0; i < this.children.length; i++) {
|
529
|
+
markup += this.children[i].toMarkup();
|
530
|
+
}
|
531
|
+
markup += "</a>";
|
532
|
+
return markup
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
502
536
|
/*
|
503
537
|
* This node represents an image embed (<img>) element.
|
504
538
|
*/
|
@@ -1528,7 +1562,7 @@ defineSymbol(math, open, "\u27e8", "\\langle", true);
|
|
1528
1562
|
defineSymbol(math, open, "\u27ea", "\\lAngle", true);
|
1529
1563
|
defineSymbol(math, open, "\u2989", "\\llangle", true);
|
1530
1564
|
defineSymbol(math, open, "|", "\\lvert");
|
1531
|
-
defineSymbol(math, open, "\u2016", "\\lVert");
|
1565
|
+
defineSymbol(math, open, "\u2016", "\\lVert", true);
|
1532
1566
|
defineSymbol(math, textord, "!", "\\oc"); // cmll package
|
1533
1567
|
defineSymbol(math, textord, "?", "\\wn");
|
1534
1568
|
defineSymbol(math, textord, "\u2193", "\\shpos");
|
@@ -1692,7 +1726,7 @@ defineSymbol(math, inner, "\u22f0", "\\iddots", true);
|
|
1692
1726
|
defineSymbol(math, inner, "\u22ef", "\\@cdots", true);
|
1693
1727
|
defineSymbol(math, inner, "\u22f1", "\\ddots", true);
|
1694
1728
|
defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
|
1695
|
-
defineSymbol(text, textord, "\u22ee", "\\
|
1729
|
+
defineSymbol(text, textord, "\u22ee", "\\varvdots");
|
1696
1730
|
defineSymbol(math, accent, "\u02ca", "\\acute");
|
1697
1731
|
defineSymbol(math, accent, "\u0060", "\\grave");
|
1698
1732
|
defineSymbol(math, accent, "\u00a8", "\\ddot");
|
@@ -2145,61 +2179,6 @@ const consolidateText = mrow => {
|
|
2145
2179
|
}
|
2146
2180
|
};
|
2147
2181
|
|
2148
|
-
const numberRegEx$1 = /^[0-9]$/;
|
2149
|
-
const isDotOrComma = (node, followingNode) => {
|
2150
|
-
return ((node.type === "textord" && node.text === ".") ||
|
2151
|
-
(node.type === "atom" && node.text === ",")) &&
|
2152
|
-
// Don't consolidate if there is a space after the comma.
|
2153
|
-
node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
|
2154
|
-
};
|
2155
|
-
const consolidateNumbers = expression => {
|
2156
|
-
// Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
|
2157
|
-
// not <mn>1</mn><mo>,</mo><mn>5</mn><mn>0</mn><mn>6</mn><mi>.</mi><mn>3</mn>
|
2158
|
-
if (expression.length < 2) { return }
|
2159
|
-
const nums = [];
|
2160
|
-
let inNum = false;
|
2161
|
-
// Find adjacent numerals
|
2162
|
-
for (let i = 0; i < expression.length; i++) {
|
2163
|
-
const node = expression[i];
|
2164
|
-
if (node.type === "textord" && numberRegEx$1.test(node.text)) {
|
2165
|
-
if (!inNum) { nums.push({ start: i }); }
|
2166
|
-
inNum = true;
|
2167
|
-
} else {
|
2168
|
-
if (inNum) { nums[nums.length - 1].end = i - 1; }
|
2169
|
-
inNum = false;
|
2170
|
-
}
|
2171
|
-
}
|
2172
|
-
if (inNum) { nums[nums.length - 1].end = expression.length - 1; }
|
2173
|
-
|
2174
|
-
// Determine if numeral groups are separated by a comma or dot.
|
2175
|
-
for (let i = nums.length - 1; i > 0; i--) {
|
2176
|
-
if (nums[i - 1].end === nums[i].start - 2 &&
|
2177
|
-
isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
|
2178
|
-
// Merge the two groups.
|
2179
|
-
nums[i - 1].end = nums[i].end;
|
2180
|
-
nums.splice(i, 1);
|
2181
|
-
}
|
2182
|
-
}
|
2183
|
-
|
2184
|
-
// Consolidate the number nodes
|
2185
|
-
for (let i = nums.length - 1; i >= 0; i--) {
|
2186
|
-
for (let j = nums[i].start + 1; j <= nums[i].end; j++) {
|
2187
|
-
expression[nums[i].start].text += expression[j].text;
|
2188
|
-
}
|
2189
|
-
expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
|
2190
|
-
// Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
|
2191
|
-
// If so, merge the first <mn> into the base.
|
2192
|
-
if (expression.length > nums[i].start + 1) {
|
2193
|
-
const nextTerm = expression[nums[i].start + 1];
|
2194
|
-
if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
|
2195
|
-
numberRegEx$1.test(nextTerm.base.text)) {
|
2196
|
-
nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
|
2197
|
-
expression.splice(nums[i].start, 1);
|
2198
|
-
}
|
2199
|
-
}
|
2200
|
-
}
|
2201
|
-
};
|
2202
|
-
|
2203
2182
|
/**
|
2204
2183
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
2205
2184
|
* unless the array has length 1. Always returns a single node.
|
@@ -2222,6 +2201,39 @@ const makeRow = function(body, semisimple = false) {
|
|
2222
2201
|
return new mathMLTree.MathNode("mrow", body);
|
2223
2202
|
};
|
2224
2203
|
|
2204
|
+
/**
|
2205
|
+
* Check for <mi>.</mi> which is how a dot renders in MathML,
|
2206
|
+
* or <mo separator="true" lspace="0em" rspace="0em">,</mo>
|
2207
|
+
* which is how a braced comma {,} renders in MathML
|
2208
|
+
*/
|
2209
|
+
function isNumberPunctuation(group) {
|
2210
|
+
if (!group) {
|
2211
|
+
return false
|
2212
|
+
}
|
2213
|
+
if (group.type === 'mi' && group.children.length === 1) {
|
2214
|
+
const child = group.children[0];
|
2215
|
+
return child instanceof TextNode && child.text === '.'
|
2216
|
+
} else if (group.type === "mtext" && group.children.length === 1) {
|
2217
|
+
const child = group.children[0];
|
2218
|
+
return child instanceof TextNode && child.text === '\u2008' // punctuation space
|
2219
|
+
} else if (group.type === 'mo' && group.children.length === 1 &&
|
2220
|
+
group.getAttribute('separator') === 'true' &&
|
2221
|
+
group.getAttribute('lspace') === '0em' &&
|
2222
|
+
group.getAttribute('rspace') === '0em') {
|
2223
|
+
const child = group.children[0];
|
2224
|
+
return child instanceof TextNode && child.text === ','
|
2225
|
+
} else {
|
2226
|
+
return false
|
2227
|
+
}
|
2228
|
+
}
|
2229
|
+
const isComma = (expression, i) => {
|
2230
|
+
const node = expression[i];
|
2231
|
+
const followingNode = expression[i + 1];
|
2232
|
+
return (node.type === "atom" && node.text === ",") &&
|
2233
|
+
// Don't consolidate if there is a space after the comma.
|
2234
|
+
node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
|
2235
|
+
};
|
2236
|
+
|
2225
2237
|
const isRel = item => {
|
2226
2238
|
return (item.type === "atom" && item.family === "rel") ||
|
2227
2239
|
(item.type === "mclass" && item.mclass === "mrel")
|
@@ -2245,11 +2257,16 @@ const buildExpression = function(expression, style, semisimple = false) {
|
|
2245
2257
|
return [group];
|
2246
2258
|
}
|
2247
2259
|
|
2248
|
-
consolidateNumbers(expression);
|
2249
|
-
|
2250
2260
|
const groups = [];
|
2261
|
+
const groupArray = [];
|
2262
|
+
let lastGroup;
|
2251
2263
|
for (let i = 0; i < expression.length; i++) {
|
2252
|
-
|
2264
|
+
groupArray.push(buildGroup$1(expression[i], style));
|
2265
|
+
}
|
2266
|
+
|
2267
|
+
for (let i = 0; i < groupArray.length; i++) {
|
2268
|
+
const group = groupArray[i];
|
2269
|
+
|
2253
2270
|
// Suppress spacing between adjacent relations
|
2254
2271
|
if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) {
|
2255
2272
|
group.setAttribute("rspace", "0em");
|
@@ -2257,9 +2274,39 @@ const buildExpression = function(expression, style, semisimple = false) {
|
|
2257
2274
|
if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) {
|
2258
2275
|
group.setAttribute("lspace", "0em");
|
2259
2276
|
}
|
2277
|
+
|
2278
|
+
// Concatenate numbers
|
2279
|
+
if (group.type === 'mn' && lastGroup && lastGroup.type === 'mn') {
|
2280
|
+
// Concatenate <mn>...</mn> followed by <mi>.</mi>
|
2281
|
+
lastGroup.children.push(...group.children);
|
2282
|
+
continue
|
2283
|
+
} else if (isNumberPunctuation(group) && lastGroup && lastGroup.type === 'mn') {
|
2284
|
+
// Concatenate <mn>...</mn> followed by <mi>.</mi>
|
2285
|
+
lastGroup.children.push(...group.children);
|
2286
|
+
continue
|
2287
|
+
} else if (lastGroup && lastGroup.type === "mn" && i < groupArray.length - 1 &&
|
2288
|
+
groupArray[i + 1].type === "mn" && isComma(expression, i)) {
|
2289
|
+
lastGroup.children.push(...group.children);
|
2290
|
+
continue
|
2291
|
+
} else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) {
|
2292
|
+
// Concatenate <mi>.</mi> followed by <mn>...</mn>
|
2293
|
+
group.children = [...lastGroup.children, ...group.children];
|
2294
|
+
groups.pop();
|
2295
|
+
} else if ((group.type === 'msup' || group.type === 'msub') &&
|
2296
|
+
group.children.length >= 1 && lastGroup &&
|
2297
|
+
(lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) {
|
2298
|
+
// Put preceding <mn>...</mn> or <mi>.</mi> inside base of
|
2299
|
+
// <msup><mn>...base...</mn>...exponent...</msup> (or <msub>)
|
2300
|
+
const base = group.children[0];
|
2301
|
+
if (base instanceof MathNode && base.type === 'mn' && lastGroup) {
|
2302
|
+
base.children = [...lastGroup.children, ...base.children];
|
2303
|
+
groups.pop();
|
2304
|
+
}
|
2305
|
+
}
|
2260
2306
|
groups.push(group);
|
2307
|
+
lastGroup = group;
|
2261
2308
|
}
|
2262
|
-
return groups
|
2309
|
+
return groups
|
2263
2310
|
};
|
2264
2311
|
|
2265
2312
|
/**
|
@@ -2321,6 +2368,11 @@ function buildMathML(tree, texExpression, style, settings) {
|
|
2321
2368
|
}
|
2322
2369
|
|
2323
2370
|
const expression = buildExpression(tree, style);
|
2371
|
+
|
2372
|
+
if (expression.length === 1 && expression[0] instanceof AnchorNode) {
|
2373
|
+
return expression[0]
|
2374
|
+
}
|
2375
|
+
|
2324
2376
|
const wrap = (settings.displayMode || settings.annotate) ? "none" : settings.wrap;
|
2325
2377
|
|
2326
2378
|
const n1 = expression.length === 0 ? null : expression[0];
|
@@ -2345,6 +2397,9 @@ function buildMathML(tree, texExpression, style, settings) {
|
|
2345
2397
|
if (settings.xml) {
|
2346
2398
|
math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
|
2347
2399
|
}
|
2400
|
+
if (wrapper.style.width) {
|
2401
|
+
math.style.width = "100%";
|
2402
|
+
}
|
2348
2403
|
if (settings.displayMode) {
|
2349
2404
|
math.setAttribute("display", "block");
|
2350
2405
|
math.style.display = "block math"; // necessary in Chromium.
|
@@ -2676,12 +2731,19 @@ const padding$2 = width => {
|
|
2676
2731
|
return node
|
2677
2732
|
};
|
2678
2733
|
|
2679
|
-
const paddedNode = (group, lspace = 0.3, rspace = 0) => {
|
2734
|
+
const paddedNode = (group, lspace = 0.3, rspace = 0, mustSmash = false) => {
|
2680
2735
|
if (group == null && rspace === 0) { return padding$2(lspace) }
|
2681
2736
|
const row = group ? [group] : [];
|
2682
2737
|
if (lspace !== 0) { row.unshift(padding$2(lspace)); }
|
2683
2738
|
if (rspace > 0) { row.push(padding$2(rspace)); }
|
2684
|
-
|
2739
|
+
if (mustSmash) {
|
2740
|
+
// Used for the bottom arrow in a {CD} environment
|
2741
|
+
const mpadded = new mathMLTree.MathNode("mpadded", row);
|
2742
|
+
mpadded.setAttribute("height", "0");
|
2743
|
+
return mpadded
|
2744
|
+
} else {
|
2745
|
+
return new mathMLTree.MathNode("mrow", row)
|
2746
|
+
}
|
2685
2747
|
};
|
2686
2748
|
|
2687
2749
|
const labelSize = (size, scriptLevel) => Number(size) / emScale(scriptLevel);
|
@@ -2721,7 +2783,8 @@ const munderoverNode = (fName, body, below, style) => {
|
|
2721
2783
|
(body.body.body || body.body.length > 0));
|
2722
2784
|
if (gotUpper) {
|
2723
2785
|
let label = buildGroup$1(body, labelStyle);
|
2724
|
-
|
2786
|
+
const mustSmash = (fName === "\\\\cdrightarrow" || fName === "\\\\cdleftarrow");
|
2787
|
+
label = paddedNode(label, space, space, mustSmash);
|
2725
2788
|
// Since Firefox does not support minsize, stack a invisible node
|
2726
2789
|
// on top of the label. Its width will serve as a min-width.
|
2727
2790
|
// TODO: Refactor this after Firefox supports minsize.
|
@@ -3144,18 +3207,23 @@ defineFunction({
|
|
3144
3207
|
};
|
3145
3208
|
},
|
3146
3209
|
mathmlBuilder(group, style) {
|
3147
|
-
|
3148
|
-
|
3149
|
-
label.setAttribute("width", "0");
|
3150
|
-
if (group.side === "left") {
|
3151
|
-
label.setAttribute("lspace", "-1width");
|
3210
|
+
if (group.label.body.length === 0) {
|
3211
|
+
return new mathMLTree.MathNode("mrow", style) // empty label
|
3152
3212
|
}
|
3153
|
-
//
|
3154
|
-
|
3155
|
-
|
3156
|
-
|
3213
|
+
// Abuse an <mtable> to create vertically centered content.
|
3214
|
+
const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.label, style)]);
|
3215
|
+
mtd.style.padding = "0";
|
3216
|
+
const mtr = new mathMLTree.MathNode("mtr", [mtd]);
|
3217
|
+
const mtable = new mathMLTree.MathNode("mtable", [mtr]);
|
3218
|
+
const label = new mathMLTree.MathNode("mpadded", [mtable]);
|
3219
|
+
// Set the label width to zero so that the arrow will be centered under the corner cell.
|
3220
|
+
label.setAttribute("width", "0");
|
3157
3221
|
label.setAttribute("displaystyle", "false");
|
3158
3222
|
label.setAttribute("scriptlevel", "1");
|
3223
|
+
if (group.side === "left") {
|
3224
|
+
label.style.display = "flex";
|
3225
|
+
label.style.justifyContent = "flex-end";
|
3226
|
+
}
|
3159
3227
|
return label;
|
3160
3228
|
}
|
3161
3229
|
});
|
@@ -3745,10 +3813,13 @@ defineFunction({
|
|
3745
3813
|
// replacement text, enclosed in '{' and '}' and properly nested
|
3746
3814
|
const { tokens } = parser.gullet.consumeArg();
|
3747
3815
|
|
3748
|
-
parser.gullet.macros.
|
3749
|
-
|
3750
|
-
|
3751
|
-
|
3816
|
+
if (!(funcName === "\\providecommand" && parser.gullet.macros.has(name))) {
|
3817
|
+
// Ignore \providecommand
|
3818
|
+
parser.gullet.macros.set(
|
3819
|
+
name,
|
3820
|
+
{ tokens, numArgs }
|
3821
|
+
);
|
3822
|
+
}
|
3752
3823
|
|
3753
3824
|
return { type: "internal", mode: parser.mode };
|
3754
3825
|
|
@@ -3842,6 +3913,7 @@ const delimiters = [
|
|
3842
3913
|
"\\vert",
|
3843
3914
|
"\\|",
|
3844
3915
|
"\\Vert",
|
3916
|
+
"\u2016",
|
3845
3917
|
"\\uparrow",
|
3846
3918
|
"\\Uparrow",
|
3847
3919
|
"\\downarrow",
|
@@ -4611,7 +4683,7 @@ defineMacro("\\underbar", "\\underline{\\text{#1}}");
|
|
4611
4683
|
// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
|
4612
4684
|
// We'll call \varvdots, which gets a glyph from symbols.js.
|
4613
4685
|
// The zero-width rule gets us an equivalent to the vertical 6pt kern.
|
4614
|
-
defineMacro("\\vdots", "
|
4686
|
+
defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}");
|
4615
4687
|
defineMacro("\u22ee", "\\vdots");
|
4616
4688
|
|
4617
4689
|
// {array} environment gaps
|
@@ -8074,6 +8146,7 @@ defineFunction({
|
|
8074
8146
|
"\\mathfrak",
|
8075
8147
|
"\\mathscr",
|
8076
8148
|
"\\mathsf",
|
8149
|
+
"\\mathsfit",
|
8077
8150
|
"\\mathtt",
|
8078
8151
|
|
8079
8152
|
// aliases
|
@@ -8143,10 +8216,19 @@ const mathmlBuilder$5 = (group, style) => {
|
|
8143
8216
|
? style.withLevel(StyleLevel.SCRIPT)
|
8144
8217
|
: style.withLevel(StyleLevel.SCRIPTSCRIPT);
|
8145
8218
|
|
8146
|
-
|
8147
|
-
|
8148
|
-
|
8149
|
-
|
8219
|
+
// Chromium (wrongly) continues to shrink fractions beyond scriptscriptlevel.
|
8220
|
+
// So we check for levels that Chromium shrinks too small.
|
8221
|
+
// If necessary, set an explicit fraction depth.
|
8222
|
+
const numer = buildGroup$1(group.numer, childOptions);
|
8223
|
+
const denom = buildGroup$1(group.denom, childOptions);
|
8224
|
+
if (style.level === 3) {
|
8225
|
+
numer.style.mathDepth = "2";
|
8226
|
+
numer.setAttribute("scriptlevel", "2");
|
8227
|
+
denom.style.mathDepth = "2";
|
8228
|
+
denom.setAttribute("scriptlevel", "2");
|
8229
|
+
}
|
8230
|
+
|
8231
|
+
let node = new mathMLTree.MathNode("mfrac", [numer, denom]);
|
8150
8232
|
|
8151
8233
|
if (!group.hasBarLine) {
|
8152
8234
|
node.setAttribute("linethickness", "0px");
|
@@ -8539,12 +8621,9 @@ defineFunction({
|
|
8539
8621
|
};
|
8540
8622
|
},
|
8541
8623
|
mathmlBuilder: (group, style) => {
|
8542
|
-
|
8543
|
-
|
8544
|
-
|
8545
|
-
}
|
8546
|
-
math.setAttribute("href", group.href);
|
8547
|
-
return math;
|
8624
|
+
const math = new MathNode("math", [buildExpressionRow(group.body, style)]);
|
8625
|
+
const anchorNode = new AnchorNode(group.href, [], [math]);
|
8626
|
+
return anchorNode
|
8548
8627
|
}
|
8549
8628
|
});
|
8550
8629
|
|
@@ -9416,13 +9495,6 @@ const mathmlBuilder$2 = (group, style) => {
|
|
9416
9495
|
node = new MathNode("mo", [makeText(group.name, group.mode)]);
|
9417
9496
|
if (noSuccessor.includes(group.name)) {
|
9418
9497
|
node.setAttribute("largeop", "false");
|
9419
|
-
} else if (group.limits) {
|
9420
|
-
// This is a workaround for a MathML/Chromium bug.
|
9421
|
-
// This is being applied to singleCharBigOps, which are not really stretchy.
|
9422
|
-
// But by setting the stretchy attribute, Chromium will vertically center
|
9423
|
-
// big ops around the math axis. This is needed since STIX TWO does not do so.
|
9424
|
-
// TODO: Remove this hack when MathML & Chromium fix their problem.
|
9425
|
-
node.setAttribute("stretchy", "true");
|
9426
9498
|
} else {
|
9427
9499
|
node.setAttribute("movablelimits", "false");
|
9428
9500
|
}
|
@@ -10057,12 +10129,10 @@ defineFunction({
|
|
10057
10129
|
};
|
10058
10130
|
},
|
10059
10131
|
mathmlBuilder(group, style) {
|
10060
|
-
// Create an empty
|
10132
|
+
// Create an empty <a> node. Set a class and an href attribute.
|
10061
10133
|
// The post-processor will populate with the target's tag or equation number.
|
10062
10134
|
const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"];
|
10063
|
-
|
10064
|
-
node.setAttribute("href", "#" + group.string);
|
10065
|
-
return node
|
10135
|
+
return new AnchorNode("#" + group.string, classes, null)
|
10066
10136
|
}
|
10067
10137
|
});
|
10068
10138
|
|
@@ -10109,6 +10179,8 @@ defineFunction({
|
|
10109
10179
|
props: {
|
10110
10180
|
numArgs: 2,
|
10111
10181
|
numOptionalArgs: 1,
|
10182
|
+
allowedInText: true,
|
10183
|
+
allowedInMath: true,
|
10112
10184
|
argTypes: ["size", "size", "size"]
|
10113
10185
|
},
|
10114
10186
|
handler({ parser }, args, optArgs) {
|
@@ -10401,16 +10473,25 @@ defineFunctionBuilders({
|
|
10401
10473
|
? [buildGroup$1(group.base.body[0], style)]
|
10402
10474
|
: [buildGroup$1(group.base, style)];
|
10403
10475
|
|
10476
|
+
// Note regarding scriptstyle level.
|
10477
|
+
// (Sub|super)scripts should not shrink beyond MathML scriptlevel 2 aka \scriptscriptstyle
|
10478
|
+
// Ref: https://w3c.github.io/mathml-core/#the-displaystyle-and-scriptlevel-attributes
|
10479
|
+
// (BTW, MathML scriptlevel 2 is equal to Temml level 3.)
|
10480
|
+
// But Chromium continues to shrink the (sub|super)scripts. So we explicitly set scriptlevel 2.
|
10481
|
+
|
10404
10482
|
const childStyle = style.inSubOrSup();
|
10405
10483
|
if (group.sub) {
|
10406
|
-
|
10484
|
+
const sub = buildGroup$1(group.sub, childStyle);
|
10485
|
+
if (style.level === 3) { sub.setAttribute("scriptlevel", "2"); }
|
10486
|
+
children.push(sub);
|
10407
10487
|
}
|
10408
10488
|
|
10409
10489
|
if (group.sup) {
|
10410
10490
|
const sup = buildGroup$1(group.sup, childStyle);
|
10491
|
+
if (style.level === 3) { sup.setAttribute("scriptlevel", "2"); }
|
10411
10492
|
const testNode = sup.type === "mrow" ? sup.children[0] : sup;
|
10412
10493
|
if ((testNode && testNode.type === "mo" && testNode.classes.includes("tml-prime"))
|
10413
|
-
&& group.base && group.base.text && group.base.text
|
10494
|
+
&& group.base && group.base.text && "fF".indexOf(group.base.text) > -1) {
|
10414
10495
|
// Chromium does not address italic correction on prime. Prevent f′ from overlapping.
|
10415
10496
|
testNode.classes.push("prime-pad");
|
10416
10497
|
}
|
@@ -10637,6 +10718,8 @@ const getVariant = function(group, style) {
|
|
10637
10718
|
return "script"
|
10638
10719
|
case "mathsf":
|
10639
10720
|
return "sans-serif"
|
10721
|
+
case "mathsfit":
|
10722
|
+
return "sans-serif-italic"
|
10640
10723
|
case "mathtt":
|
10641
10724
|
return "monospace"
|
10642
10725
|
}
|
@@ -11101,6 +11184,32 @@ defineFunction({
|
|
11101
11184
|
}
|
11102
11185
|
});
|
11103
11186
|
|
11187
|
+
// \vcenter: Vertically center the argument group on the math axis.
|
11188
|
+
|
11189
|
+
defineFunction({
|
11190
|
+
type: "vcenter",
|
11191
|
+
names: ["\\vcenter"],
|
11192
|
+
props: {
|
11193
|
+
numArgs: 1,
|
11194
|
+
argTypes: ["original"],
|
11195
|
+
allowedInText: false
|
11196
|
+
},
|
11197
|
+
handler({ parser }, args) {
|
11198
|
+
return {
|
11199
|
+
type: "vcenter",
|
11200
|
+
mode: parser.mode,
|
11201
|
+
body: args[0]
|
11202
|
+
};
|
11203
|
+
},
|
11204
|
+
mathmlBuilder(group, style) {
|
11205
|
+
// Use a math table to create vertically centered content.
|
11206
|
+
const mtd = new mathMLTree.MathNode("mtd", [buildGroup$1(group.body, style)]);
|
11207
|
+
mtd.style.padding = "0";
|
11208
|
+
const mtr = new mathMLTree.MathNode("mtr", [mtd]);
|
11209
|
+
return new mathMLTree.MathNode("mtable", [mtr])
|
11210
|
+
}
|
11211
|
+
});
|
11212
|
+
|
11104
11213
|
defineFunction({
|
11105
11214
|
type: "verb",
|
11106
11215
|
names: ["\\verb"],
|
@@ -13367,9 +13476,11 @@ class Style {
|
|
13367
13476
|
constructor(data) {
|
13368
13477
|
// Style.level can be 0 | 1 | 2 | 3, which correspond to
|
13369
13478
|
// displaystyle, textstyle, scriptstyle, and scriptscriptstyle.
|
13370
|
-
// style.level does not directly set MathML's script level. MathML does that itself.
|
13371
|
-
//
|
13372
|
-
//
|
13479
|
+
// style.level usually does not directly set MathML's script level. MathML does that itself.
|
13480
|
+
// However, Chromium does not stop shrinking after scriptscriptstyle, so we do explicitly
|
13481
|
+
// set a scriptlevel attribute in those conditions.
|
13482
|
+
// We also use style.level to track math style so that we can get the correct
|
13483
|
+
// scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em.
|
13373
13484
|
this.level = data.level;
|
13374
13485
|
this.color = data.color; // string | void
|
13375
13486
|
// A font family applies to a group of fonts (i.e. SansSerif), while a font
|
@@ -13493,39 +13604,47 @@ class Style {
|
|
13493
13604
|
}
|
13494
13605
|
|
13495
13606
|
/* Temml Post Process
|
13496
|
-
*
|
13497
|
-
* Given a block,
|
13498
|
-
* 1. At each AMS auto-numbered environment, assign an id.
|
13499
|
-
* 2. Populate the text contents of each \ref & \eqref
|
13607
|
+
* Populate the text contents of each \ref & \eqref
|
13500
13608
|
*
|
13501
13609
|
* As with other Temml code, this file is released under terms of the MIT license.
|
13502
13610
|
* https://mit-license.org/
|
13503
13611
|
*/
|
13504
13612
|
|
13505
|
-
const version = "0.10.
|
13613
|
+
const version = "0.10.33";
|
13506
13614
|
|
13507
13615
|
function postProcess(block) {
|
13508
13616
|
const labelMap = {};
|
13509
13617
|
let i = 0;
|
13510
13618
|
|
13511
13619
|
// Get a collection of the parents of each \tag & auto-numbered equation
|
13512
|
-
const
|
13513
|
-
for (
|
13514
|
-
|
13515
|
-
|
13516
|
-
|
13517
|
-
|
13518
|
-
|
13519
|
-
|
13520
|
-
|
13521
|
-
|
13620
|
+
const amsEqns = document.getElementsByClassName('tml-eqn');
|
13621
|
+
for (let parent of amsEqns) {
|
13622
|
+
// AMS automatically numbered equation.
|
13623
|
+
// Assign an id.
|
13624
|
+
i += 1;
|
13625
|
+
parent.setAttribute("id", "tml-eqn-" + String(i));
|
13626
|
+
// No need to write a number into the text content of the element.
|
13627
|
+
// A CSS counter has done that even if this postProcess() function is not used.
|
13628
|
+
|
13629
|
+
// Find any \label that refers to an AMS eqn number.
|
13630
|
+
while (true) {
|
13631
|
+
const labels = parent.getElementsByClassName("tml-label");
|
13632
|
+
if (labels.length > 0) {
|
13633
|
+
parent.setAttribute("id", labels[0].id);
|
13634
|
+
labelMap[labels[0].id] = String(i);
|
13635
|
+
break
|
13636
|
+
} else {
|
13637
|
+
if (parent.tagName === "mtable") { break }
|
13638
|
+
parent = parent.parentElement;
|
13639
|
+
}
|
13522
13640
|
}
|
13523
|
-
|
13641
|
+
}
|
13642
|
+
|
13643
|
+
// Find \labels associated with \tag
|
13644
|
+
const taggedEqns = document.getElementsByClassName('tml-tageqn');
|
13645
|
+
for (const parent of taggedEqns) {
|
13524
13646
|
const labels = parent.getElementsByClassName("tml-label");
|
13525
|
-
if (labels.length
|
13526
|
-
if (eqns.length > 0) {
|
13527
|
-
labelMap[labels[0].id] = String(i);
|
13528
|
-
} else {
|
13647
|
+
if (labels.length > 0) {
|
13529
13648
|
const tags = parent.getElementsByClassName("tml-tag");
|
13530
13649
|
if (tags.length > 0) {
|
13531
13650
|
labelMap[labels[0].id] = tags[0].textContent;
|
@@ -13536,17 +13655,22 @@ function postProcess(block) {
|
|
13536
13655
|
// Populate \ref & \eqref text content
|
13537
13656
|
const refs = block.getElementsByClassName("tml-ref");
|
13538
13657
|
[...refs].forEach(ref => {
|
13539
|
-
|
13658
|
+
const attr = ref.getAttribute("href");
|
13659
|
+
let str = labelMap[attr.slice(1)];
|
13540
13660
|
if (ref.className.indexOf("tml-eqref") === -1) {
|
13541
13661
|
// \ref. Omit parens.
|
13542
13662
|
str = str.replace(/^\(/, "");
|
13543
|
-
str = str.replace(/\
|
13544
|
-
}
|
13663
|
+
str = str.replace(/\)$/, "");
|
13664
|
+
} else {
|
13545
13665
|
// \eqref. Include parens
|
13546
13666
|
if (str.charAt(0) !== "(") { str = "(" + str; }
|
13547
13667
|
if (str.slice(-1) !== ")") { str = str + ")"; }
|
13548
13668
|
}
|
13549
|
-
|
13669
|
+
const mtext = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mtext");
|
13670
|
+
mtext.appendChild(document.createTextNode(str));
|
13671
|
+
const math = document.createElementNS("http://www.w3.org/1998/Math/MathML", "math");
|
13672
|
+
math.appendChild(mtext);
|
13673
|
+
ref.appendChild(math);
|
13550
13674
|
});
|
13551
13675
|
}
|
13552
13676
|
|