temml 0.10.19 → 0.10.21
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 +33 -0
- package/dist/Temml-Latin-Modern.css +33 -0
- package/dist/Temml-Libertinus.css +33 -0
- package/dist/Temml-Local.css +33 -0
- package/dist/Temml-STIX2.css +33 -0
- package/dist/temml.cjs +50 -65
- package/dist/temml.js +50 -65
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +50 -65
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +1 -1
- package/src/Parser.js +8 -3
- package/src/buildMathML.js +10 -8
- package/src/environments/array.js +6 -3
- package/src/environments/cd.js +2 -1
- package/src/functions/color.js +2 -9
- package/src/functions/delimsizing.js +2 -12
- package/src/functions/enclose.js +5 -24
- package/src/functions/font.js +1 -1
- package/src/functions/not.js +2 -2
- package/src/functions/op.js +10 -0
- package/src/functions/ordgroup.js +1 -1
- package/src/postProcess.js +1 -1
- package/src/svg.js +0 -110
package/dist/temml.mjs
CHANGED
@@ -2070,20 +2070,22 @@ const consolidateNumbers = expression => {
|
|
2070
2070
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
2071
2071
|
* unless the array has length 1. Always returns a single node.
|
2072
2072
|
*/
|
2073
|
-
const makeRow = function(body) {
|
2073
|
+
const makeRow = function(body, semisimple = false) {
|
2074
2074
|
if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
|
2075
2075
|
return body[0];
|
2076
|
-
} else {
|
2076
|
+
} else if (!semisimple) {
|
2077
2077
|
// Suppress spacing on <mo> nodes at both ends of the row.
|
2078
2078
|
if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
|
2079
2079
|
body[0].attributes.lspace = "0em";
|
2080
|
+
body[0].attributes.rspace = "0em";
|
2080
2081
|
}
|
2081
2082
|
const end = body.length - 1;
|
2082
2083
|
if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
|
2084
|
+
body[end].attributes.lspace = "0em";
|
2083
2085
|
body[end].attributes.rspace = "0em";
|
2084
2086
|
}
|
2085
|
-
return new mathMLTree.MathNode("mrow", body);
|
2086
2087
|
}
|
2088
|
+
return new mathMLTree.MathNode("mrow", body);
|
2087
2089
|
};
|
2088
2090
|
|
2089
2091
|
const isRel = item => {
|
@@ -2097,10 +2099,10 @@ const isRel = item => {
|
|
2097
2099
|
* (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
|
2098
2100
|
* (2) Suppress spacing between two adjacent relations.
|
2099
2101
|
*/
|
2100
|
-
const buildExpression = function(expression, style,
|
2101
|
-
if (expression.length === 1) {
|
2102
|
+
const buildExpression = function(expression, style, semisimple = false) {
|
2103
|
+
if (!semisimple && expression.length === 1) {
|
2102
2104
|
const group = buildGroup$1(expression[0], style);
|
2103
|
-
if (
|
2105
|
+
if (group instanceof MathNode && group.type === "mo") {
|
2104
2106
|
// When TeX writers want to suppress spacing on an operator,
|
2105
2107
|
// they often put the operator by itself inside braces.
|
2106
2108
|
group.setAttribute("lspace", "0em");
|
@@ -2130,8 +2132,8 @@ const buildExpression = function(expression, style, isOrdgroup) {
|
|
2130
2132
|
* Equivalent to buildExpression, but wraps the elements in an <mrow>
|
2131
2133
|
* if there's more than one. Returns a single node instead of an array.
|
2132
2134
|
*/
|
2133
|
-
const buildExpressionRow = function(expression, style,
|
2134
|
-
return makeRow(buildExpression(expression, style,
|
2135
|
+
const buildExpressionRow = function(expression, style, semisimple = false) {
|
2136
|
+
return makeRow(buildExpression(expression, style, semisimple), semisimple);
|
2135
2137
|
};
|
2136
2138
|
|
2137
2139
|
/**
|
@@ -2816,7 +2818,8 @@ function cdArrow(arrowChar, labels, parser) {
|
|
2816
2818
|
const arrowGroup = {
|
2817
2819
|
type: "ordgroup",
|
2818
2820
|
mode: "math",
|
2819
|
-
body: [leftLabel, sizedArrow, rightLabel]
|
2821
|
+
body: [leftLabel, sizedArrow, rightLabel],
|
2822
|
+
semisimple: true
|
2820
2823
|
};
|
2821
2824
|
return parser.callFunction("\\\\cdparent", [arrowGroup], []);
|
2822
2825
|
}
|
@@ -3242,7 +3245,7 @@ defineFunction({
|
|
3242
3245
|
allowedInText: true,
|
3243
3246
|
argTypes: ["raw", "raw"]
|
3244
3247
|
},
|
3245
|
-
handler({ parser, token }, args, optArgs) {
|
3248
|
+
handler({ parser, breakOnTokenText, token }, args, optArgs) {
|
3246
3249
|
const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string;
|
3247
3250
|
let color = "";
|
3248
3251
|
if (model) {
|
@@ -3252,15 +3255,8 @@ defineFunction({
|
|
3252
3255
|
color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token);
|
3253
3256
|
}
|
3254
3257
|
|
3255
|
-
// Set macro \current@color in current namespace to store the current
|
3256
|
-
// color, mimicking the behavior of color.sty.
|
3257
|
-
// This is currently used just to correctly color a \right
|
3258
|
-
// that follows a \color command.
|
3259
|
-
parser.gullet.macros.set("\\current@color", color);
|
3260
|
-
|
3261
3258
|
// Parse out the implicit body that should be colored.
|
3262
|
-
|
3263
|
-
const body = parser.parseExpression(true, "\\color");
|
3259
|
+
const body = parser.parseExpression(true, breakOnTokenText);
|
3264
3260
|
|
3265
3261
|
return {
|
3266
3262
|
type: "color",
|
@@ -3800,18 +3796,10 @@ defineFunction({
|
|
3800
3796
|
argTypes: ["primitive"]
|
3801
3797
|
},
|
3802
3798
|
handler: (context, args) => {
|
3803
|
-
// \left case below triggers parsing of \right in
|
3804
|
-
// `const right = parser.parseFunction();`
|
3805
|
-
// uses this return value.
|
3806
|
-
const color = context.parser.gullet.macros.get("\\current@color");
|
3807
|
-
if (color && typeof color !== "string") {
|
3808
|
-
throw new ParseError("\\current@color set to non-string in \\right");
|
3809
|
-
}
|
3810
3799
|
return {
|
3811
3800
|
type: "leftright-right",
|
3812
3801
|
mode: context.parser.mode,
|
3813
|
-
delim: checkDelimiter(args[0], context).text
|
3814
|
-
color // undefined if not set via \color
|
3802
|
+
delim: checkDelimiter(args[0], context).text
|
3815
3803
|
};
|
3816
3804
|
}
|
3817
3805
|
});
|
@@ -3840,8 +3828,7 @@ defineFunction({
|
|
3840
3828
|
mode: parser.mode,
|
3841
3829
|
body,
|
3842
3830
|
left: delim.text,
|
3843
|
-
right: right.delim
|
3844
|
-
rightColor: right.color
|
3831
|
+
right: right.delim
|
3845
3832
|
};
|
3846
3833
|
},
|
3847
3834
|
mathmlBuilder: (group, style) => {
|
@@ -3864,7 +3851,6 @@ defineFunction({
|
|
3864
3851
|
if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
|
3865
3852
|
rightNode.setAttribute("stretchy", "true");
|
3866
3853
|
}
|
3867
|
-
if (group.rightColor) { rightNode.style.color = group.rightColor; }
|
3868
3854
|
inner.push(rightNode);
|
3869
3855
|
|
3870
3856
|
return makeRow(inner);
|
@@ -3938,20 +3924,12 @@ const mathmlBuilder$8 = (group, style) => {
|
|
3938
3924
|
node.style.borderBottom = "0.065em solid";
|
3939
3925
|
break
|
3940
3926
|
case "\\cancel":
|
3941
|
-
|
3942
|
-
|
3943
|
-
|
3944
|
-
rgba(0,0,0,1) 50%,
|
3945
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
3946
|
-
rgba(0,0,0,0) 100%);`;
|
3927
|
+
// We can't use an inline background-gradient. It does not work client-side.
|
3928
|
+
// So set a class and put the rule in the external CSS file.
|
3929
|
+
node.classes.push("tml-cancel");
|
3947
3930
|
break
|
3948
3931
|
case "\\bcancel":
|
3949
|
-
node.
|
3950
|
-
rgba(0,0,0,0) 0%,
|
3951
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
3952
|
-
rgba(0,0,0,1) 50%,
|
3953
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
3954
|
-
rgba(0,0,0,0) 100%);`;
|
3932
|
+
node.classes.push("tml-bcancel");
|
3955
3933
|
break
|
3956
3934
|
/*
|
3957
3935
|
case "\\longdiv":
|
@@ -3998,18 +3976,7 @@ rgba(0,0,0,0) 100%);`;
|
|
3998
3976
|
break
|
3999
3977
|
}
|
4000
3978
|
case "\\xcancel":
|
4001
|
-
node.
|
4002
|
-
rgba(0,0,0,0) 0%,
|
4003
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
4004
|
-
rgba(0,0,0,1) 50%,
|
4005
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
4006
|
-
rgba(0,0,0,0) 100%),
|
4007
|
-
linear-gradient(to top right,
|
4008
|
-
rgba(0,0,0,0) 0%,
|
4009
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
4010
|
-
rgba(0,0,0,1) 50%,
|
4011
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
4012
|
-
rgba(0,0,0,0) 100%);`;
|
3979
|
+
node.classes.push("tml-xcancel");
|
4013
3980
|
break
|
4014
3981
|
}
|
4015
3982
|
if (group.backgroundColor) {
|
@@ -4207,7 +4174,7 @@ const getTag = (group, style, rowNum) => {
|
|
4207
4174
|
if (tagContents) {
|
4208
4175
|
// The author has written a \tag or a \notag in this row.
|
4209
4176
|
if (tagContents.body) {
|
4210
|
-
tag = buildExpressionRow(tagContents.body, style);
|
4177
|
+
tag = buildExpressionRow(tagContents.body, style, true);
|
4211
4178
|
tag.classes = ["tml-tag"];
|
4212
4179
|
} else {
|
4213
4180
|
// \notag. Return an empty span.
|
@@ -4254,7 +4221,9 @@ function parseArray(
|
|
4254
4221
|
parser.gullet.macros.set("\\cr", "\\\\\\relax");
|
4255
4222
|
}
|
4256
4223
|
if (addEqnNum) {
|
4257
|
-
parser.gullet.macros.set("\\tag", "\\
|
4224
|
+
parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren");
|
4225
|
+
parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
|
4226
|
+
parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}");
|
4258
4227
|
parser.gullet.macros.set("\\notag", "\\env@notag");
|
4259
4228
|
parser.gullet.macros.set("\\nonumber", "\\env@notag");
|
4260
4229
|
}
|
@@ -4295,7 +4264,8 @@ function parseArray(
|
|
4295
4264
|
cell = {
|
4296
4265
|
type: "ordgroup",
|
4297
4266
|
mode: parser.mode,
|
4298
|
-
body: cell
|
4267
|
+
body: cell,
|
4268
|
+
semisimple: true
|
4299
4269
|
};
|
4300
4270
|
row.push(cell);
|
4301
4271
|
const next = parser.fetch().text;
|
@@ -5128,7 +5098,7 @@ const mathmlBuilder$6 = (group, style) => {
|
|
5128
5098
|
const mathGroup = buildGroup$1(group.body, newStyle);
|
5129
5099
|
|
5130
5100
|
if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
|
5131
|
-
if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
|
5101
|
+
if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
|
5132
5102
|
mathGroup.style.fontWeight = "bold";
|
5133
5103
|
return mathGroup
|
5134
5104
|
}
|
@@ -6485,10 +6455,10 @@ defineFunction({
|
|
6485
6455
|
},
|
6486
6456
|
mathmlBuilder(group, style) {
|
6487
6457
|
if (group.isCharacterBox) {
|
6488
|
-
const inner = buildExpression(group.body, style);
|
6458
|
+
const inner = buildExpression(group.body, style, true);
|
6489
6459
|
return inner[0]
|
6490
6460
|
} else {
|
6491
|
-
return buildExpressionRow(group.body, style
|
6461
|
+
return buildExpressionRow(group.body, style)
|
6492
6462
|
}
|
6493
6463
|
}
|
6494
6464
|
});
|
@@ -6508,6 +6478,13 @@ const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
|
|
6508
6478
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
6509
6479
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
6510
6480
|
|
6481
|
+
const setSpacing = node => {
|
6482
|
+
// The user wrote a \mathop{…} function. Change spacing from default to OP spacing.
|
6483
|
+
// The most likely spacing for an OP is a thin space per TeXbook p170.
|
6484
|
+
node.attributes.lspace = "0.1667em";
|
6485
|
+
node.attributes.rspace = "0.1667em";
|
6486
|
+
};
|
6487
|
+
|
6511
6488
|
const mathmlBuilder$2 = (group, style) => {
|
6512
6489
|
let node;
|
6513
6490
|
|
@@ -6519,9 +6496,11 @@ const mathmlBuilder$2 = (group, style) => {
|
|
6519
6496
|
} else {
|
6520
6497
|
node.setAttribute("movablelimits", "false");
|
6521
6498
|
}
|
6499
|
+
if (group.fromMathOp) { setSpacing(node); }
|
6522
6500
|
} else if (group.body) {
|
6523
6501
|
// This is an operator with children. Add them.
|
6524
6502
|
node = new MathNode("mo", buildExpression(group.body, style));
|
6503
|
+
if (group.fromMathOp) { setSpacing(node); }
|
6525
6504
|
} else {
|
6526
6505
|
// This is a text operator. Add all of the characters from the operator's name.
|
6527
6506
|
node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
|
@@ -6641,6 +6620,7 @@ defineFunction({
|
|
6641
6620
|
limits: true,
|
6642
6621
|
parentIsSupSub: false,
|
6643
6622
|
symbol: isSymbol,
|
6623
|
+
fromMathOp: true,
|
6644
6624
|
stack: false,
|
6645
6625
|
name: isSymbol ? arr[0].text : null,
|
6646
6626
|
body: isSymbol ? null : ordargument(body)
|
@@ -6974,7 +6954,7 @@ defineMacro("\\operatorname",
|
|
6974
6954
|
defineFunctionBuilders({
|
6975
6955
|
type: "ordgroup",
|
6976
6956
|
mathmlBuilder(group, style) {
|
6977
|
-
return buildExpressionRow(group.body, style,
|
6957
|
+
return buildExpressionRow(group.body, style, group.semisimple);
|
6978
6958
|
}
|
6979
6959
|
});
|
6980
6960
|
|
@@ -12003,6 +11983,8 @@ var unicodeSymbols = {
|
|
12003
11983
|
|
12004
11984
|
/* eslint no-constant-condition:0 */
|
12005
11985
|
|
11986
|
+
const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
|
11987
|
+
|
12006
11988
|
/**
|
12007
11989
|
* This file contains the parser used to parse out a TeX expression from the
|
12008
11990
|
* input. Since TeX isn't context-free, standard parsers don't work particularly
|
@@ -12772,8 +12754,7 @@ class Parser {
|
|
12772
12754
|
body: expression,
|
12773
12755
|
// A group formed by \begingroup...\endgroup is a semi-simple group
|
12774
12756
|
// which doesn't affect spacing in math mode, i.e., is transparent.
|
12775
|
-
// https://tex.stackexchange.com/questions/1930/
|
12776
|
-
// use-begingroup-instead-of-bgroup
|
12757
|
+
// https://tex.stackexchange.com/questions/1930/
|
12777
12758
|
semisimple: text === "\\begingroup" || undefined
|
12778
12759
|
};
|
12779
12760
|
} else {
|
@@ -12887,7 +12868,11 @@ class Parser {
|
|
12887
12868
|
// Recognize base symbol
|
12888
12869
|
let symbol;
|
12889
12870
|
if (symbols[this.mode][text]) {
|
12890
|
-
|
12871
|
+
let group = symbols[this.mode][text].group;
|
12872
|
+
if (group === "bin" && binLeftCancellers.includes(this.prevAtomType)) {
|
12873
|
+
// Change from a binary operator to a unary (prefix) operator
|
12874
|
+
group = "open";
|
12875
|
+
}
|
12891
12876
|
const loc = SourceLocation.range(nucleus);
|
12892
12877
|
let s;
|
12893
12878
|
if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
|
@@ -13157,7 +13142,7 @@ class Style {
|
|
13157
13142
|
* https://mit-license.org/
|
13158
13143
|
*/
|
13159
13144
|
|
13160
|
-
const version = "0.10.
|
13145
|
+
const version = "0.10.21";
|
13161
13146
|
|
13162
13147
|
function postProcess(block) {
|
13163
13148
|
const labelMap = {};
|
package/dist/temmlPostProcess.js
CHANGED
package/package.json
CHANGED
package/src/Parser.js
CHANGED
@@ -15,6 +15,8 @@ import { isDelimiter } from "./functions/delimsizing"
|
|
15
15
|
import unicodeAccents from /*preval*/ "./unicodeAccents";
|
16
16
|
import unicodeSymbols from /*preval*/ "./unicodeSymbols";
|
17
17
|
|
18
|
+
const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
|
19
|
+
|
18
20
|
/**
|
19
21
|
* This file contains the parser used to parse out a TeX expression from the
|
20
22
|
* input. Since TeX isn't context-free, standard parsers don't work particularly
|
@@ -784,8 +786,7 @@ export default class Parser {
|
|
784
786
|
body: expression,
|
785
787
|
// A group formed by \begingroup...\endgroup is a semi-simple group
|
786
788
|
// which doesn't affect spacing in math mode, i.e., is transparent.
|
787
|
-
// https://tex.stackexchange.com/questions/1930/
|
788
|
-
// use-begingroup-instead-of-bgroup
|
789
|
+
// https://tex.stackexchange.com/questions/1930/
|
789
790
|
semisimple: text === "\\begingroup" || undefined
|
790
791
|
};
|
791
792
|
} else {
|
@@ -899,7 +900,11 @@ export default class Parser {
|
|
899
900
|
// Recognize base symbol
|
900
901
|
let symbol;
|
901
902
|
if (symbols[this.mode][text]) {
|
902
|
-
|
903
|
+
let group = symbols[this.mode][text].group;
|
904
|
+
if (group === "bin" && binLeftCancellers.includes(this.prevAtomType)) {
|
905
|
+
// Change from a binary operator to a unary (prefix) operator
|
906
|
+
group = "open"
|
907
|
+
}
|
903
908
|
const loc = SourceLocation.range(nucleus);
|
904
909
|
let s;
|
905
910
|
if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
|
package/src/buildMathML.js
CHANGED
@@ -135,20 +135,22 @@ const consolidateNumbers = expression => {
|
|
135
135
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
136
136
|
* unless the array has length 1. Always returns a single node.
|
137
137
|
*/
|
138
|
-
export const makeRow = function(body) {
|
138
|
+
export const makeRow = function(body, semisimple = false) {
|
139
139
|
if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
|
140
140
|
return body[0];
|
141
|
-
} else {
|
141
|
+
} else if (!semisimple) {
|
142
142
|
// Suppress spacing on <mo> nodes at both ends of the row.
|
143
143
|
if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
|
144
144
|
body[0].attributes.lspace = "0em"
|
145
|
+
body[0].attributes.rspace = "0em"
|
145
146
|
}
|
146
147
|
const end = body.length - 1
|
147
148
|
if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
|
149
|
+
body[end].attributes.lspace = "0em"
|
148
150
|
body[end].attributes.rspace = "0em"
|
149
151
|
}
|
150
|
-
return new mathMLTree.MathNode("mrow", body);
|
151
152
|
}
|
153
|
+
return new mathMLTree.MathNode("mrow", body);
|
152
154
|
};
|
153
155
|
|
154
156
|
const isRel = item => {
|
@@ -162,10 +164,10 @@ const isRel = item => {
|
|
162
164
|
* (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
|
163
165
|
* (2) Suppress spacing between two adjacent relations.
|
164
166
|
*/
|
165
|
-
export const buildExpression = function(expression, style,
|
166
|
-
if (expression.length === 1) {
|
167
|
+
export const buildExpression = function(expression, style, semisimple = false) {
|
168
|
+
if (!semisimple && expression.length === 1) {
|
167
169
|
const group = buildGroup(expression[0], style);
|
168
|
-
if (
|
170
|
+
if (group instanceof MathNode && group.type === "mo") {
|
169
171
|
// When TeX writers want to suppress spacing on an operator,
|
170
172
|
// they often put the operator by itself inside braces.
|
171
173
|
group.setAttribute("lspace", "0em");
|
@@ -195,8 +197,8 @@ export const buildExpression = function(expression, style, isOrdgroup) {
|
|
195
197
|
* Equivalent to buildExpression, but wraps the elements in an <mrow>
|
196
198
|
* if there's more than one. Returns a single node instead of an array.
|
197
199
|
*/
|
198
|
-
export const buildExpressionRow = function(expression, style,
|
199
|
-
return makeRow(buildExpression(expression, style,
|
200
|
+
export const buildExpressionRow = function(expression, style, semisimple = false) {
|
201
|
+
return makeRow(buildExpression(expression, style, semisimple), semisimple);
|
200
202
|
};
|
201
203
|
|
202
204
|
/**
|
@@ -44,7 +44,7 @@ const getTag = (group, style, rowNum) => {
|
|
44
44
|
if (tagContents) {
|
45
45
|
// The author has written a \tag or a \notag in this row.
|
46
46
|
if (tagContents.body) {
|
47
|
-
tag = mml.buildExpressionRow(tagContents.body, style)
|
47
|
+
tag = mml.buildExpressionRow(tagContents.body, style, true)
|
48
48
|
tag.classes = ["tml-tag"]
|
49
49
|
} else {
|
50
50
|
// \notag. Return an empty span.
|
@@ -91,7 +91,9 @@ function parseArray(
|
|
91
91
|
parser.gullet.macros.set("\\cr", "\\\\\\relax");
|
92
92
|
}
|
93
93
|
if (addEqnNum) {
|
94
|
-
parser.gullet.macros.set("\\tag", "\\
|
94
|
+
parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren")
|
95
|
+
parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
|
96
|
+
parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}")
|
95
97
|
parser.gullet.macros.set("\\notag", "\\env@notag");
|
96
98
|
parser.gullet.macros.set("\\nonumber", "\\env@notag")
|
97
99
|
}
|
@@ -132,7 +134,8 @@ function parseArray(
|
|
132
134
|
cell = {
|
133
135
|
type: "ordgroup",
|
134
136
|
mode: parser.mode,
|
135
|
-
body: cell
|
137
|
+
body: cell,
|
138
|
+
semisimple: true
|
136
139
|
};
|
137
140
|
row.push(cell);
|
138
141
|
const next = parser.fetch().text;
|
package/src/environments/cd.js
CHANGED
@@ -49,7 +49,8 @@ function cdArrow(arrowChar, labels, parser) {
|
|
49
49
|
const arrowGroup = {
|
50
50
|
type: "ordgroup",
|
51
51
|
mode: "math",
|
52
|
-
body: [leftLabel, sizedArrow, rightLabel]
|
52
|
+
body: [leftLabel, sizedArrow, rightLabel],
|
53
|
+
semisimple: true
|
53
54
|
};
|
54
55
|
return parser.callFunction("\\\\cdparent", [arrowGroup], []);
|
55
56
|
}
|
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)
|
223
216
|
|
224
217
|
return {
|
225
218
|
type: "color",
|
@@ -211,18 +211,10 @@ defineFunction({
|
|
211
211
|
argTypes: ["primitive"]
|
212
212
|
},
|
213
213
|
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
214
|
return {
|
222
215
|
type: "leftright-right",
|
223
216
|
mode: context.parser.mode,
|
224
|
-
delim: checkDelimiter(args[0], context).text
|
225
|
-
color // undefined if not set via \color
|
217
|
+
delim: checkDelimiter(args[0], context).text
|
226
218
|
};
|
227
219
|
}
|
228
220
|
});
|
@@ -251,8 +243,7 @@ defineFunction({
|
|
251
243
|
mode: parser.mode,
|
252
244
|
body,
|
253
245
|
left: delim.text,
|
254
|
-
right: right.delim
|
255
|
-
rightColor: right.color
|
246
|
+
right: right.delim
|
256
247
|
};
|
257
248
|
},
|
258
249
|
mathmlBuilder: (group, style) => {
|
@@ -275,7 +266,6 @@ defineFunction({
|
|
275
266
|
if (group.right === "\u2216" || group.right.indexOf("arrow") > -1) {
|
276
267
|
rightNode.setAttribute("stretchy", "true")
|
277
268
|
}
|
278
|
-
if (group.rightColor) { rightNode.style.color = group.rightColor }
|
279
269
|
inner.push(rightNode)
|
280
270
|
|
281
271
|
return mml.makeRow(inner);
|
package/src/functions/enclose.js
CHANGED
@@ -34,20 +34,12 @@ const mathmlBuilder = (group, style) => {
|
|
34
34
|
node.style.borderBottom = "0.065em solid"
|
35
35
|
break
|
36
36
|
case "\\cancel":
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
rgba(0,0,0,1) 50%,
|
41
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
42
|
-
rgba(0,0,0,0) 100%);`
|
37
|
+
// We can't use an inline background-gradient. It does not work client-side.
|
38
|
+
// So set a class and put the rule in the external CSS file.
|
39
|
+
node.classes.push("tml-cancel")
|
43
40
|
break
|
44
41
|
case "\\bcancel":
|
45
|
-
node.
|
46
|
-
rgba(0,0,0,0) 0%,
|
47
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
48
|
-
rgba(0,0,0,1) 50%,
|
49
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
50
|
-
rgba(0,0,0,0) 100%);`
|
42
|
+
node.classes.push("tml-bcancel")
|
51
43
|
break
|
52
44
|
/*
|
53
45
|
case "\\longdiv":
|
@@ -94,18 +86,7 @@ rgba(0,0,0,0) 100%);`
|
|
94
86
|
break
|
95
87
|
}
|
96
88
|
case "\\xcancel":
|
97
|
-
node.
|
98
|
-
rgba(0,0,0,0) 0%,
|
99
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
100
|
-
rgba(0,0,0,1) 50%,
|
101
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
102
|
-
rgba(0,0,0,0) 100%),
|
103
|
-
linear-gradient(to top right,
|
104
|
-
rgba(0,0,0,0) 0%,
|
105
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
106
|
-
rgba(0,0,0,1) 50%,
|
107
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
108
|
-
rgba(0,0,0,0) 100%);`
|
89
|
+
node.classes.push("tml-xcancel")
|
109
90
|
break
|
110
91
|
}
|
111
92
|
if (group.backgroundColor) {
|
package/src/functions/font.js
CHANGED
@@ -8,7 +8,7 @@ const mathmlBuilder = (group, style) => {
|
|
8
8
|
const mathGroup = mml.buildGroup(group.body, newStyle)
|
9
9
|
|
10
10
|
if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
|
11
|
-
if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
|
11
|
+
if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
|
12
12
|
mathGroup.style.fontWeight = "bold"
|
13
13
|
return mathGroup
|
14
14
|
}
|
package/src/functions/not.js
CHANGED
@@ -37,10 +37,10 @@ defineFunction({
|
|
37
37
|
},
|
38
38
|
mathmlBuilder(group, style) {
|
39
39
|
if (group.isCharacterBox) {
|
40
|
-
const inner = mml.buildExpression(group.body, style);
|
40
|
+
const inner = mml.buildExpression(group.body, style, true);
|
41
41
|
return inner[0]
|
42
42
|
} else {
|
43
|
-
return mml.buildExpressionRow(group.body, style
|
43
|
+
return mml.buildExpressionRow(group.body, style)
|
44
44
|
}
|
45
45
|
}
|
46
46
|
});
|
package/src/functions/op.js
CHANGED
@@ -17,6 +17,13 @@ export const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]
|
|
17
17
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
18
18
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
19
19
|
|
20
|
+
const setSpacing = node => {
|
21
|
+
// The user wrote a \mathop{…} function. Change spacing from default to OP spacing.
|
22
|
+
// The most likely spacing for an OP is a thin space per TeXbook p170.
|
23
|
+
node.attributes.lspace = "0.1667em"
|
24
|
+
node.attributes.rspace = "0.1667em"
|
25
|
+
}
|
26
|
+
|
20
27
|
const mathmlBuilder = (group, style) => {
|
21
28
|
let node;
|
22
29
|
|
@@ -28,9 +35,11 @@ const mathmlBuilder = (group, style) => {
|
|
28
35
|
} else {
|
29
36
|
node.setAttribute("movablelimits", "false")
|
30
37
|
}
|
38
|
+
if (group.fromMathOp) { setSpacing(node) }
|
31
39
|
} else if (group.body) {
|
32
40
|
// This is an operator with children. Add them.
|
33
41
|
node = new mathMLTree.MathNode("mo", mml.buildExpression(group.body, style));
|
42
|
+
if (group.fromMathOp) { setSpacing(node) }
|
34
43
|
} else {
|
35
44
|
// This is a text operator. Add all of the characters from the operator's name.
|
36
45
|
node = new mathMLTree.MathNode("mi", [new mathMLTree.TextNode(group.name.slice(1))]);
|
@@ -150,6 +159,7 @@ defineFunction({
|
|
150
159
|
limits: true,
|
151
160
|
parentIsSupSub: false,
|
152
161
|
symbol: isSymbol,
|
162
|
+
fromMathOp: true,
|
153
163
|
stack: false,
|
154
164
|
name: isSymbol ? arr[0].text : null,
|
155
165
|
body: isSymbol ? null : ordargument(body)
|