temml 0.10.18 → 0.10.20
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 +60 -46
- package/dist/temml.js +60 -46
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +60 -46
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +1 -1
- package/src/Parser.js +8 -3
- package/src/buildMathML.js +20 -8
- package/src/environments/array.js +6 -3
- package/src/environments/cd.js +2 -1
- 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/macros.js +2 -0
- package/src/postProcess.js +1 -1
- package/src/symbols.js +2 -2
- package/src/svg.js +0 -110
package/dist/temml.mjs
CHANGED
@@ -938,8 +938,8 @@ defineSymbol(math, textord, "\u2207", "\\nabla", true);
|
|
938
938
|
defineSymbol(math, textord, "\u266d", "\\flat", true);
|
939
939
|
defineSymbol(math, textord, "\u2113", "\\ell", true);
|
940
940
|
defineSymbol(math, textord, "\u266e", "\\natural", true);
|
941
|
-
defineSymbol(math, textord, "Å", "\\
|
942
|
-
defineSymbol(text, textord, "Å", "\\
|
941
|
+
defineSymbol(math, textord, "Å", "\\Angstrom", true);
|
942
|
+
defineSymbol(text, textord, "Å", "\\Angstrom", true);
|
943
943
|
defineSymbol(math, textord, "\u2663", "\\clubsuit", true);
|
944
944
|
defineSymbol(math, textord, "\u2667", "\\varclubsuit", true);
|
945
945
|
defineSymbol(math, textord, "\u2118", "\\wp", true);
|
@@ -2053,6 +2053,16 @@ const consolidateNumbers = expression => {
|
|
2053
2053
|
expression[nums[i].start].text += expression[j].text;
|
2054
2054
|
}
|
2055
2055
|
expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
|
2056
|
+
// Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
|
2057
|
+
// If so, merge the first <mn> into the base.
|
2058
|
+
if (expression.length > nums[i].start + 1) {
|
2059
|
+
const nextTerm = expression[nums[i].start + 1];
|
2060
|
+
if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
|
2061
|
+
numberRegEx$1.test(nextTerm.base.text)) {
|
2062
|
+
nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text;
|
2063
|
+
expression.splice(nums[i].start, 1);
|
2064
|
+
}
|
2065
|
+
}
|
2056
2066
|
}
|
2057
2067
|
};
|
2058
2068
|
|
@@ -2060,20 +2070,22 @@ const consolidateNumbers = expression => {
|
|
2060
2070
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
2061
2071
|
* unless the array has length 1. Always returns a single node.
|
2062
2072
|
*/
|
2063
|
-
const makeRow = function(body) {
|
2073
|
+
const makeRow = function(body, semisimple = false) {
|
2064
2074
|
if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
|
2065
2075
|
return body[0];
|
2066
|
-
} else {
|
2076
|
+
} else if (!semisimple) {
|
2067
2077
|
// Suppress spacing on <mo> nodes at both ends of the row.
|
2068
2078
|
if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
|
2069
2079
|
body[0].attributes.lspace = "0em";
|
2080
|
+
body[0].attributes.rspace = "0em";
|
2070
2081
|
}
|
2071
2082
|
const end = body.length - 1;
|
2072
2083
|
if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
|
2084
|
+
body[end].attributes.lspace = "0em";
|
2073
2085
|
body[end].attributes.rspace = "0em";
|
2074
2086
|
}
|
2075
|
-
return new mathMLTree.MathNode("mrow", body);
|
2076
2087
|
}
|
2088
|
+
return new mathMLTree.MathNode("mrow", body);
|
2077
2089
|
};
|
2078
2090
|
|
2079
2091
|
const isRel = item => {
|
@@ -2087,10 +2099,10 @@ const isRel = item => {
|
|
2087
2099
|
* (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
|
2088
2100
|
* (2) Suppress spacing between two adjacent relations.
|
2089
2101
|
*/
|
2090
|
-
const buildExpression = function(expression, style,
|
2091
|
-
if (expression.length === 1) {
|
2102
|
+
const buildExpression = function(expression, style, semisimple = false) {
|
2103
|
+
if (!semisimple && expression.length === 1) {
|
2092
2104
|
const group = buildGroup$1(expression[0], style);
|
2093
|
-
if (
|
2105
|
+
if (group instanceof MathNode && group.type === "mo") {
|
2094
2106
|
// When TeX writers want to suppress spacing on an operator,
|
2095
2107
|
// they often put the operator by itself inside braces.
|
2096
2108
|
group.setAttribute("lspace", "0em");
|
@@ -2120,8 +2132,8 @@ const buildExpression = function(expression, style, isOrdgroup) {
|
|
2120
2132
|
* Equivalent to buildExpression, but wraps the elements in an <mrow>
|
2121
2133
|
* if there's more than one. Returns a single node instead of an array.
|
2122
2134
|
*/
|
2123
|
-
const buildExpressionRow = function(expression, style,
|
2124
|
-
return makeRow(buildExpression(expression, style,
|
2135
|
+
const buildExpressionRow = function(expression, style, semisimple = false) {
|
2136
|
+
return makeRow(buildExpression(expression, style, semisimple), semisimple);
|
2125
2137
|
};
|
2126
2138
|
|
2127
2139
|
/**
|
@@ -2806,7 +2818,8 @@ function cdArrow(arrowChar, labels, parser) {
|
|
2806
2818
|
const arrowGroup = {
|
2807
2819
|
type: "ordgroup",
|
2808
2820
|
mode: "math",
|
2809
|
-
body: [leftLabel, sizedArrow, rightLabel]
|
2821
|
+
body: [leftLabel, sizedArrow, rightLabel],
|
2822
|
+
semisimple: true
|
2810
2823
|
};
|
2811
2824
|
return parser.callFunction("\\\\cdparent", [arrowGroup], []);
|
2812
2825
|
}
|
@@ -3928,20 +3941,12 @@ const mathmlBuilder$8 = (group, style) => {
|
|
3928
3941
|
node.style.borderBottom = "0.065em solid";
|
3929
3942
|
break
|
3930
3943
|
case "\\cancel":
|
3931
|
-
|
3932
|
-
|
3933
|
-
|
3934
|
-
rgba(0,0,0,1) 50%,
|
3935
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
3936
|
-
rgba(0,0,0,0) 100%);`;
|
3944
|
+
// We can't use an inline background-gradient. It does not work client-side.
|
3945
|
+
// So set a class and put the rule in the external CSS file.
|
3946
|
+
node.classes.push("tml-cancel");
|
3937
3947
|
break
|
3938
3948
|
case "\\bcancel":
|
3939
|
-
node.
|
3940
|
-
rgba(0,0,0,0) 0%,
|
3941
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
3942
|
-
rgba(0,0,0,1) 50%,
|
3943
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
3944
|
-
rgba(0,0,0,0) 100%);`;
|
3949
|
+
node.classes.push("tml-bcancel");
|
3945
3950
|
break
|
3946
3951
|
/*
|
3947
3952
|
case "\\longdiv":
|
@@ -3988,18 +3993,7 @@ rgba(0,0,0,0) 100%);`;
|
|
3988
3993
|
break
|
3989
3994
|
}
|
3990
3995
|
case "\\xcancel":
|
3991
|
-
node.
|
3992
|
-
rgba(0,0,0,0) 0%,
|
3993
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
3994
|
-
rgba(0,0,0,1) 50%,
|
3995
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
3996
|
-
rgba(0,0,0,0) 100%),
|
3997
|
-
linear-gradient(to top right,
|
3998
|
-
rgba(0,0,0,0) 0%,
|
3999
|
-
rgba(0,0,0,0) calc(50% - 0.06em),
|
4000
|
-
rgba(0,0,0,1) 50%,
|
4001
|
-
rgba(0,0,0,0) calc(50% + 0.06em),
|
4002
|
-
rgba(0,0,0,0) 100%);`;
|
3996
|
+
node.classes.push("tml-xcancel");
|
4003
3997
|
break
|
4004
3998
|
}
|
4005
3999
|
if (group.backgroundColor) {
|
@@ -4197,7 +4191,7 @@ const getTag = (group, style, rowNum) => {
|
|
4197
4191
|
if (tagContents) {
|
4198
4192
|
// The author has written a \tag or a \notag in this row.
|
4199
4193
|
if (tagContents.body) {
|
4200
|
-
tag = buildExpressionRow(tagContents.body, style);
|
4194
|
+
tag = buildExpressionRow(tagContents.body, style, true);
|
4201
4195
|
tag.classes = ["tml-tag"];
|
4202
4196
|
} else {
|
4203
4197
|
// \notag. Return an empty span.
|
@@ -4244,7 +4238,9 @@ function parseArray(
|
|
4244
4238
|
parser.gullet.macros.set("\\cr", "\\\\\\relax");
|
4245
4239
|
}
|
4246
4240
|
if (addEqnNum) {
|
4247
|
-
parser.gullet.macros.set("\\tag", "\\
|
4241
|
+
parser.gullet.macros.set("\\tag", "\\@ifstar\\envtag@literal\\envtag@paren");
|
4242
|
+
parser.gullet.macros.set("\\envtag@paren", "\\env@tag{{(\\text{#1})}}");
|
4243
|
+
parser.gullet.macros.set("\\envtag@literal", "\\env@tag{\\text{#1}}");
|
4248
4244
|
parser.gullet.macros.set("\\notag", "\\env@notag");
|
4249
4245
|
parser.gullet.macros.set("\\nonumber", "\\env@notag");
|
4250
4246
|
}
|
@@ -4285,7 +4281,8 @@ function parseArray(
|
|
4285
4281
|
cell = {
|
4286
4282
|
type: "ordgroup",
|
4287
4283
|
mode: parser.mode,
|
4288
|
-
body: cell
|
4284
|
+
body: cell,
|
4285
|
+
semisimple: true
|
4289
4286
|
};
|
4290
4287
|
row.push(cell);
|
4291
4288
|
const next = parser.fetch().text;
|
@@ -5118,7 +5115,7 @@ const mathmlBuilder$6 = (group, style) => {
|
|
5118
5115
|
const mathGroup = buildGroup$1(group.body, newStyle);
|
5119
5116
|
|
5120
5117
|
if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{}
|
5121
|
-
if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) {
|
5118
|
+
if (font === "boldsymbol" && ["mo", "mpadded", "mrow"].includes(mathGroup.type)) {
|
5122
5119
|
mathGroup.style.fontWeight = "bold";
|
5123
5120
|
return mathGroup
|
5124
5121
|
}
|
@@ -6475,10 +6472,10 @@ defineFunction({
|
|
6475
6472
|
},
|
6476
6473
|
mathmlBuilder(group, style) {
|
6477
6474
|
if (group.isCharacterBox) {
|
6478
|
-
const inner = buildExpression(group.body, style);
|
6475
|
+
const inner = buildExpression(group.body, style, true);
|
6479
6476
|
return inner[0]
|
6480
6477
|
} else {
|
6481
|
-
return buildExpressionRow(group.body, style
|
6478
|
+
return buildExpressionRow(group.body, style)
|
6482
6479
|
}
|
6483
6480
|
}
|
6484
6481
|
});
|
@@ -6498,6 +6495,13 @@ const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
|
|
6498
6495
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
6499
6496
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
6500
6497
|
|
6498
|
+
const setSpacing = node => {
|
6499
|
+
// The user wrote a \mathop{…} function. Change spacing from default to OP spacing.
|
6500
|
+
// The most likely spacing for an OP is a thin space per TeXbook p170.
|
6501
|
+
node.attributes.lspace = "0.1667em";
|
6502
|
+
node.attributes.rspace = "0.1667em";
|
6503
|
+
};
|
6504
|
+
|
6501
6505
|
const mathmlBuilder$2 = (group, style) => {
|
6502
6506
|
let node;
|
6503
6507
|
|
@@ -6509,9 +6513,11 @@ const mathmlBuilder$2 = (group, style) => {
|
|
6509
6513
|
} else {
|
6510
6514
|
node.setAttribute("movablelimits", "false");
|
6511
6515
|
}
|
6516
|
+
if (group.fromMathOp) { setSpacing(node); }
|
6512
6517
|
} else if (group.body) {
|
6513
6518
|
// This is an operator with children. Add them.
|
6514
6519
|
node = new MathNode("mo", buildExpression(group.body, style));
|
6520
|
+
if (group.fromMathOp) { setSpacing(node); }
|
6515
6521
|
} else {
|
6516
6522
|
// This is a text operator. Add all of the characters from the operator's name.
|
6517
6523
|
node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
|
@@ -6631,6 +6637,7 @@ defineFunction({
|
|
6631
6637
|
limits: true,
|
6632
6638
|
parentIsSupSub: false,
|
6633
6639
|
symbol: isSymbol,
|
6640
|
+
fromMathOp: true,
|
6634
6641
|
stack: false,
|
6635
6642
|
name: isSymbol ? arr[0].text : null,
|
6636
6643
|
body: isSymbol ? null : ordargument(body)
|
@@ -6964,7 +6971,7 @@ defineMacro("\\operatorname",
|
|
6964
6971
|
defineFunctionBuilders({
|
6965
6972
|
type: "ordgroup",
|
6966
6973
|
mathmlBuilder(group, style) {
|
6967
|
-
return buildExpressionRow(group.body, style,
|
6974
|
+
return buildExpressionRow(group.body, style, group.semisimple);
|
6968
6975
|
}
|
6969
6976
|
});
|
6970
6977
|
|
@@ -8914,6 +8921,8 @@ defineMacro("\\quad", "\\hskip1em\\relax");
|
|
8914
8921
|
// \def\qquad{\hskip2em\relax}
|
8915
8922
|
defineMacro("\\qquad", "\\hskip2em\\relax");
|
8916
8923
|
|
8924
|
+
defineMacro("\\AA", "\\TextOrMath{\\Angstrom}{\\mathring{A}}\\relax");
|
8925
|
+
|
8917
8926
|
// \tag@in@display form of \tag
|
8918
8927
|
defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
|
8919
8928
|
defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
|
@@ -11991,6 +12000,8 @@ var unicodeSymbols = {
|
|
11991
12000
|
|
11992
12001
|
/* eslint no-constant-condition:0 */
|
11993
12002
|
|
12003
|
+
const binLeftCancellers = ["bin", "op", "open", "punct", "rel"];
|
12004
|
+
|
11994
12005
|
/**
|
11995
12006
|
* This file contains the parser used to parse out a TeX expression from the
|
11996
12007
|
* input. Since TeX isn't context-free, standard parsers don't work particularly
|
@@ -12760,8 +12771,7 @@ class Parser {
|
|
12760
12771
|
body: expression,
|
12761
12772
|
// A group formed by \begingroup...\endgroup is a semi-simple group
|
12762
12773
|
// which doesn't affect spacing in math mode, i.e., is transparent.
|
12763
|
-
// https://tex.stackexchange.com/questions/1930/
|
12764
|
-
// use-begingroup-instead-of-bgroup
|
12774
|
+
// https://tex.stackexchange.com/questions/1930/
|
12765
12775
|
semisimple: text === "\\begingroup" || undefined
|
12766
12776
|
};
|
12767
12777
|
} else {
|
@@ -12875,7 +12885,11 @@ class Parser {
|
|
12875
12885
|
// Recognize base symbol
|
12876
12886
|
let symbol;
|
12877
12887
|
if (symbols[this.mode][text]) {
|
12878
|
-
|
12888
|
+
let group = symbols[this.mode][text].group;
|
12889
|
+
if (group === "bin" && binLeftCancellers.includes(this.prevAtomType)) {
|
12890
|
+
// Change from a binary operator to a unary (prefix) operator
|
12891
|
+
group = "open";
|
12892
|
+
}
|
12879
12893
|
const loc = SourceLocation.range(nucleus);
|
12880
12894
|
let s;
|
12881
12895
|
if (Object.prototype.hasOwnProperty.call(ATOMS, group )) {
|
@@ -13145,7 +13159,7 @@ class Style {
|
|
13145
13159
|
* https://mit-license.org/
|
13146
13160
|
*/
|
13147
13161
|
|
13148
|
-
const version = "0.10.
|
13162
|
+
const version = "0.10.20";
|
13149
13163
|
|
13150
13164
|
function postProcess(block) {
|
13151
13165
|
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
@@ -118,6 +118,16 @@ const consolidateNumbers = expression => {
|
|
118
118
|
expression[nums[i].start].text += expression[j].text
|
119
119
|
}
|
120
120
|
expression.splice(nums[i].start + 1, nums[i].end - nums[i].start)
|
121
|
+
// Check if the <mn> is followed by a numeric base in a supsub, e.g. the "3" in 123^4
|
122
|
+
// If so, merge the first <mn> into the base.
|
123
|
+
if (expression.length > nums[i].start + 1) {
|
124
|
+
const nextTerm = expression[nums[i].start + 1];
|
125
|
+
if (nextTerm.type === "supsub" && nextTerm.base && nextTerm.base.type === "textord" &&
|
126
|
+
numberRegEx.test(nextTerm.base.text)) {
|
127
|
+
nextTerm.base.text = expression[nums[i].start].text + nextTerm.base.text
|
128
|
+
expression.splice(nums[i].start, 1)
|
129
|
+
}
|
130
|
+
}
|
121
131
|
}
|
122
132
|
}
|
123
133
|
|
@@ -125,20 +135,22 @@ const consolidateNumbers = expression => {
|
|
125
135
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
126
136
|
* unless the array has length 1. Always returns a single node.
|
127
137
|
*/
|
128
|
-
export const makeRow = function(body) {
|
138
|
+
export const makeRow = function(body, semisimple = false) {
|
129
139
|
if (body.length === 1 && !(body[0] instanceof DocumentFragment)) {
|
130
140
|
return body[0];
|
131
|
-
} else {
|
141
|
+
} else if (!semisimple) {
|
132
142
|
// Suppress spacing on <mo> nodes at both ends of the row.
|
133
143
|
if (body[0] instanceof MathNode && body[0].type === "mo" && !body[0].attributes.fence) {
|
134
144
|
body[0].attributes.lspace = "0em"
|
145
|
+
body[0].attributes.rspace = "0em"
|
135
146
|
}
|
136
147
|
const end = body.length - 1
|
137
148
|
if (body[end] instanceof MathNode && body[end].type === "mo" && !body[end].attributes.fence) {
|
149
|
+
body[end].attributes.lspace = "0em"
|
138
150
|
body[end].attributes.rspace = "0em"
|
139
151
|
}
|
140
|
-
return new mathMLTree.MathNode("mrow", body);
|
141
152
|
}
|
153
|
+
return new mathMLTree.MathNode("mrow", body);
|
142
154
|
};
|
143
155
|
|
144
156
|
const isRel = item => {
|
@@ -152,10 +164,10 @@ const isRel = item => {
|
|
152
164
|
* (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
|
153
165
|
* (2) Suppress spacing between two adjacent relations.
|
154
166
|
*/
|
155
|
-
export const buildExpression = function(expression, style,
|
156
|
-
if (expression.length === 1) {
|
167
|
+
export const buildExpression = function(expression, style, semisimple = false) {
|
168
|
+
if (!semisimple && expression.length === 1) {
|
157
169
|
const group = buildGroup(expression[0], style);
|
158
|
-
if (
|
170
|
+
if (group instanceof MathNode && group.type === "mo") {
|
159
171
|
// When TeX writers want to suppress spacing on an operator,
|
160
172
|
// they often put the operator by itself inside braces.
|
161
173
|
group.setAttribute("lspace", "0em");
|
@@ -185,8 +197,8 @@ export const buildExpression = function(expression, style, isOrdgroup) {
|
|
185
197
|
* Equivalent to buildExpression, but wraps the elements in an <mrow>
|
186
198
|
* if there's more than one. Returns a single node instead of an array.
|
187
199
|
*/
|
188
|
-
export const buildExpressionRow = function(expression, style,
|
189
|
-
return makeRow(buildExpression(expression, style,
|
200
|
+
export const buildExpressionRow = function(expression, style, semisimple = false) {
|
201
|
+
return makeRow(buildExpression(expression, style, semisimple), semisimple);
|
190
202
|
};
|
191
203
|
|
192
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/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)
|
package/src/macros.js
CHANGED
@@ -436,6 +436,8 @@ defineMacro("\\quad", "\\hskip1em\\relax");
|
|
436
436
|
// \def\qquad{\hskip2em\relax}
|
437
437
|
defineMacro("\\qquad", "\\hskip2em\\relax");
|
438
438
|
|
439
|
+
defineMacro("\\AA", "\\TextOrMath{\\Angstrom}{\\mathring{A}}\\relax")
|
440
|
+
|
439
441
|
// \tag@in@display form of \tag
|
440
442
|
defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
|
441
443
|
defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
|
package/src/postProcess.js
CHANGED
package/src/symbols.js
CHANGED
@@ -132,8 +132,8 @@ defineSymbol(math, textord, "\u2207", "\\nabla", true);
|
|
132
132
|
defineSymbol(math, textord, "\u266d", "\\flat", true);
|
133
133
|
defineSymbol(math, textord, "\u2113", "\\ell", true);
|
134
134
|
defineSymbol(math, textord, "\u266e", "\\natural", true);
|
135
|
-
defineSymbol(math, textord, "Å", "\\
|
136
|
-
defineSymbol(text, textord, "Å", "\\
|
135
|
+
defineSymbol(math, textord, "Å", "\\Angstrom", true);
|
136
|
+
defineSymbol(text, textord, "Å", "\\Angstrom", true);
|
137
137
|
defineSymbol(math, textord, "\u2663", "\\clubsuit", true);
|
138
138
|
defineSymbol(math, textord, "\u2667", "\\varclubsuit", true);
|
139
139
|
defineSymbol(math, textord, "\u2118", "\\wp", true);
|