temml 0.12.2 → 0.13.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 +3 -4
- package/contrib/mhchem/mhchem.min.js +1 -1
- package/dist/Temml-Asana.css +11 -13
- package/dist/Temml-Latin-Modern.css +11 -13
- package/dist/Temml-Libertinus.css +11 -13
- package/dist/Temml-Local.css +11 -13
- package/dist/Temml-NotoSans.css +11 -13
- package/dist/Temml-STIX2.css +11 -13
- package/dist/temml.cjs +227 -116
- package/dist/temml.js +227 -116
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +227 -116
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +2 -2
- package/src/Parser.js +11 -4
- package/src/Settings.js +1 -0
- package/src/functions/cancelto.js +2 -0
- package/src/functions/color.js +1 -1
- package/src/functions/{delimsizing.js → delimiter.js} +132 -42
- package/src/functions/enclose.js +1 -1
- package/src/functions/genfrac.js +32 -45
- package/src/functions/mclass.js +10 -2
- package/src/functions/op.js +1 -1
- package/src/functions/operatorname.js +9 -1
- package/src/functions/symbolsOrd.js +2 -2
- package/src/functions.js +1 -1
- package/src/linebreaking.js +3 -10
- package/src/macros.js +2 -2
- package/src/parseNode.js +1 -1
- package/src/parseTree.js +20 -4
- package/src/postProcess.js +1 -1
- package/src/symbols.js +2 -3
package/dist/temml.js
CHANGED
|
@@ -216,6 +216,7 @@ var temml = (function () {
|
|
|
216
216
|
: [Infinity, Infinity]
|
|
217
217
|
);
|
|
218
218
|
this.maxExpand = Math.max(0, deflt(options.maxExpand, 1000)); // number
|
|
219
|
+
this.wrapDelimiterPairs = true; // boolean
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
/**
|
|
@@ -997,8 +998,7 @@ var temml = (function () {
|
|
|
997
998
|
defineSymbol(math, textord, "\u2200", "\\forall", true);
|
|
998
999
|
defineSymbol(math, textord, "\u210f", "\\hbar", true);
|
|
999
1000
|
defineSymbol(math, textord, "\u2203", "\\exists", true);
|
|
1000
|
-
|
|
1001
|
-
defineSymbol(math, bin, "\u2207", "\\nabla", true);
|
|
1001
|
+
defineSymbol(math, open, "\u2207", "\\nabla", true);
|
|
1002
1002
|
defineSymbol(math, textord, "\u266d", "\\flat", true);
|
|
1003
1003
|
defineSymbol(math, textord, "\u2113", "\\ell", true);
|
|
1004
1004
|
defineSymbol(math, textord, "\u266e", "\\natural", true);
|
|
@@ -1091,7 +1091,7 @@ var temml = (function () {
|
|
|
1091
1091
|
|
|
1092
1092
|
// AMS Negated Binary Relations
|
|
1093
1093
|
defineSymbol(math, rel, "\u226e", "\\nless", true);
|
|
1094
|
-
// Symbol names
|
|
1094
|
+
// Symbol names preceded by "@" each have a corresponding macro.
|
|
1095
1095
|
defineSymbol(math, rel, "\u2a87", "\\lneq", true);
|
|
1096
1096
|
defineSymbol(math, rel, "\u2268", "\\lneqq", true);
|
|
1097
1097
|
defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq");
|
|
@@ -2002,16 +2002,12 @@ var temml = (function () {
|
|
|
2002
2002
|
* much of this module.
|
|
2003
2003
|
*/
|
|
2004
2004
|
|
|
2005
|
-
const openDelims = "([{⌊⌈⟨⟮⎰⟦⦃";
|
|
2006
|
-
const closeDelims = ")]}⌋⌉⟩⟯⎱⟦⦄";
|
|
2007
|
-
|
|
2008
2005
|
function setLineBreaks(expression, wrapMode, isDisplayMode) {
|
|
2009
2006
|
const mtrs = [];
|
|
2010
2007
|
let mrows = [];
|
|
2011
2008
|
let block = [];
|
|
2012
2009
|
let numTopLevelEquals = 0;
|
|
2013
2010
|
let i = 0;
|
|
2014
|
-
let level = 0;
|
|
2015
2011
|
while (i < expression.length) {
|
|
2016
2012
|
while (expression[i] instanceof DocumentFragment) {
|
|
2017
2013
|
expression.splice(i, 1, ...expression[i].children); // Expand the fragment.
|
|
@@ -2034,13 +2030,10 @@ var temml = (function () {
|
|
|
2034
2030
|
}
|
|
2035
2031
|
block.push(node);
|
|
2036
2032
|
if (node.type && node.type === "mo" && node.children.length === 1 &&
|
|
2033
|
+
!(node.attributes.form && node.attributes.form === "prefix") && // unary operators
|
|
2037
2034
|
!Object.prototype.hasOwnProperty.call(node.attributes, "movablelimits")) {
|
|
2038
2035
|
const ch = node.children[0].text;
|
|
2039
|
-
if (
|
|
2040
|
-
level += 1;
|
|
2041
|
-
} else if (closeDelims.indexOf(ch) > -1) {
|
|
2042
|
-
level -= 1;
|
|
2043
|
-
} else if (level === 0 && wrapMode === "=" && ch === "=") {
|
|
2036
|
+
if (wrapMode === "=" && ch === "=") {
|
|
2044
2037
|
numTopLevelEquals += 1;
|
|
2045
2038
|
if (numTopLevelEquals > 1) {
|
|
2046
2039
|
block.pop();
|
|
@@ -2049,7 +2042,7 @@ var temml = (function () {
|
|
|
2049
2042
|
mrows.push(element);
|
|
2050
2043
|
block = [node];
|
|
2051
2044
|
}
|
|
2052
|
-
} else if (
|
|
2045
|
+
} else if (wrapMode === "tex") {
|
|
2053
2046
|
// Check if the following node is a \nobreak text node, e.g. "~""
|
|
2054
2047
|
const next = i < expression.length - 1 ? expression[i + 1] : null;
|
|
2055
2048
|
let glueIsFreeOfNobreak = true;
|
|
@@ -3071,7 +3064,7 @@ var temml = (function () {
|
|
|
3071
3064
|
* returns null.
|
|
3072
3065
|
*/
|
|
3073
3066
|
function checkSymbolNodeType(node) {
|
|
3074
|
-
if (node && (node.type === "atom" ||
|
|
3067
|
+
if (node && (node.type === "atom" || node.type === "delimiter" ||
|
|
3075
3068
|
Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) {
|
|
3076
3069
|
return node;
|
|
3077
3070
|
}
|
|
@@ -3877,7 +3870,6 @@ var temml = (function () {
|
|
|
3877
3870
|
"\\iint": "\\dotsi",
|
|
3878
3871
|
"\\iiint": "\\dotsi",
|
|
3879
3872
|
"\\iiiint": "\\dotsi",
|
|
3880
|
-
"\\idotsint": "\\dotsi",
|
|
3881
3873
|
// Symbols whose definition starts with \DOTSX:
|
|
3882
3874
|
"\\DOTSX": "\\dotsx"
|
|
3883
3875
|
};
|
|
@@ -3959,7 +3951,7 @@ var temml = (function () {
|
|
|
3959
3951
|
defineMacro("\\dotsb", "\\cdots");
|
|
3960
3952
|
defineMacro("\\dotsm", "\\cdots");
|
|
3961
3953
|
defineMacro("\\dotsi", "\\!\\cdots");
|
|
3962
|
-
defineMacro("\\idotsint", "\\
|
|
3954
|
+
defineMacro("\\idotsint", "\\int\\!\\cdots\\!\\int");
|
|
3963
3955
|
// amsmath doesn't actually define \dotsx, but \dots followed by a macro
|
|
3964
3956
|
// starting with \DOTSX implies \dotso, and then \extra@ detects this case
|
|
3965
3957
|
// and forces the added `\,`.
|
|
@@ -4254,6 +4246,7 @@ var temml = (function () {
|
|
|
4254
4246
|
// cmll package
|
|
4255
4247
|
defineMacro("\\invamp", '\\mathbin{\\char"214b}');
|
|
4256
4248
|
defineMacro("\\parr", '\\mathbin{\\char"214b}');
|
|
4249
|
+
defineMacro("\\upand", '\\mathbin{\\char"214b}'); // STIX package
|
|
4257
4250
|
defineMacro("\\with", '\\mathbin{\\char"26}');
|
|
4258
4251
|
defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}');
|
|
4259
4252
|
defineMacro("\\multimapboth", '\\mathrel{\\char"29df}');
|
|
@@ -5311,6 +5304,7 @@ var temml = (function () {
|
|
|
5311
5304
|
// That way, the arrow will be an overlay on the content.
|
|
5312
5305
|
const phantom = new MathNode("mphantom", [buildGroup$1(group.body, style)]);
|
|
5313
5306
|
const arrow = new MathNode("mrow", [phantom], ["tml-cancelto"]);
|
|
5307
|
+
arrow.style.color = style.color;
|
|
5314
5308
|
if (group.isCharacterBox && smalls.indexOf(group.body.body[0].text) > -1) {
|
|
5315
5309
|
arrow.style.left = "0.1em";
|
|
5316
5310
|
arrow.style.width = "90%";
|
|
@@ -5342,6 +5336,7 @@ var temml = (function () {
|
|
|
5342
5336
|
dummyNode = new MathNode("mphantom", [zeroWidthNode]); // Hide it.
|
|
5343
5337
|
}
|
|
5344
5338
|
const toNode = buildGroup$1(group.to, style);
|
|
5339
|
+
toNode.style.color = style.color;
|
|
5345
5340
|
const zeroWidthToNode = new MathNode("mpadded", [toNode]);
|
|
5346
5341
|
if (!group.isCharacterBox || /[f∫∑]/.test(group.body.body[0].text)) {
|
|
5347
5342
|
const w = new MathNode("mspace", []);
|
|
@@ -5400,7 +5395,7 @@ var temml = (function () {
|
|
|
5400
5395
|
|
|
5401
5396
|
// Colors from Tables 4.1 and 4.2 of the xcolor package.
|
|
5402
5397
|
// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx.
|
|
5403
|
-
// Table 4.2 (
|
|
5398
|
+
// Table 4.2 (Capitalized) values were sampled, because Chroma contains a unreliable
|
|
5404
5399
|
// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274.
|
|
5405
5400
|
const xcolors = JSON.parse(`{
|
|
5406
5401
|
"Apricot": "#ffb484",
|
|
@@ -5959,7 +5954,41 @@ var temml = (function () {
|
|
|
5959
5954
|
"\\Bigg": { mclass: "mord", size: 4 }
|
|
5960
5955
|
};
|
|
5961
5956
|
|
|
5962
|
-
const
|
|
5957
|
+
const leftToRight = {
|
|
5958
|
+
"(": ")",
|
|
5959
|
+
"\\lparen": "\\rparen",
|
|
5960
|
+
"[": "]",
|
|
5961
|
+
"\\lbrack": "\\rbrack",
|
|
5962
|
+
"\\{": "\\}",
|
|
5963
|
+
"\\lbrace": "\\rbrace",
|
|
5964
|
+
"⦇": "⦈",
|
|
5965
|
+
"\\llparenthesis": "\\rrparenthesis",
|
|
5966
|
+
"\\lfloor": "\\rfloor",
|
|
5967
|
+
"\u230a": "\u230b",
|
|
5968
|
+
"\\lceil": "\\rceil",
|
|
5969
|
+
"\u2308": "\u2309",
|
|
5970
|
+
"\\langle": "\\rangle",
|
|
5971
|
+
"\u27e8": "\u27e9",
|
|
5972
|
+
"\\lAngle": "\\rAngle",
|
|
5973
|
+
"\u27ea": "\u27eb",
|
|
5974
|
+
"\\llangle": "\\rrangle",
|
|
5975
|
+
"⦉": "⦊",
|
|
5976
|
+
"\\lvert": "\\rvert",
|
|
5977
|
+
"\\lVert": "\\rVert",
|
|
5978
|
+
"\\lgroup": "\\rgroup",
|
|
5979
|
+
"\u27ee": "\u27ef",
|
|
5980
|
+
"\\lmoustache": "\\rmoustache",
|
|
5981
|
+
"\u23b0": "\u23b1",
|
|
5982
|
+
"\\llbracket": "\\rrbracket",
|
|
5983
|
+
"\u27e6": "\u27e7",
|
|
5984
|
+
"\\lBrace": "\\rBrace",
|
|
5985
|
+
"\u2983": "\u2984"
|
|
5986
|
+
};
|
|
5987
|
+
|
|
5988
|
+
const leftDelimiterNames = new Set(Object.keys(leftToRight));
|
|
5989
|
+
new Set(Object.values(leftToRight));
|
|
5990
|
+
|
|
5991
|
+
const delimiters = new Set([
|
|
5963
5992
|
"(",
|
|
5964
5993
|
"\\lparen",
|
|
5965
5994
|
")",
|
|
@@ -6015,7 +6044,7 @@ var temml = (function () {
|
|
|
6015
6044
|
"\\llbracket",
|
|
6016
6045
|
"\\rrbracket",
|
|
6017
6046
|
"\u27e6",
|
|
6018
|
-
"\
|
|
6047
|
+
"\u27e7",
|
|
6019
6048
|
"\\lBrace",
|
|
6020
6049
|
"\\rBrace",
|
|
6021
6050
|
"\u2983",
|
|
@@ -6034,12 +6063,12 @@ var temml = (function () {
|
|
|
6034
6063
|
"\\updownarrow",
|
|
6035
6064
|
"\\Updownarrow",
|
|
6036
6065
|
"."
|
|
6037
|
-
];
|
|
6066
|
+
]);
|
|
6038
6067
|
|
|
6039
6068
|
// Export isDelimiter for benefit of parser.
|
|
6040
|
-
const dels = ["}", "\\left", "\\middle", "\\right"];
|
|
6069
|
+
const dels = new Set(["}", "\\left", "\\middle", "\\right"]);
|
|
6041
6070
|
const isDelimiter = str => str.length > 0 &&
|
|
6042
|
-
(delimiters.
|
|
6071
|
+
(delimiters.has(str) || delimiterSizes[str] || dels.has(str));
|
|
6043
6072
|
|
|
6044
6073
|
// Metrics of the different sizes. Found by looking at TeX's output of
|
|
6045
6074
|
// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
|
|
@@ -6052,11 +6081,11 @@ var temml = (function () {
|
|
|
6052
6081
|
delim = delim.body[0]; // Unwrap the braces
|
|
6053
6082
|
}
|
|
6054
6083
|
const symDelim = checkSymbolNodeType(delim);
|
|
6055
|
-
if (symDelim && delimiters.
|
|
6084
|
+
if (symDelim && delimiters.has(symDelim.text)) {
|
|
6056
6085
|
// If a character is not in the MathML operator dictionary, it will not stretch.
|
|
6057
6086
|
// Replace such characters w/characters that will stretch.
|
|
6058
|
-
if (
|
|
6059
|
-
if (
|
|
6087
|
+
if (symDelim.text === "<" || symDelim.text === "\\lt") { symDelim.text = "⟨"; }
|
|
6088
|
+
if (symDelim.text === ">" || symDelim.text === "\\gt") { symDelim.text = "⟩"; }
|
|
6060
6089
|
return symDelim;
|
|
6061
6090
|
} else if (symDelim) {
|
|
6062
6091
|
throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim);
|
|
@@ -6066,7 +6095,16 @@ var temml = (function () {
|
|
|
6066
6095
|
}
|
|
6067
6096
|
|
|
6068
6097
|
// / \
|
|
6069
|
-
const needExplicitStretch = ["\u002F", "\u005C", "\\backslash", "\\vert", "|"];
|
|
6098
|
+
const needExplicitStretch = new Set(["\u002F", "\u005C", "\\backslash", "\u2216", "\\vert", "|"]);
|
|
6099
|
+
|
|
6100
|
+
const makeFenceMo = (delim, mode, form, isStretchy) => {
|
|
6101
|
+
const text = delim === "." ? "" : delim;
|
|
6102
|
+
const node = new MathNode("mo", [makeText(text, mode)]);
|
|
6103
|
+
node.setAttribute("fence", "true");
|
|
6104
|
+
node.setAttribute("form", form);
|
|
6105
|
+
node.setAttribute("stretchy", isStretchy ? "true" : "false");
|
|
6106
|
+
return node;
|
|
6107
|
+
};
|
|
6070
6108
|
|
|
6071
6109
|
defineFunction({
|
|
6072
6110
|
type: "delimsizing",
|
|
@@ -6117,9 +6155,9 @@ var temml = (function () {
|
|
|
6117
6155
|
},
|
|
6118
6156
|
mathmlBuilder: (group) => {
|
|
6119
6157
|
const children = [];
|
|
6158
|
+
const delim = group.delim === "." ? "" : group.delim;
|
|
6120
6159
|
|
|
6121
|
-
|
|
6122
|
-
children.push(makeText(group.delim, group.mode));
|
|
6160
|
+
children.push(makeText(delim, group.mode));
|
|
6123
6161
|
|
|
6124
6162
|
const node = new MathNode("mo", children);
|
|
6125
6163
|
|
|
@@ -6132,7 +6170,7 @@ var temml = (function () {
|
|
|
6132
6170
|
// defaults.
|
|
6133
6171
|
node.setAttribute("fence", "false");
|
|
6134
6172
|
}
|
|
6135
|
-
if (needExplicitStretch.
|
|
6173
|
+
if (needExplicitStretch.has(delim) || delim.indexOf("arrow") > -1) {
|
|
6136
6174
|
// We have to explicitly set stretchy to true.
|
|
6137
6175
|
node.setAttribute("stretchy", "true");
|
|
6138
6176
|
}
|
|
@@ -6145,7 +6183,7 @@ var temml = (function () {
|
|
|
6145
6183
|
|
|
6146
6184
|
function assertParsed(group) {
|
|
6147
6185
|
if (!group.body) {
|
|
6148
|
-
throw new Error("Bug: The
|
|
6186
|
+
throw new Error("Bug: The delim ParseNode wasn't fully parsed.");
|
|
6149
6187
|
}
|
|
6150
6188
|
}
|
|
6151
6189
|
|
|
@@ -6176,17 +6214,10 @@ var temml = (function () {
|
|
|
6176
6214
|
const delim = checkDelimiter(args[0], context);
|
|
6177
6215
|
|
|
6178
6216
|
const parser = context.parser;
|
|
6179
|
-
// Parse out the implicit body
|
|
6180
6217
|
++parser.leftrightDepth;
|
|
6181
|
-
|
|
6182
|
-
let body = parser.parseExpression(false, null, true);
|
|
6218
|
+
let body = parser.parseExpression(false, "\\right", true);
|
|
6183
6219
|
let nextToken = parser.fetch();
|
|
6184
6220
|
while (nextToken.text === "\\middle") {
|
|
6185
|
-
// `\middle`, from the ε-TeX package, ends one group and starts another group.
|
|
6186
|
-
// We had to parse this expression with `breakOnMiddle` enabled in order
|
|
6187
|
-
// to get TeX-compliant parsing of \over.
|
|
6188
|
-
// But we do not want, at this point, to end on \middle, so continue
|
|
6189
|
-
// to parse until we fetch a `\right`.
|
|
6190
6221
|
parser.consume();
|
|
6191
6222
|
const middle = parser.fetch().text;
|
|
6192
6223
|
if (!symbols.math[middle]) {
|
|
@@ -6195,11 +6226,10 @@ var temml = (function () {
|
|
|
6195
6226
|
checkDelimiter({ type: "atom", mode: "math", text: middle }, { funcName: "\\middle" });
|
|
6196
6227
|
body.push({ type: "middle", mode: "math", delim: middle });
|
|
6197
6228
|
parser.consume();
|
|
6198
|
-
body = body.concat(parser.parseExpression(false,
|
|
6229
|
+
body = body.concat(parser.parseExpression(false, "\\right", true));
|
|
6199
6230
|
nextToken = parser.fetch();
|
|
6200
6231
|
}
|
|
6201
6232
|
--parser.leftrightDepth;
|
|
6202
|
-
// Check the next token
|
|
6203
6233
|
parser.expect("\\right", false);
|
|
6204
6234
|
const right = assertNodeType(parser.parseFunction(), "leftright-right");
|
|
6205
6235
|
return {
|
|
@@ -6207,35 +6237,90 @@ var temml = (function () {
|
|
|
6207
6237
|
mode: parser.mode,
|
|
6208
6238
|
body,
|
|
6209
6239
|
left: delim.text,
|
|
6210
|
-
right: right.delim
|
|
6240
|
+
right: right.delim,
|
|
6241
|
+
isStretchy: true
|
|
6211
6242
|
};
|
|
6212
6243
|
},
|
|
6213
6244
|
mathmlBuilder: (group, style) => {
|
|
6214
6245
|
assertParsed(group);
|
|
6215
6246
|
const inner = buildExpression(group.body, style);
|
|
6216
6247
|
|
|
6217
|
-
|
|
6218
|
-
const leftNode = new MathNode("mo", [makeText(group.left, group.mode)]);
|
|
6219
|
-
leftNode.setAttribute("fence", "true");
|
|
6220
|
-
leftNode.setAttribute("form", "prefix");
|
|
6221
|
-
if (group.left === "/" || group.left === "\u005C" || group.left.indexOf("arrow") > -1) {
|
|
6222
|
-
leftNode.setAttribute("stretchy", "true");
|
|
6223
|
-
}
|
|
6248
|
+
const leftNode = makeFenceMo(group.left, group.mode, "prefix", true);
|
|
6224
6249
|
inner.unshift(leftNode);
|
|
6225
6250
|
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6251
|
+
const rightNode = makeFenceMo(group.right, group.mode, "postfix", true);
|
|
6252
|
+
if (group.body.length > 0) {
|
|
6253
|
+
const lastElement = group.body[group.body.length - 1];
|
|
6254
|
+
if (lastElement.type === "color" && !lastElement.isTextColor) {
|
|
6255
|
+
rightNode.setAttribute("mathcolor", lastElement.color);
|
|
6256
|
+
}
|
|
6232
6257
|
}
|
|
6258
|
+
inner.push(rightNode);
|
|
6259
|
+
|
|
6260
|
+
return makeRow(inner);
|
|
6261
|
+
}
|
|
6262
|
+
});
|
|
6263
|
+
|
|
6264
|
+
defineFunction({
|
|
6265
|
+
type: "delimiter",
|
|
6266
|
+
names: Array.from(leftDelimiterNames),
|
|
6267
|
+
props: {
|
|
6268
|
+
numArgs: 0,
|
|
6269
|
+
allowedInText: true,
|
|
6270
|
+
allowedInMath: true,
|
|
6271
|
+
allowedInArgument: true
|
|
6272
|
+
},
|
|
6273
|
+
handler: ({ parser, funcName, token }) => {
|
|
6274
|
+
if (parser.mode === "text") {
|
|
6275
|
+
return {
|
|
6276
|
+
type: "textord",
|
|
6277
|
+
mode: "text",
|
|
6278
|
+
text: funcName,
|
|
6279
|
+
loc: token.loc
|
|
6280
|
+
}
|
|
6281
|
+
} else if (!parser.settings.wrapDelimiterPairs) {
|
|
6282
|
+
// Treat this token as an ordinary symbol.
|
|
6283
|
+
return {
|
|
6284
|
+
type: "atom",
|
|
6285
|
+
mode: "math",
|
|
6286
|
+
family: "open",
|
|
6287
|
+
loc: token.loc,
|
|
6288
|
+
text: funcName
|
|
6289
|
+
};
|
|
6290
|
+
}
|
|
6291
|
+
// Otherwise, try to wrap a pair of delimiters with an <mrow>.
|
|
6292
|
+
const rightDelim = leftToRight[funcName];
|
|
6293
|
+
// Parse the inner expression, looking for the corresponding right delimiter.
|
|
6294
|
+
const body = parser.parseExpression(false, rightDelim, false);
|
|
6295
|
+
const nextToken = parser.fetch().text;
|
|
6296
|
+
|
|
6297
|
+
if (nextToken !== rightDelim) {
|
|
6298
|
+
// We were unable to find a matching right delimiter.
|
|
6299
|
+
// Throw control back to renderToMathMLTree.
|
|
6300
|
+
// It will reparse the entire expression with wrapDelimiterPairs set to false.
|
|
6301
|
+
throw new ParseError("Unmatched delimiter");
|
|
6302
|
+
}
|
|
6303
|
+
parser.consume();
|
|
6304
|
+
|
|
6305
|
+
return {
|
|
6306
|
+
type: "delimiter",
|
|
6307
|
+
mode: parser.mode,
|
|
6308
|
+
body,
|
|
6309
|
+
left: funcName,
|
|
6310
|
+
right: rightDelim
|
|
6311
|
+
};
|
|
6312
|
+
},
|
|
6313
|
+
mathmlBuilder: (group, style) => {
|
|
6314
|
+
assertParsed(group);
|
|
6315
|
+
const inner = buildExpression(group.body, style);
|
|
6316
|
+
|
|
6317
|
+
const leftNode = makeFenceMo(group.left, group.mode, "prefix", false);
|
|
6318
|
+
inner.unshift(leftNode);
|
|
6319
|
+
|
|
6320
|
+
const rightNode = makeFenceMo(group.right, group.mode, "postfix", false);
|
|
6233
6321
|
if (group.body.length > 0) {
|
|
6234
6322
|
const lastElement = group.body[group.body.length - 1];
|
|
6235
6323
|
if (lastElement.type === "color" && !lastElement.isTextColor) {
|
|
6236
|
-
// \color is a switch. If the last element is of type "color" then
|
|
6237
|
-
// the user set the \color switch and left it on.
|
|
6238
|
-
// A \right delimiter turns the switch off, but the delimiter itself gets the color.
|
|
6239
6324
|
rightNode.setAttribute("mathcolor", lastElement.color);
|
|
6240
6325
|
}
|
|
6241
6326
|
}
|
|
@@ -6264,7 +6349,7 @@ var temml = (function () {
|
|
|
6264
6349
|
delim: delim.text
|
|
6265
6350
|
};
|
|
6266
6351
|
},
|
|
6267
|
-
mathmlBuilder: (group
|
|
6352
|
+
mathmlBuilder: (group) => {
|
|
6268
6353
|
const textNode = makeText(group.delim, group.mode);
|
|
6269
6354
|
const middleNode = new MathNode("mo", [textNode]);
|
|
6270
6355
|
middleNode.setAttribute("fence", "true");
|
|
@@ -6310,7 +6395,7 @@ var temml = (function () {
|
|
|
6310
6395
|
break
|
|
6311
6396
|
case "\\xcancel":
|
|
6312
6397
|
node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
|
|
6313
|
-
node.
|
|
6398
|
+
node.children.push(new MathNode("mrow", [], ["tml-cancel", "tml-xcancel"]));
|
|
6314
6399
|
break
|
|
6315
6400
|
// cancelto is handled in cancelto.js
|
|
6316
6401
|
case "\\longdiv":
|
|
@@ -6747,22 +6832,37 @@ var temml = (function () {
|
|
|
6747
6832
|
const stylArray = ["display", "text", "script", "scriptscript"];
|
|
6748
6833
|
const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 };
|
|
6749
6834
|
|
|
6835
|
+
const adjustStyle = (functionSize, originalStyle) => {
|
|
6836
|
+
// Figure out what style this fraction should be in based on the
|
|
6837
|
+
// function used
|
|
6838
|
+
let style = originalStyle;
|
|
6839
|
+
if (functionSize === "display") { //\tfrac or \cfrac
|
|
6840
|
+
// Get display style as a default.
|
|
6841
|
+
// If incoming style is sub/sup, use style.text() to get correct size.
|
|
6842
|
+
const newSize = style.level >= StyleLevel.SCRIPT ? StyleLevel.TEXT : StyleLevel.DISPLAY;
|
|
6843
|
+
style = style.withLevel(newSize);
|
|
6844
|
+
} else if (functionSize === "text" &&
|
|
6845
|
+
style.level === StyleLevel.DISPLAY) {
|
|
6846
|
+
// We're in a \tfrac but incoming style is displaystyle, so:
|
|
6847
|
+
style = style.withLevel(StyleLevel.TEXT);
|
|
6848
|
+
} else if (functionSize === "auto") {
|
|
6849
|
+
style = style.incrementLevel();
|
|
6850
|
+
} else if (functionSize === "script") {
|
|
6851
|
+
style = style.withLevel(StyleLevel.SCRIPT);
|
|
6852
|
+
} else if (functionSize === "scriptscript") {
|
|
6853
|
+
style = style.withLevel(StyleLevel.SCRIPTSCRIPT);
|
|
6854
|
+
}
|
|
6855
|
+
return style;
|
|
6856
|
+
};
|
|
6857
|
+
|
|
6750
6858
|
const mathmlBuilder$5 = (group, style) => {
|
|
6751
|
-
|
|
6752
|
-
// We may need that info for \mathchoice or for adjusting em dimensions.
|
|
6753
|
-
const childOptions = group.scriptLevel === "auto"
|
|
6754
|
-
? style.incrementLevel()
|
|
6755
|
-
: group.scriptLevel === "display"
|
|
6756
|
-
? style.withLevel(StyleLevel.TEXT)
|
|
6757
|
-
: group.scriptLevel === "text"
|
|
6758
|
-
? style.withLevel(StyleLevel.SCRIPT)
|
|
6759
|
-
: style.withLevel(StyleLevel.SCRIPTSCRIPT);
|
|
6859
|
+
style = adjustStyle(group.scriptLevel, style);
|
|
6760
6860
|
|
|
6761
6861
|
// Chromium (wrongly) continues to shrink fractions beyond scriptscriptlevel.
|
|
6762
6862
|
// So we check for levels that Chromium shrinks too small.
|
|
6763
6863
|
// If necessary, set an explicit fraction depth.
|
|
6764
|
-
const numer = buildGroup$1(group.numer,
|
|
6765
|
-
const denom = buildGroup$1(group.denom,
|
|
6864
|
+
const numer = buildGroup$1(group.numer, style);
|
|
6865
|
+
const denom = buildGroup$1(group.denom, style);
|
|
6766
6866
|
if (style.level === 3) {
|
|
6767
6867
|
numer.style.mathDepth = "2";
|
|
6768
6868
|
numer.setAttribute("scriptlevel", "2");
|
|
@@ -6815,6 +6915,7 @@ var temml = (function () {
|
|
|
6815
6915
|
defineFunction({
|
|
6816
6916
|
type: "genfrac",
|
|
6817
6917
|
names: [
|
|
6918
|
+
"\\cfrac",
|
|
6818
6919
|
"\\dfrac",
|
|
6819
6920
|
"\\frac",
|
|
6820
6921
|
"\\tfrac",
|
|
@@ -6838,6 +6939,7 @@ var temml = (function () {
|
|
|
6838
6939
|
let scriptLevel = "auto";
|
|
6839
6940
|
|
|
6840
6941
|
switch (funcName) {
|
|
6942
|
+
case "\\cfrac":
|
|
6841
6943
|
case "\\dfrac":
|
|
6842
6944
|
case "\\frac":
|
|
6843
6945
|
case "\\tfrac":
|
|
@@ -6864,15 +6966,10 @@ var temml = (function () {
|
|
|
6864
6966
|
throw new Error("Unrecognized genfrac command");
|
|
6865
6967
|
}
|
|
6866
6968
|
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
break;
|
|
6872
|
-
case "\\tfrac":
|
|
6873
|
-
case "\\tbinom":
|
|
6874
|
-
scriptLevel = "text";
|
|
6875
|
-
break;
|
|
6969
|
+
if (funcName === "\\cfrac" || funcName.startsWith("\\d")) {
|
|
6970
|
+
scriptLevel = "display";
|
|
6971
|
+
} else if (funcName.startsWith("\\t")) {
|
|
6972
|
+
scriptLevel = "text";
|
|
6876
6973
|
}
|
|
6877
6974
|
|
|
6878
6975
|
return {
|
|
@@ -6891,31 +6988,6 @@ var temml = (function () {
|
|
|
6891
6988
|
mathmlBuilder: mathmlBuilder$5
|
|
6892
6989
|
});
|
|
6893
6990
|
|
|
6894
|
-
defineFunction({
|
|
6895
|
-
type: "genfrac",
|
|
6896
|
-
names: ["\\cfrac"],
|
|
6897
|
-
props: {
|
|
6898
|
-
numArgs: 2
|
|
6899
|
-
},
|
|
6900
|
-
handler: ({ parser, funcName }, args) => {
|
|
6901
|
-
const numer = args[0];
|
|
6902
|
-
const denom = args[1];
|
|
6903
|
-
|
|
6904
|
-
return {
|
|
6905
|
-
type: "genfrac",
|
|
6906
|
-
mode: parser.mode,
|
|
6907
|
-
continued: true,
|
|
6908
|
-
numer,
|
|
6909
|
-
denom,
|
|
6910
|
-
hasBarLine: true,
|
|
6911
|
-
leftDelim: null,
|
|
6912
|
-
rightDelim: null,
|
|
6913
|
-
scriptLevel: "display",
|
|
6914
|
-
barSize: null
|
|
6915
|
-
};
|
|
6916
|
-
}
|
|
6917
|
-
});
|
|
6918
|
-
|
|
6919
6991
|
// Infix generalized fractions -- these are not rendered directly, but replaced
|
|
6920
6992
|
// immediately by one of the variants above.
|
|
6921
6993
|
defineFunction({
|
|
@@ -7744,8 +7816,16 @@ var temml = (function () {
|
|
|
7744
7816
|
const atom = arg.type === "ordgroup" && arg.body.length && arg.body.length === 1
|
|
7745
7817
|
? arg.body[0]
|
|
7746
7818
|
: arg;
|
|
7747
|
-
if (atom.type === "atom"
|
|
7748
|
-
|
|
7819
|
+
if (atom.type === "atom") {
|
|
7820
|
+
// BIN args are sometimes changed to OPEN, so check the original family.
|
|
7821
|
+
const family = arg.body.length > 0 && arg.body[0].text && symbols.math[arg.body[0].text]
|
|
7822
|
+
? symbols.math[arg.body[0].text].group
|
|
7823
|
+
: atom.family;
|
|
7824
|
+
if (family === "bin" || family === "rel") {
|
|
7825
|
+
return "m" + family;
|
|
7826
|
+
} else {
|
|
7827
|
+
return "mord";
|
|
7828
|
+
}
|
|
7749
7829
|
} else {
|
|
7750
7830
|
return "mord";
|
|
7751
7831
|
}
|
|
@@ -8316,6 +8396,14 @@ var temml = (function () {
|
|
|
8316
8396
|
if ((node.type === "mrow" || node.type === "mpadded") && node.children.length === 1 &&
|
|
8317
8397
|
node.children[0] instanceof MathNode) {
|
|
8318
8398
|
node = node.children[0];
|
|
8399
|
+
} else if (node.type === "mrow" && node.children.length === 2 &&
|
|
8400
|
+
node.children[0] instanceof MathNode &&
|
|
8401
|
+
node.children[1] instanceof MathNode &&
|
|
8402
|
+
node.children[1].type === "mspace" && !node.children[1].attributes.width &&
|
|
8403
|
+
node.children[1].children.length === 0) {
|
|
8404
|
+
// This is a workaround for a Firefox bug that applies spacing to
|
|
8405
|
+
// an <mi> with mathvariant="normal".
|
|
8406
|
+
node = node.children[0];
|
|
8319
8407
|
}
|
|
8320
8408
|
switch (node.type) {
|
|
8321
8409
|
case "mi":
|
|
@@ -9586,8 +9674,8 @@ var temml = (function () {
|
|
|
9586
9674
|
node.setAttribute("mathvariant", "normal");
|
|
9587
9675
|
if (text.text.length === 1) {
|
|
9588
9676
|
// A Firefox bug will apply spacing here, but there should be none. Fix it.
|
|
9589
|
-
|
|
9590
|
-
node
|
|
9677
|
+
const mspace = new MathNode("mspace", []);
|
|
9678
|
+
node = new MathNode("mrow", [node, mspace]);
|
|
9591
9679
|
}
|
|
9592
9680
|
}
|
|
9593
9681
|
return node
|
|
@@ -11124,7 +11212,7 @@ var temml = (function () {
|
|
|
11124
11212
|
* Parses an "expression", which is a list of atoms.
|
|
11125
11213
|
*
|
|
11126
11214
|
* `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
|
|
11127
|
-
* happens when functions have higher precedence
|
|
11215
|
+
* happens when functions have higher precedence than infix
|
|
11128
11216
|
* nodes in implicit parses.
|
|
11129
11217
|
*
|
|
11130
11218
|
* `breakOnTokenText`: The text of the token that the expression should end
|
|
@@ -11732,7 +11820,7 @@ var temml = (function () {
|
|
|
11732
11820
|
) {
|
|
11733
11821
|
const firstToken = this.fetch();
|
|
11734
11822
|
const text = firstToken.text;
|
|
11735
|
-
|
|
11823
|
+
if (name === "argument to '\\left'") { return this.parseSymbol() }
|
|
11736
11824
|
let result;
|
|
11737
11825
|
// Try to parse an open brace or \begingroup
|
|
11738
11826
|
if (text === "{" || text === "\\begingroup" || text === "\\toggle") {
|
|
@@ -11765,6 +11853,12 @@ var temml = (function () {
|
|
|
11765
11853
|
result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol();
|
|
11766
11854
|
if (result == null && text[0] === "\\" &&
|
|
11767
11855
|
!Object.prototype.hasOwnProperty.call(implicitCommands, text )) {
|
|
11856
|
+
if (this.settings.throwOnError) {
|
|
11857
|
+
throw new ParseError("Unsupported function name: " + text, firstToken);
|
|
11858
|
+
}
|
|
11859
|
+
// For people getting dyanamically rendered math, it's better to
|
|
11860
|
+
// show the unsupported command in red rather than panicking for every
|
|
11861
|
+
// partially written expression.
|
|
11768
11862
|
result = this.formatUnsupportedCmd(text);
|
|
11769
11863
|
this.consume();
|
|
11770
11864
|
}
|
|
@@ -11873,7 +11967,8 @@ var temml = (function () {
|
|
|
11873
11967
|
let symbol;
|
|
11874
11968
|
if (symbols[this.mode][text]) {
|
|
11875
11969
|
let group = symbols[this.mode][text].group;
|
|
11876
|
-
if (group === "bin" &&
|
|
11970
|
+
if (group === "bin" &&
|
|
11971
|
+
(binLeftCancellers.includes(this.prevAtomType) || this.prevAtomType === "")) {
|
|
11877
11972
|
// Change from a binary operator to a unary (prefix) operator
|
|
11878
11973
|
group = "open";
|
|
11879
11974
|
}
|
|
@@ -11969,11 +12064,27 @@ var temml = (function () {
|
|
|
11969
12064
|
if (!(typeof toParse === "string" || toParse instanceof String)) {
|
|
11970
12065
|
throw new TypeError("Temml can only parse string typed expression")
|
|
11971
12066
|
}
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
12067
|
+
let tree;
|
|
12068
|
+
let parser;
|
|
12069
|
+
try {
|
|
12070
|
+
parser = new Parser(toParse, settings);
|
|
12071
|
+
// Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
|
|
12072
|
+
delete parser.gullet.macros.current["\\df@tag"];
|
|
11975
12073
|
|
|
11976
|
-
|
|
12074
|
+
tree = parser.parse();
|
|
12075
|
+
} catch (error) {
|
|
12076
|
+
if (error.toString() === "ParseError: Unmatched delimiter") {
|
|
12077
|
+
// Abandon the attempt to wrap delimiter pairs in an <mrow>.
|
|
12078
|
+
// Try again, and put each delimiter into an <mo> element.
|
|
12079
|
+
settings.wrapDelimiterPairs = false;
|
|
12080
|
+
parser = new Parser(toParse, settings);
|
|
12081
|
+
// Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
|
|
12082
|
+
delete parser.gullet.macros.current["\\df@tag"];
|
|
12083
|
+
tree = parser.parse();
|
|
12084
|
+
} else {
|
|
12085
|
+
throw error;
|
|
12086
|
+
}
|
|
12087
|
+
}
|
|
11977
12088
|
|
|
11978
12089
|
// LaTeX ignores a \tag placed outside an AMS environment.
|
|
11979
12090
|
if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) {
|
|
@@ -12150,7 +12261,7 @@ var temml = (function () {
|
|
|
12150
12261
|
* https://mit-license.org/
|
|
12151
12262
|
*/
|
|
12152
12263
|
|
|
12153
|
-
const version = "0.
|
|
12264
|
+
const version = "0.13.02";
|
|
12154
12265
|
|
|
12155
12266
|
function postProcess(block) {
|
|
12156
12267
|
const labelMap = {};
|