temml 0.10.20 → 0.10.22
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/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
|