temml 0.10.20 → 0.10.22
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Temml-Asana.css +0 -4
- package/dist/Temml-STIX2.css +0 -4
- package/dist/temml.cjs +126 -99
- package/dist/temml.d.ts +1 -1
- package/dist/temml.js +126 -99
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +126 -99
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +1 -1
- package/src/Parser.js +8 -1
- package/src/functions/color.js +2 -9
- package/src/functions/delimsizing.js +24 -19
- package/src/functions/font.js +1 -1
- package/src/functions/mclass.js +3 -0
- package/src/functions/reflect.js +24 -0
- package/src/functions/sizing.js +1 -1
- package/src/functions/styling.js +1 -1
- package/src/functions/symbolsOrd.js +0 -2
- package/src/functions.js +1 -0
- package/src/linebreaking.js +3 -2
- package/src/macros.js +49 -53
- package/src/postProcess.js +1 -1
- package/src/replace.js +8 -8
- package/src/symbols.js +4 -1
package/dist/temml.mjs
CHANGED
@@ -934,7 +934,8 @@ defineSymbol(math, textord, "\u2135", "\\aleph", true);
|
|
934
934
|
defineSymbol(math, textord, "\u2200", "\\forall", true);
|
935
935
|
defineSymbol(math, textord, "\u210f", "\\hbar", true);
|
936
936
|
defineSymbol(math, textord, "\u2203", "\\exists", true);
|
937
|
-
|
937
|
+
// ∇ is actually a unary operator, not binary. But this works.
|
938
|
+
defineSymbol(math, bin, "\u2207", "\\nabla", true);
|
938
939
|
defineSymbol(math, textord, "\u266d", "\\flat", true);
|
939
940
|
defineSymbol(math, textord, "\u2113", "\\ell", true);
|
940
941
|
defineSymbol(math, textord, "\u266e", "\\natural", true);
|
@@ -988,6 +989,7 @@ defineSymbol(math, bin, "\u2021", "\\ddagger");
|
|
988
989
|
defineSymbol(math, bin, "\u2240", "\\wr", true);
|
989
990
|
defineSymbol(math, bin, "\u2a3f", "\\amalg");
|
990
991
|
defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath
|
992
|
+
defineSymbol(math, bin, "\u2AFD", "\\sslash", true); // from stmaryrd
|
991
993
|
|
992
994
|
// Arrow Symbols
|
993
995
|
defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true);
|
@@ -1406,6 +1408,7 @@ defineSymbol(math, mathord, "\u2aeb", "\\Bot");
|
|
1406
1408
|
defineSymbol(math, bin, "\u2217", "\u2217", true);
|
1407
1409
|
defineSymbol(math, bin, "+", "+");
|
1408
1410
|
defineSymbol(math, bin, "*", "*");
|
1411
|
+
defineSymbol(math, bin, "\u2044", "/", true);
|
1409
1412
|
defineSymbol(math, bin, "\u2044", "\u2044");
|
1410
1413
|
defineSymbol(math, bin, "\u2212", "-", true);
|
1411
1414
|
defineSymbol(math, bin, "\u22c5", "\\cdot", true);
|
@@ -1862,7 +1865,8 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
|
|
1862
1865
|
continue
|
1863
1866
|
}
|
1864
1867
|
block.push(node);
|
1865
|
-
if (node.type && node.type === "mo" && node.children.length === 1
|
1868
|
+
if (node.type && node.type === "mo" && node.children.length === 1 &&
|
1869
|
+
!Object.hasOwn(node.attributes, "movablelimits")) {
|
1866
1870
|
const ch = node.children[0].text;
|
1867
1871
|
if (openDelims.indexOf(ch) > -1) {
|
1868
1872
|
level += 1;
|
@@ -1877,7 +1881,7 @@ function setLineBreaks(expression, wrapMode, isDisplayMode) {
|
|
1877
1881
|
mrows.push(element);
|
1878
1882
|
block = [node];
|
1879
1883
|
}
|
1880
|
-
} else if (level === 0 && wrapMode === "tex") {
|
1884
|
+
} else if (level === 0 && wrapMode === "tex" && ch !== "∇") {
|
1881
1885
|
// Check if the following node is a \nobreak text node, e.g. "~""
|
1882
1886
|
const next = i < expression.length - 1 ? expression[i + 1] : null;
|
1883
1887
|
let glueIsFreeOfNobreak = true;
|
@@ -3245,7 +3249,7 @@ defineFunction({
|
|
3245
3249
|
allowedInText: true,
|
3246
3250
|
argTypes: ["raw", "raw"]
|
3247
3251
|
},
|
3248
|
-
handler({ parser, token }, args, optArgs) {
|
3252
|
+
handler({ parser, breakOnTokenText, token }, args, optArgs) {
|
3249
3253
|
const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string;
|
3250
3254
|
let color = "";
|
3251
3255
|
if (model) {
|
@@ -3255,15 +3259,8 @@ defineFunction({
|
|
3255
3259
|
color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token);
|
3256
3260
|
}
|
3257
3261
|
|
3258
|
-
// Set macro \current@color in current namespace to store the current
|
3259
|
-
// color, mimicking the behavior of color.sty.
|
3260
|
-
// This is currently used just to correctly color a \right
|
3261
|
-
// that follows a \color command.
|
3262
|
-
parser.gullet.macros.set("\\current@color", color);
|
3263
|
-
|
3264
3262
|
// Parse out the implicit body that should be colored.
|
3265
|
-
|
3266
|
-
const body = parser.parseExpression(true, "\\color");
|
3263
|
+
const body = parser.parseExpression(true, breakOnTokenText, true);
|
3267
3264
|
|
3268
3265
|
return {
|
3269
3266
|
type: "color",
|
@@ -3705,17 +3702,13 @@ const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
|
|
3705
3702
|
|
3706
3703
|
// Delimiter functions
|
3707
3704
|
function checkDelimiter(delim, context) {
|
3708
|
-
if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") {
|
3709
|
-
// Recover "/" from the zero spacing group. (See macros.js)
|
3710
|
-
delim = { type: "textord", text: "/", mode: "math" };
|
3711
|
-
}
|
3712
3705
|
const symDelim = checkSymbolNodeType(delim);
|
3713
3706
|
if (symDelim && delimiters.includes(symDelim.text)) {
|
3714
3707
|
// If a character is not in the MathML operator dictionary, it will not stretch.
|
3715
3708
|
// Replace such characters w/characters that will stretch.
|
3709
|
+
if (["/", "\u2044"].includes(symDelim.text)) { symDelim.text = "\u2215"; }
|
3716
3710
|
if (["<", "\\lt"].includes(symDelim.text)) { symDelim.text = "⟨"; }
|
3717
3711
|
if ([">", "\\gt"].includes(symDelim.text)) { symDelim.text = "⟩"; }
|
3718
|
-
if (symDelim.text === "/") { symDelim.text = "\u2215"; }
|
3719
3712
|
if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; }
|
3720
3713
|
return symDelim;
|
3721
3714
|
} else if (symDelim) {
|
@@ -3803,18 +3796,10 @@ defineFunction({
|
|
3803
3796
|
argTypes: ["primitive"]
|
3804
3797
|
},
|
3805
3798
|
handler: (context, args) => {
|
3806
|
-
// \left case below triggers parsing of \right in
|
3807
|
-
// `const right = parser.parseFunction();`
|
3808
|
-
// uses this return value.
|
3809
|
-
const color = context.parser.gullet.macros.get("\\current@color");
|
3810
|
-
if (color && typeof color !== "string") {
|
3811
|
-
throw new ParseError("\\current@color set to non-string in \\right");
|
3812
|
-
}
|
3813
3799
|
return {
|
3814
3800
|
type: "leftright-right",
|
3815
3801
|
mode: context.parser.mode,
|
3816
|
-
delim: checkDelimiter(args[0], context).text
|
3817
|
-
color // undefined if not set via \color
|
3802
|
+
delim: checkDelimiter(args[0], context).text
|
3818
3803
|
};
|
3819
3804
|
}
|
3820
3805
|
});
|
@@ -3832,8 +3817,26 @@ defineFunction({
|
|
3832
3817
|
const parser = context.parser;
|
3833
3818
|
// Parse out the implicit body
|
3834
3819
|
++parser.leftrightDepth;
|
3835
|
-
// parseExpression stops before '\\right'
|
3836
|
-
|
3820
|
+
// parseExpression stops before '\\right' or `\\middle`
|
3821
|
+
let body = parser.parseExpression(false, null, true);
|
3822
|
+
let nextToken = parser.fetch();
|
3823
|
+
while (nextToken.text === "\\middle") {
|
3824
|
+
// `\middle`, from the ε-TeX package, ends one group and starts another group.
|
3825
|
+
// We had to parse this expression with `breakOnMiddle` enabled in order
|
3826
|
+
// to get TeX-compliant parsing of \over.
|
3827
|
+
// But we do not want, at this point, to end on \middle, so continue
|
3828
|
+
// to parse until we fetch a `\right`.
|
3829
|
+
parser.consume();
|
3830
|
+
const middle = parser.fetch().text;
|
3831
|
+
if (!symbols.math[middle]) {
|
3832
|
+
throw new ParseError(`Invalid delimiter '${middle}' after '\\middle'`);
|
3833
|
+
}
|
3834
|
+
checkDelimiter({ type: "atom", mode: "math", text: middle }, { funcName: "\\middle" });
|
3835
|
+
body.push({ type: "middle", mode: "math", delim: middle });
|
3836
|
+
parser.consume();
|
3837
|
+
body = body.concat(parser.parseExpression(false, null, true));
|
3838
|
+
nextToken = parser.fetch();
|
3839
|
+
}
|
3837
3840
|
--parser.leftrightDepth;
|
3838
3841
|
// Check the next token
|
3839
3842
|
parser.expect("\\right", false);
|
@@ -3843,8 +3846,7 @@ defineFunction({
|
|
3843
3846
|
mode: parser.mode,
|
3844
3847
|
body,
|
3845
3848
|
left: delim.text,
|
3846
|
-
right: right.delim
|
3847
|
-
rightColor: right.color
|
3849
|
+
right: right.delim
|
3848
3850
|
};
|
3849
3851
|
},
|
3850
3852
|
mathmlBuilder: (group, style) => {
|
@@ -3867,7 +3869,6 @@ defineFunction({
|
|
3867
3869
|
if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
|
3868
3870
|
rightNode.setAttribute("stretchy", "true");
|
3869
3871
|
}
|
3870
|
-
if (group.rightColor) { rightNode.style.color = group.rightColor; }
|
3871
3872
|
inner.push(rightNode);
|
3872
3873
|
|
3873
3874
|
return makeRow(inner);
|
@@ -5210,7 +5211,7 @@ defineFunction({
|
|
5210
5211
|
},
|
5211
5212
|
handler: ({ parser, funcName, breakOnTokenText }, args) => {
|
5212
5213
|
const { mode } = parser;
|
5213
|
-
const body = parser.parseExpression(true, breakOnTokenText);
|
5214
|
+
const body = parser.parseExpression(true, breakOnTokenText, true);
|
5214
5215
|
const fontStyle = `math${funcName.slice(1)}`;
|
5215
5216
|
|
5216
5217
|
return {
|
@@ -6171,6 +6172,9 @@ function mathmlBuilder$3(group, style) {
|
|
6171
6172
|
if (group.isCharacterBox || inner[0].type === "mathord") {
|
6172
6173
|
node = inner[0];
|
6173
6174
|
node.type = "mi";
|
6175
|
+
if (node.children.length === 1 && node.children[0].text && node.children[0].text === "∇") {
|
6176
|
+
node.setAttribute("mathvariant", "normal");
|
6177
|
+
}
|
6174
6178
|
} else {
|
6175
6179
|
node = new mathMLTree.MathNode("mi", inner);
|
6176
6180
|
}
|
@@ -7158,6 +7162,28 @@ defineFunction({
|
|
7158
7162
|
}
|
7159
7163
|
});
|
7160
7164
|
|
7165
|
+
defineFunction({
|
7166
|
+
type: "reflect",
|
7167
|
+
names: ["\\reflectbox"],
|
7168
|
+
props: {
|
7169
|
+
numArgs: 1,
|
7170
|
+
argTypes: ["hbox"],
|
7171
|
+
allowedInText: true
|
7172
|
+
},
|
7173
|
+
handler({ parser }, args) {
|
7174
|
+
return {
|
7175
|
+
type: "reflect",
|
7176
|
+
mode: parser.mode,
|
7177
|
+
body: args[0]
|
7178
|
+
};
|
7179
|
+
},
|
7180
|
+
mathmlBuilder(group, style) {
|
7181
|
+
const node = buildGroup$1(group.body, style);
|
7182
|
+
node.style.transform = "scaleX(-1)";
|
7183
|
+
return node
|
7184
|
+
}
|
7185
|
+
});
|
7186
|
+
|
7161
7187
|
defineFunction({
|
7162
7188
|
type: "internal",
|
7163
7189
|
names: ["\\relax"],
|
@@ -7263,7 +7289,7 @@ defineFunction({
|
|
7263
7289
|
// eslint-disable-next-line no-console
|
7264
7290
|
console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`);
|
7265
7291
|
}
|
7266
|
-
const body = parser.parseExpression(false, breakOnTokenText);
|
7292
|
+
const body = parser.parseExpression(false, breakOnTokenText, true);
|
7267
7293
|
return {
|
7268
7294
|
type: "sizing",
|
7269
7295
|
mode: parser.mode,
|
@@ -7396,7 +7422,7 @@ defineFunction({
|
|
7396
7422
|
},
|
7397
7423
|
handler({ breakOnTokenText, funcName, parser }, args) {
|
7398
7424
|
// parse out the implicit body
|
7399
|
-
const body = parser.parseExpression(true, breakOnTokenText);
|
7425
|
+
const body = parser.parseExpression(true, breakOnTokenText, true);
|
7400
7426
|
|
7401
7427
|
const scriptLevel = funcName.slice(1, funcName.length - 5);
|
7402
7428
|
return {
|
@@ -7827,22 +7853,22 @@ const offset = Object.freeze({
|
|
7827
7853
|
"sans-serif-bold-italic": ch => { return 0x1D5F5 },
|
7828
7854
|
"monospace": ch => { return 0x1D629 }
|
7829
7855
|
},
|
7830
|
-
upperCaseGreek: { // A-Ω
|
7856
|
+
upperCaseGreek: { // A-Ω
|
7831
7857
|
"normal": ch => { return 0 },
|
7832
|
-
"bold": ch => { return
|
7833
|
-
"italic": ch => { return
|
7858
|
+
"bold": ch => { return 0x1D317 },
|
7859
|
+
"italic": ch => { return 0x1D351 },
|
7834
7860
|
// \boldsymbol actually returns upright bold for upperCaseGreek
|
7835
|
-
"bold-italic": ch => { return
|
7861
|
+
"bold-italic": ch => { return 0x1D317 },
|
7836
7862
|
"script": ch => { return 0 },
|
7837
7863
|
"script-bold": ch => { return 0 },
|
7838
7864
|
"fraktur": ch => { return 0 },
|
7839
7865
|
"fraktur-bold": ch => { return 0 },
|
7840
7866
|
"double-struck": ch => { return 0 },
|
7841
7867
|
// Unicode has no code points for regular-weight san-serif Greek. Use bold.
|
7842
|
-
"sans-serif": ch => { return
|
7843
|
-
"sans-serif-bold": ch => { return
|
7868
|
+
"sans-serif": ch => { return 0x1D3C5 },
|
7869
|
+
"sans-serif-bold": ch => { return 0x1D3C5 },
|
7844
7870
|
"sans-serif-italic": ch => { return 0 },
|
7845
|
-
"sans-serif-bold-italic": ch => { return
|
7871
|
+
"sans-serif-bold-italic": ch => { return 0x1D3FF },
|
7846
7872
|
"monospace": ch => { return 0 }
|
7847
7873
|
},
|
7848
7874
|
lowerCaseGreek: { // α-ω
|
@@ -7902,7 +7928,7 @@ const variantChar = (ch, variant) => {
|
|
7902
7928
|
? "upperCaseLatin"
|
7903
7929
|
: 0x60 < codePoint && codePoint < 0x7b
|
7904
7930
|
? "lowerCaseLatin"
|
7905
|
-
: (0x390 < codePoint && codePoint < 0x3AA)
|
7931
|
+
: (0x390 < codePoint && codePoint < 0x3AA)
|
7906
7932
|
? "upperCaseGreek"
|
7907
7933
|
: 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5"
|
7908
7934
|
? "lowerCaseGreek"
|
@@ -8031,8 +8057,6 @@ defineFunctionBuilders({
|
|
8031
8057
|
node = new mathMLTree.MathNode("mi", [text]);
|
8032
8058
|
if (text.text === origText && latinRegEx.test(origText)) {
|
8033
8059
|
node.setAttribute("mathvariant", "italic");
|
8034
|
-
} else if (text.text === "∇" && variant === "normal") {
|
8035
|
-
node.setAttribute("mathvariant", "normal");
|
8036
8060
|
}
|
8037
8061
|
}
|
8038
8062
|
return node
|
@@ -8669,6 +8693,24 @@ defineMacro("\\char", function(context) {
|
|
8669
8693
|
return `\\@char{${number}}`;
|
8670
8694
|
});
|
8671
8695
|
|
8696
|
+
function recreateArgStr(context) {
|
8697
|
+
// Recreate the macro's original argument string from the array of parse tokens.
|
8698
|
+
const tokens = context.consumeArgs(1)[0];
|
8699
|
+
let str = "";
|
8700
|
+
let expectedLoc = tokens[tokens.length - 1].loc.start;
|
8701
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
8702
|
+
const actualLoc = tokens[i].loc.start;
|
8703
|
+
if (actualLoc > expectedLoc) {
|
8704
|
+
// context.consumeArgs has eaten a space.
|
8705
|
+
str += " ";
|
8706
|
+
expectedLoc = actualLoc;
|
8707
|
+
}
|
8708
|
+
str += tokens[i].text;
|
8709
|
+
expectedLoc += tokens[i].text.length;
|
8710
|
+
}
|
8711
|
+
return str
|
8712
|
+
}
|
8713
|
+
|
8672
8714
|
// The Latin Modern font renders <mi>√</mi> at the wrong vertical alignment.
|
8673
8715
|
// This macro provides a better rendering.
|
8674
8716
|
defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
|
@@ -8676,10 +8718,6 @@ defineMacro("\\surd", '\\sqrt{\\vphantom{|}}');
|
|
8676
8718
|
// See comment for \oplus in symbols.js.
|
8677
8719
|
defineMacro("\u2295", "\\oplus");
|
8678
8720
|
|
8679
|
-
// Per TeXbook p.122, "/" gets zero operator spacing.
|
8680
|
-
// And MDN recommends using U+2044 instead of / for inline
|
8681
|
-
defineMacro("/", "{\u2044}");
|
8682
|
-
|
8683
8721
|
// Since Temml has no \par, ignore \long.
|
8684
8722
|
defineMacro("\\long", "");
|
8685
8723
|
|
@@ -9057,6 +9095,11 @@ defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
|
|
9057
9095
|
defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
|
9058
9096
|
defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}");
|
9059
9097
|
|
9098
|
+
//////////////////////////////////////////////////////////////////////
|
9099
|
+
// MnSymbol.sty
|
9100
|
+
|
9101
|
+
defineMacro("\\leftmodels", "\\mathop{\\reflectbox{$\\models$}}");
|
9102
|
+
|
9060
9103
|
//////////////////////////////////////////////////////////////////////
|
9061
9104
|
// braket.sty
|
9062
9105
|
// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
|
@@ -9066,56 +9109,33 @@ defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
|
|
9066
9109
|
defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
|
9067
9110
|
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
9068
9111
|
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
9069
|
-
|
9070
|
-
|
9071
|
-
const
|
9072
|
-
const
|
9073
|
-
|
9074
|
-
const oldMiddle = context.macros.get("|");
|
9075
|
-
const oldMiddleDouble = context.macros.get("\\|");
|
9076
|
-
context.macros.beginGroup();
|
9077
|
-
const midMacro = (double) => (context) => {
|
9078
|
-
if (one) {
|
9079
|
-
// Only modify the first instance of | or \|
|
9080
|
-
context.macros.set("|", oldMiddle);
|
9081
|
-
if (middleDouble.length) {
|
9082
|
-
context.macros.set("\\|", oldMiddleDouble);
|
9083
|
-
}
|
9084
|
-
}
|
9085
|
-
let doubled = double;
|
9086
|
-
if (!double && middleDouble.length) {
|
9087
|
-
// Mimic \@ifnextchar
|
9088
|
-
const nextToken = context.future();
|
9089
|
-
if (nextToken.text === "|") {
|
9090
|
-
context.popToken();
|
9091
|
-
doubled = true;
|
9092
|
-
}
|
9093
|
-
}
|
9094
|
-
return {
|
9095
|
-
tokens: doubled ? middleDouble : middle,
|
9096
|
-
numArgs: 0
|
9097
|
-
};
|
9098
|
-
};
|
9099
|
-
context.macros.set("|", midMacro(false));
|
9100
|
-
if (middleDouble.length) {
|
9101
|
-
context.macros.set("\\|", midMacro(true));
|
9102
|
-
}
|
9103
|
-
const arg = context.consumeArg().tokens;
|
9104
|
-
const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed
|
9105
|
-
context.macros.endGroup();
|
9106
|
-
return {
|
9107
|
-
tokens: expanded.reverse(),
|
9108
|
-
numArgs: 0
|
9109
|
-
};
|
9112
|
+
// A helper for \Braket and \Set
|
9113
|
+
const replaceVert = (argStr, match) => {
|
9114
|
+
const ch = match[0] === "|" ? "\\vert" : "\\Vert";
|
9115
|
+
const replaceStr = `}\\,\\middle${ch}\\,{`;
|
9116
|
+
return argStr.slice(0, match.index) + replaceStr + argStr.slice(match.index + match[0].length)
|
9110
9117
|
};
|
9111
|
-
defineMacro("\\
|
9112
|
-
|
9113
|
-
|
9114
|
-
|
9115
|
-
|
9116
|
-
|
9117
|
-
|
9118
|
-
|
9118
|
+
defineMacro("\\Braket", function(context) {
|
9119
|
+
let argStr = recreateArgStr(context);
|
9120
|
+
const regEx = /\|\||\||\\\|/g;
|
9121
|
+
let match;
|
9122
|
+
while ((match = regEx.exec(argStr)) !== null) {
|
9123
|
+
argStr = replaceVert(argStr, match);
|
9124
|
+
}
|
9125
|
+
return "\\left\\langle{" + argStr + "}\\right\\rangle"
|
9126
|
+
});
|
9127
|
+
defineMacro("\\Set", function(context) {
|
9128
|
+
let argStr = recreateArgStr(context);
|
9129
|
+
const match = /\|\||\||\\\|/.exec(argStr);
|
9130
|
+
if (match) {
|
9131
|
+
argStr = replaceVert(argStr, match);
|
9132
|
+
}
|
9133
|
+
return "\\left\\{\\:{" + argStr + "}\\:\\right\\}"
|
9134
|
+
});
|
9135
|
+
defineMacro("\\set", function(context) {
|
9136
|
+
const argStr = recreateArgStr(context);
|
9137
|
+
return "\\{{" + argStr.replace(/\|/, "}\\mid{") + "}\\}"
|
9138
|
+
});
|
9119
9139
|
|
9120
9140
|
//////////////////////////////////////////////////////////////////////
|
9121
9141
|
// actuarialangle.dtx
|
@@ -12164,8 +12184,12 @@ class Parser {
|
|
12164
12184
|
* `breakOnTokenText`: The text of the token that the expression should end
|
12165
12185
|
* with, or `null` if something else should end the
|
12166
12186
|
* expression.
|
12187
|
+
*
|
12188
|
+
* `breakOnMiddle`: \color, \over, and old styling functions work on an implicit group.
|
12189
|
+
* These groups end just before the usual tokens, but they also
|
12190
|
+
* end just before `\middle`.
|
12167
12191
|
*/
|
12168
|
-
parseExpression(breakOnInfix, breakOnTokenText) {
|
12192
|
+
parseExpression(breakOnInfix, breakOnTokenText, breakOnMiddle) {
|
12169
12193
|
const body = [];
|
12170
12194
|
// Keep adding atoms to the body until we can't parse any more atoms (either
|
12171
12195
|
// we reached the end, a }, or a \right)
|
@@ -12181,6 +12205,9 @@ class Parser {
|
|
12181
12205
|
if (breakOnTokenText && lex.text === breakOnTokenText) {
|
12182
12206
|
break;
|
12183
12207
|
}
|
12208
|
+
if (breakOnMiddle && lex.text === "\\middle") {
|
12209
|
+
break
|
12210
|
+
}
|
12184
12211
|
if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
|
12185
12212
|
break;
|
12186
12213
|
}
|
@@ -13159,7 +13186,7 @@ class Style {
|
|
13159
13186
|
* https://mit-license.org/
|
13160
13187
|
*/
|
13161
13188
|
|
13162
|
-
const version = "0.10.
|
13189
|
+
const version = "0.10.22";
|
13163
13190
|
|
13164
13191
|
function postProcess(block) {
|
13165
13192
|
const labelMap = {};
|
package/dist/temmlPostProcess.js
CHANGED
package/package.json
CHANGED
package/src/Parser.js
CHANGED
@@ -179,8 +179,12 @@ export default class Parser {
|
|
179
179
|
* `breakOnTokenText`: The text of the token that the expression should end
|
180
180
|
* with, or `null` if something else should end the
|
181
181
|
* expression.
|
182
|
+
*
|
183
|
+
* `breakOnMiddle`: \color, \over, and old styling functions work on an implicit group.
|
184
|
+
* These groups end just before the usual tokens, but they also
|
185
|
+
* end just before `\middle`.
|
182
186
|
*/
|
183
|
-
parseExpression(breakOnInfix, breakOnTokenText) {
|
187
|
+
parseExpression(breakOnInfix, breakOnTokenText, breakOnMiddle) {
|
184
188
|
const body = [];
|
185
189
|
// Keep adding atoms to the body until we can't parse any more atoms (either
|
186
190
|
// we reached the end, a }, or a \right)
|
@@ -196,6 +200,9 @@ export default class Parser {
|
|
196
200
|
if (breakOnTokenText && lex.text === breakOnTokenText) {
|
197
201
|
break;
|
198
202
|
}
|
203
|
+
if (breakOnMiddle && lex.text === "\\middle") {
|
204
|
+
break
|
205
|
+
}
|
199
206
|
if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
|
200
207
|
break;
|
201
208
|
}
|
package/src/functions/color.js
CHANGED
@@ -201,7 +201,7 @@ defineFunction({
|
|
201
201
|
allowedInText: true,
|
202
202
|
argTypes: ["raw", "raw"]
|
203
203
|
},
|
204
|
-
handler({ parser, token }, args, optArgs) {
|
204
|
+
handler({ parser, breakOnTokenText, token }, args, optArgs) {
|
205
205
|
const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string
|
206
206
|
let color = ""
|
207
207
|
if (model) {
|
@@ -211,15 +211,8 @@ defineFunction({
|
|
211
211
|
color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token)
|
212
212
|
}
|
213
213
|
|
214
|
-
// Set macro \current@color in current namespace to store the current
|
215
|
-
// color, mimicking the behavior of color.sty.
|
216
|
-
// This is currently used just to correctly color a \right
|
217
|
-
// that follows a \color command.
|
218
|
-
parser.gullet.macros.set("\\current@color", color)
|
219
|
-
|
220
214
|
// Parse out the implicit body that should be colored.
|
221
|
-
|
222
|
-
const body = parser.parseExpression(true, "\\color")
|
215
|
+
const body = parser.parseExpression(true, breakOnTokenText, true)
|
223
216
|
|
224
217
|
return {
|
225
218
|
type: "color",
|
@@ -4,6 +4,7 @@ import ParseError from "../ParseError";
|
|
4
4
|
import { assertNodeType, checkSymbolNodeType } from "../parseNode";
|
5
5
|
|
6
6
|
import * as mml from "../buildMathML";
|
7
|
+
import symbols from "../symbols";
|
7
8
|
|
8
9
|
// Extra data needed for the delimiter handler down below
|
9
10
|
export const delimiterSizes = {
|
@@ -113,17 +114,13 @@ const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
|
|
113
114
|
|
114
115
|
// Delimiter functions
|
115
116
|
function checkDelimiter(delim, context) {
|
116
|
-
if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") {
|
117
|
-
// Recover "/" from the zero spacing group. (See macros.js)
|
118
|
-
delim = { type: "textord", text: "/", mode: "math" }
|
119
|
-
}
|
120
117
|
const symDelim = checkSymbolNodeType(delim)
|
121
118
|
if (symDelim && delimiters.includes(symDelim.text)) {
|
122
119
|
// If a character is not in the MathML operator dictionary, it will not stretch.
|
123
120
|
// Replace such characters w/characters that will stretch.
|
121
|
+
if (["/", "\u2044"].includes(symDelim.text)) { symDelim.text = "\u2215" }
|
124
122
|
if (["<", "\\lt"].includes(symDelim.text)) { symDelim.text = "⟨" }
|
125
123
|
if ([">", "\\gt"].includes(symDelim.text)) { symDelim.text = "⟩" }
|
126
|
-
if (symDelim.text === "/") { symDelim.text = "\u2215" }
|
127
124
|
if (symDelim.text === "\\backslash") { symDelim.text = "\u2216" }
|
128
125
|
return symDelim;
|
129
126
|
} else if (symDelim) {
|
@@ -211,18 +208,10 @@ defineFunction({
|
|
211
208
|
argTypes: ["primitive"]
|
212
209
|
},
|
213
210
|
handler: (context, args) => {
|
214
|
-
// \left case below triggers parsing of \right in
|
215
|
-
// `const right = parser.parseFunction();`
|
216
|
-
// uses this return value.
|
217
|
-
const color = context.parser.gullet.macros.get("\\current@color");
|
218
|
-
if (color && typeof color !== "string") {
|
219
|
-
throw new ParseError("\\current@color set to non-string in \\right");
|
220
|
-
}
|
221
211
|
return {
|
222
212
|
type: "leftright-right",
|
223
213
|
mode: context.parser.mode,
|
224
|
-
delim: checkDelimiter(args[0], context).text
|
225
|
-
color // undefined if not set via \color
|
214
|
+
delim: checkDelimiter(args[0], context).text
|
226
215
|
};
|
227
216
|
}
|
228
217
|
});
|
@@ -240,8 +229,26 @@ defineFunction({
|
|
240
229
|
const parser = context.parser;
|
241
230
|
// Parse out the implicit body
|
242
231
|
++parser.leftrightDepth;
|
243
|
-
// parseExpression stops before '\\right'
|
244
|
-
|
232
|
+
// parseExpression stops before '\\right' or `\\middle`
|
233
|
+
let body = parser.parseExpression(false, null, true)
|
234
|
+
let nextToken = parser.fetch()
|
235
|
+
while (nextToken.text === "\\middle") {
|
236
|
+
// `\middle`, from the ε-TeX package, ends one group and starts another group.
|
237
|
+
// We had to parse this expression with `breakOnMiddle` enabled in order
|
238
|
+
// to get TeX-compliant parsing of \over.
|
239
|
+
// But we do not want, at this point, to end on \middle, so continue
|
240
|
+
// to parse until we fetch a `\right`.
|
241
|
+
parser.consume()
|
242
|
+
const middle = parser.fetch().text
|
243
|
+
if (!symbols.math[middle]) {
|
244
|
+
throw new ParseError(`Invalid delimiter '${middle}' after '\\middle'`);
|
245
|
+
}
|
246
|
+
checkDelimiter({ type: "atom", mode: "math", text: middle }, { funcName: "\\middle" })
|
247
|
+
body.push({ type: "middle", mode: "math", delim: middle })
|
248
|
+
parser.consume()
|
249
|
+
body = body.concat(parser.parseExpression(false, null, true))
|
250
|
+
nextToken = parser.fetch()
|
251
|
+
}
|
245
252
|
--parser.leftrightDepth;
|
246
253
|
// Check the next token
|
247
254
|
parser.expect("\\right", false);
|
@@ -251,8 +258,7 @@ defineFunction({
|
|
251
258
|
mode: parser.mode,
|
252
259
|
body,
|
253
260
|
left: delim.text,
|
254
|
-
right: right.delim
|
255
|
-
rightColor: right.color
|
261
|
+
right: right.delim
|
256
262
|
};
|
257
263
|
},
|
258
264
|
mathmlBuilder: (group, style) => {
|
@@ -275,7 +281,6 @@ defineFunction({
|
|
275
281
|
if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
|
276
282
|
rightNode.setAttribute("stretchy", "true")
|
277
283
|
}
|
278
|
-
if (group.rightColor) { rightNode.style.color = group.rightColor }
|
279
284
|
inner.push(rightNode)
|
280
285
|
|
281
286
|
return mml.makeRow(inner);
|
package/src/functions/font.js
CHANGED
@@ -103,7 +103,7 @@ defineFunction({
|
|
103
103
|
},
|
104
104
|
handler: ({ parser, funcName, breakOnTokenText }, args) => {
|
105
105
|
const { mode } = parser;
|
106
|
-
const body = parser.parseExpression(true, breakOnTokenText);
|
106
|
+
const body = parser.parseExpression(true, breakOnTokenText, true);
|
107
107
|
const fontStyle = `math${funcName.slice(1)}`;
|
108
108
|
|
109
109
|
return {
|
package/src/functions/mclass.js
CHANGED
@@ -23,6 +23,9 @@ function mathmlBuilder(group, style) {
|
|
23
23
|
if (group.isCharacterBox || inner[0].type === "mathord") {
|
24
24
|
node = inner[0];
|
25
25
|
node.type = "mi";
|
26
|
+
if (node.children.length === 1 && node.children[0].text && node.children[0].text === "∇") {
|
27
|
+
node.setAttribute("mathvariant", "normal")
|
28
|
+
}
|
26
29
|
} else {
|
27
30
|
node = new mathMLTree.MathNode("mi", inner);
|
28
31
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import defineFunction from "../defineFunction"
|
2
|
+
import * as mml from "../buildMathML"
|
3
|
+
|
4
|
+
defineFunction({
|
5
|
+
type: "reflect",
|
6
|
+
names: ["\\reflectbox"],
|
7
|
+
props: {
|
8
|
+
numArgs: 1,
|
9
|
+
argTypes: ["hbox"],
|
10
|
+
allowedInText: true
|
11
|
+
},
|
12
|
+
handler({ parser }, args) {
|
13
|
+
return {
|
14
|
+
type: "reflect",
|
15
|
+
mode: parser.mode,
|
16
|
+
body: args[0]
|
17
|
+
};
|
18
|
+
},
|
19
|
+
mathmlBuilder(group, style) {
|
20
|
+
const node = mml.buildGroup(group.body, style)
|
21
|
+
node.style.transform = "scaleX(-1)"
|
22
|
+
return node
|
23
|
+
}
|
24
|
+
})
|
package/src/functions/sizing.js
CHANGED
@@ -44,7 +44,7 @@ defineFunction({
|
|
44
44
|
// eslint-disable-next-line no-console
|
45
45
|
console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`)
|
46
46
|
}
|
47
|
-
const body = parser.parseExpression(false, breakOnTokenText);
|
47
|
+
const body = parser.parseExpression(false, breakOnTokenText, true);
|
48
48
|
return {
|
49
49
|
type: "sizing",
|
50
50
|
mode: parser.mode,
|
package/src/functions/styling.js
CHANGED
@@ -26,7 +26,7 @@ defineFunction({
|
|
26
26
|
},
|
27
27
|
handler({ breakOnTokenText, funcName, parser }, args) {
|
28
28
|
// parse out the implicit body
|
29
|
-
const body = parser.parseExpression(true, breakOnTokenText);
|
29
|
+
const body = parser.parseExpression(true, breakOnTokenText, true);
|
30
30
|
|
31
31
|
const scriptLevel = funcName.slice(1, funcName.length - 5);
|
32
32
|
return {
|
@@ -90,8 +90,6 @@ defineFunctionBuilders({
|
|
90
90
|
node = new mathMLTree.MathNode("mi", [text])
|
91
91
|
if (text.text === origText && latinRegEx.test(origText)) {
|
92
92
|
node.setAttribute("mathvariant", "italic")
|
93
|
-
} else if (text.text === "∇" && variant === "normal") {
|
94
|
-
node.setAttribute("mathvariant", "normal")
|
95
93
|
}
|
96
94
|
}
|
97
95
|
return node
|