katex 0.10.0-rc → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +214 -126
- package/README.md +18 -17
- package/cli.js +5 -1
- package/contrib/auto-render/README.md +1 -1
- package/contrib/auto-render/auto-render.js +4 -1
- package/contrib/auto-render/test/auto-render-spec.js +17 -0
- package/contrib/copy-tex/README.md +8 -2
- package/contrib/copy-tex/copy-tex.js +0 -1
- package/contrib/copy-tex/copy-tex.webpack.js +6 -0
- package/contrib/mathtex-script-type/README.md +10 -6
- package/contrib/mhchem/README.md +19 -0
- package/contrib/mhchem/mhchem.js +1695 -0
- package/contrib/mhchem/mhchem.patch +235 -0
- package/dist/README.md +18 -17
- package/dist/contrib/auto-render.js +179 -161
- package/dist/contrib/auto-render.min.js +1 -1
- package/dist/contrib/auto-render.mjs +215 -0
- package/dist/contrib/copy-tex.js +84 -62
- package/dist/contrib/copy-tex.min.css +1 -1
- package/dist/contrib/copy-tex.min.js +1 -1
- package/dist/contrib/copy-tex.mjs +85 -0
- package/dist/contrib/mathtex-script-type.js +17 -14
- package/dist/contrib/mathtex-script-type.mjs +24 -0
- package/dist/contrib/mhchem.js +3241 -0
- package/dist/contrib/mhchem.min.js +1 -0
- package/dist/contrib/mhchem.mjs +3109 -0
- package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/katex.css +24 -9
- package/dist/katex.js +13295 -12413
- package/dist/katex.min.css +1 -1
- package/dist/katex.min.js +1 -1
- package/dist/katex.mjs +13388 -11826
- package/katex.js +1 -2
- package/package.json +60 -48
- package/src/Lexer.js +25 -25
- package/src/MacroExpander.js +0 -1
- package/src/Options.js +11 -75
- package/src/Parser.js +231 -313
- package/src/Settings.js +6 -0
- package/src/buildCommon.js +140 -103
- package/src/buildHTML.js +125 -121
- package/src/buildMathML.js +14 -4
- package/src/buildTree.js +16 -10
- package/src/delimiter.js +4 -3
- package/src/domTree.js +91 -44
- package/src/environments/array.js +120 -7
- package/src/fontMetrics.js +3 -2
- package/src/functions/arrow.js +21 -7
- package/src/functions/color.js +2 -37
- package/src/functions/delimsizing.js +18 -11
- package/src/functions/enclose.js +19 -4
- package/src/functions/environment.js +35 -4
- package/src/functions/font.js +1 -2
- package/src/functions/genfrac.js +35 -20
- package/src/functions/href.js +5 -3
- package/src/functions/includegraphics.js +146 -0
- package/src/functions/mclass.js +1 -0
- package/src/functions/op.js +21 -32
- package/src/functions/operatorname.js +1 -2
- package/src/functions/ordgroup.js +4 -0
- package/src/functions/phantom.js +7 -3
- package/src/functions/rule.js +20 -9
- package/src/functions/sizing.js +2 -4
- package/src/functions/smash.js +5 -2
- package/src/functions/sqrt.js +1 -4
- package/src/functions/styling.js +0 -1
- package/src/functions/supsub.js +6 -2
- package/src/functions/symbolsOp.js +4 -0
- package/src/functions/symbolsSpacing.js +29 -6
- package/src/functions/tag.js +20 -4
- package/src/functions/text.js +6 -4
- package/src/functions/verb.js +16 -4
- package/src/functions.js +2 -0
- package/src/katex.less +35 -12
- package/src/macros.js +161 -36
- package/src/mathMLTree.js +17 -19
- package/src/parseNode.js +27 -1
- package/src/stretchy.js +3 -1
- package/src/svgGeometry.js +1 -1
- package/src/symbols.js +39 -17
- package/src/tree.js +0 -4
- package/src/types.js +4 -3
- package/src/unicodeMake.js +1 -1
- package/src/utils.js +1 -62
- package/src/wide-character.js +2 -2
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import defineFunction from "../defineFunction";
|
|
3
|
+
import type {Measurement} from "../units";
|
|
4
|
+
import {calculateSize, validUnit} from "../units";
|
|
5
|
+
import ParseError from "../ParseError";
|
|
6
|
+
import {Img} from "../domTree";
|
|
7
|
+
import mathMLTree from "../mathMLTree";
|
|
8
|
+
import {assertNodeType} from "../parseNode";
|
|
9
|
+
import type {CssStyle} from "../domTree";
|
|
10
|
+
|
|
11
|
+
const sizeData = function(str: string): Measurement {
|
|
12
|
+
if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
|
|
13
|
+
// str is a number with no unit specified.
|
|
14
|
+
// default unit is bp, per graphix package.
|
|
15
|
+
return {number: +str, unit: "bp"};
|
|
16
|
+
} else {
|
|
17
|
+
const match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(str);
|
|
18
|
+
if (!match) {
|
|
19
|
+
throw new ParseError("Invalid size: '" + str
|
|
20
|
+
+ "' in \\includegraphics");
|
|
21
|
+
}
|
|
22
|
+
const data = {
|
|
23
|
+
number: +(match[1] + match[2]), // sign + magnitude, cast to number
|
|
24
|
+
unit: match[3],
|
|
25
|
+
};
|
|
26
|
+
if (!validUnit(data)) {
|
|
27
|
+
throw new ParseError("Invalid unit: '" + data.unit
|
|
28
|
+
+ "' in \\includegraphics.");
|
|
29
|
+
}
|
|
30
|
+
return data;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
defineFunction({
|
|
35
|
+
type: "includegraphics",
|
|
36
|
+
names: ["\\includegraphics"],
|
|
37
|
+
props: {
|
|
38
|
+
numArgs: 1,
|
|
39
|
+
numOptionalArgs: 1,
|
|
40
|
+
argTypes: ["raw", "url"],
|
|
41
|
+
allowedInText: false,
|
|
42
|
+
},
|
|
43
|
+
handler: ({parser}, args, optArgs) => {
|
|
44
|
+
let width = {number: 0, unit: "em"};
|
|
45
|
+
let height = {number: 0.9, unit: "em"}; // sorta character sized.
|
|
46
|
+
let totalheight = {number: 0, unit: "em"};
|
|
47
|
+
let alt = "";
|
|
48
|
+
|
|
49
|
+
if (optArgs[0]) {
|
|
50
|
+
const attributeStr = assertNodeType(optArgs[0], "raw").string;
|
|
51
|
+
|
|
52
|
+
// Parser.js does not parse key/value pairs. We get a string.
|
|
53
|
+
const attributes = attributeStr.split(",");
|
|
54
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
55
|
+
const keyVal = attributes[i].split("=");
|
|
56
|
+
if (keyVal.length === 2) {
|
|
57
|
+
const str = keyVal[1].trim();
|
|
58
|
+
switch (keyVal[0].trim()) {
|
|
59
|
+
case "alt":
|
|
60
|
+
alt = str;
|
|
61
|
+
break;
|
|
62
|
+
case "width":
|
|
63
|
+
width = sizeData(str);
|
|
64
|
+
break;
|
|
65
|
+
case "height":
|
|
66
|
+
height = sizeData(str);
|
|
67
|
+
break;
|
|
68
|
+
case "totalheight":
|
|
69
|
+
totalheight = sizeData(str);
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
throw new ParseError("Invalid key: '" + keyVal[0] +
|
|
73
|
+
"' in \\includegraphics.");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const src = assertNodeType(args[0], "url").url;
|
|
80
|
+
|
|
81
|
+
if (alt === "") {
|
|
82
|
+
// No alt given. Use the file name. Strip away the path.
|
|
83
|
+
alt = src;
|
|
84
|
+
alt = alt.replace(/^.*[\\/]/, '');
|
|
85
|
+
alt = alt.substring(0, alt.lastIndexOf('.'));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
type: "includegraphics",
|
|
90
|
+
mode: parser.mode,
|
|
91
|
+
alt: alt,
|
|
92
|
+
width: width,
|
|
93
|
+
height: height,
|
|
94
|
+
totalheight: totalheight,
|
|
95
|
+
src: src,
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
htmlBuilder: (group, options) => {
|
|
99
|
+
const height = calculateSize(group.height, options);
|
|
100
|
+
let depth = 0;
|
|
101
|
+
|
|
102
|
+
if (group.totalheight.number > 0) {
|
|
103
|
+
depth = calculateSize(group.totalheight, options) - height;
|
|
104
|
+
depth = Number(depth.toFixed(2));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let width = 0;
|
|
108
|
+
if (group.width.number > 0) {
|
|
109
|
+
width = calculateSize(group.width, options);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const style: CssStyle = {height: height + depth + "em"};
|
|
113
|
+
if (width > 0) {
|
|
114
|
+
style.width = width + "em";
|
|
115
|
+
}
|
|
116
|
+
if (depth > 0) {
|
|
117
|
+
style.verticalAlign = -depth + "em";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const node = new Img(group.src, group.alt, style);
|
|
121
|
+
node.height = height;
|
|
122
|
+
node.depth = depth;
|
|
123
|
+
|
|
124
|
+
return node;
|
|
125
|
+
},
|
|
126
|
+
mathmlBuilder: (group, options) => {
|
|
127
|
+
const node = new mathMLTree.MathNode("mglyph", []);
|
|
128
|
+
node.setAttribute("alt", group.alt);
|
|
129
|
+
|
|
130
|
+
const height = calculateSize(group.height, options);
|
|
131
|
+
let depth = 0;
|
|
132
|
+
if (group.totalheight.number > 0) {
|
|
133
|
+
depth = calculateSize(group.totalheight, options) - height;
|
|
134
|
+
depth = depth.toFixed(2);
|
|
135
|
+
node.setAttribute("valign", "-" + depth + "em");
|
|
136
|
+
}
|
|
137
|
+
node.setAttribute("height", height + depth + "em");
|
|
138
|
+
|
|
139
|
+
if (group.width.number > 0) {
|
|
140
|
+
const width = calculateSize(group.width, options);
|
|
141
|
+
node.setAttribute("width", width + "em");
|
|
142
|
+
}
|
|
143
|
+
node.setAttribute("src", group.src);
|
|
144
|
+
return node;
|
|
145
|
+
},
|
|
146
|
+
});
|
package/src/functions/mclass.js
CHANGED
package/src/functions/op.js
CHANGED
|
@@ -14,6 +14,11 @@ import * as mml from "../buildMathML";
|
|
|
14
14
|
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
|
|
15
15
|
import type {ParseNode} from "../parseNode";
|
|
16
16
|
|
|
17
|
+
// Most operators have a large successor symbol, but these don't.
|
|
18
|
+
const noSuccessor = [
|
|
19
|
+
"\\smallint",
|
|
20
|
+
];
|
|
21
|
+
|
|
17
22
|
// NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
|
|
18
23
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
|
19
24
|
export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
|
|
@@ -37,11 +42,6 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
|
|
|
37
42
|
|
|
38
43
|
const style = options.style;
|
|
39
44
|
|
|
40
|
-
// Most operators have a large successor symbol, but these don't.
|
|
41
|
-
const noSuccessor = [
|
|
42
|
-
"\\smallint",
|
|
43
|
-
];
|
|
44
|
-
|
|
45
45
|
let large = false;
|
|
46
46
|
if (style.size === Style.DISPLAY.size &&
|
|
47
47
|
group.symbol &&
|
|
@@ -95,7 +95,8 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
|
|
|
95
95
|
base = inner[0];
|
|
96
96
|
base.classes[0] = "mop"; // replace old mclass
|
|
97
97
|
} else {
|
|
98
|
-
base = buildCommon.makeSpan(
|
|
98
|
+
base = buildCommon.makeSpan(
|
|
99
|
+
["mop"], buildCommon.tryCombineChars(inner), options);
|
|
99
100
|
}
|
|
100
101
|
} else {
|
|
101
102
|
// Otherwise, this is a text operator. Build the text from the
|
|
@@ -236,12 +237,13 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
|
|
|
236
237
|
const mathmlBuilder: MathMLBuilder<"op"> = (group, options) => {
|
|
237
238
|
let node;
|
|
238
239
|
|
|
239
|
-
// TODO(emily): handle big operators using the `largeop` attribute
|
|
240
|
-
|
|
241
240
|
if (group.symbol) {
|
|
242
241
|
// This is a symbol. Just add the symbol.
|
|
243
242
|
node = new mathMLTree.MathNode(
|
|
244
243
|
"mo", [mml.makeText(group.name, group.mode)]);
|
|
244
|
+
if (utils.contains(noSuccessor, group.name)) {
|
|
245
|
+
node.setAttribute("largeop", "false");
|
|
246
|
+
}
|
|
245
247
|
} else if (group.body) {
|
|
246
248
|
// This is an operator with children. Add them.
|
|
247
249
|
node = new mathMLTree.MathNode(
|
|
@@ -253,13 +255,15 @@ const mathmlBuilder: MathMLBuilder<"op"> = (group, options) => {
|
|
|
253
255
|
// operators, like \limsup.
|
|
254
256
|
node = new mathMLTree.MathNode(
|
|
255
257
|
"mi", [new mathMLTree.TextNode(group.name.slice(1))]);
|
|
256
|
-
|
|
257
258
|
// Append an <mo>⁡</mo>.
|
|
258
259
|
// ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
|
|
259
260
|
const operator = new mathMLTree.MathNode("mo",
|
|
260
261
|
[mml.makeText("\u2061", "text")]);
|
|
261
|
-
|
|
262
|
-
|
|
262
|
+
if (group.parentIsSupSub) {
|
|
263
|
+
node = new mathMLTree.MathNode("mo", [node, operator]);
|
|
264
|
+
} else {
|
|
265
|
+
node = mathMLTree.newDocumentFragment([node, operator]);
|
|
266
|
+
}
|
|
263
267
|
}
|
|
264
268
|
|
|
265
269
|
return node;
|
|
@@ -272,7 +276,7 @@ const singleCharBigOps: {[string]: string} = {
|
|
|
272
276
|
"\u22c0": "\\bigwedge",
|
|
273
277
|
"\u22c1": "\\bigvee",
|
|
274
278
|
"\u22c2": "\\bigcap",
|
|
275
|
-
"\u22c3": "\\
|
|
279
|
+
"\u22c3": "\\bigcup",
|
|
276
280
|
"\u2a00": "\\bigodot",
|
|
277
281
|
"\u2a01": "\\bigoplus",
|
|
278
282
|
"\u2a02": "\\bigotimes",
|
|
@@ -301,6 +305,7 @@ defineFunction({
|
|
|
301
305
|
type: "op",
|
|
302
306
|
mode: parser.mode,
|
|
303
307
|
limits: true,
|
|
308
|
+
parentIsSupSub: false,
|
|
304
309
|
symbol: true,
|
|
305
310
|
name: fName,
|
|
306
311
|
};
|
|
@@ -323,6 +328,7 @@ defineFunction({
|
|
|
323
328
|
type: "op",
|
|
324
329
|
mode: parser.mode,
|
|
325
330
|
limits: false,
|
|
331
|
+
parentIsSupSub: false,
|
|
326
332
|
symbol: false,
|
|
327
333
|
body: ordargument(body),
|
|
328
334
|
};
|
|
@@ -344,26 +350,6 @@ const singleCharIntegrals: {[string]: string} = {
|
|
|
344
350
|
"\u2230": "\\oiiint",
|
|
345
351
|
};
|
|
346
352
|
|
|
347
|
-
defineFunction({
|
|
348
|
-
type: "op",
|
|
349
|
-
names: ["\\mathop"],
|
|
350
|
-
props: {
|
|
351
|
-
numArgs: 1,
|
|
352
|
-
},
|
|
353
|
-
handler: ({parser}, args) => {
|
|
354
|
-
const body = args[0];
|
|
355
|
-
return {
|
|
356
|
-
type: "op",
|
|
357
|
-
mode: parser.mode,
|
|
358
|
-
limits: false,
|
|
359
|
-
symbol: false,
|
|
360
|
-
body: ordargument(body),
|
|
361
|
-
};
|
|
362
|
-
},
|
|
363
|
-
htmlBuilder,
|
|
364
|
-
mathmlBuilder,
|
|
365
|
-
});
|
|
366
|
-
|
|
367
353
|
// No limits, not symbols
|
|
368
354
|
defineFunction({
|
|
369
355
|
type: "op",
|
|
@@ -382,6 +368,7 @@ defineFunction({
|
|
|
382
368
|
type: "op",
|
|
383
369
|
mode: parser.mode,
|
|
384
370
|
limits: false,
|
|
371
|
+
parentIsSupSub: false,
|
|
385
372
|
symbol: false,
|
|
386
373
|
name: funcName,
|
|
387
374
|
};
|
|
@@ -404,6 +391,7 @@ defineFunction({
|
|
|
404
391
|
type: "op",
|
|
405
392
|
mode: parser.mode,
|
|
406
393
|
limits: true,
|
|
394
|
+
parentIsSupSub: false,
|
|
407
395
|
symbol: false,
|
|
408
396
|
name: funcName,
|
|
409
397
|
};
|
|
@@ -431,6 +419,7 @@ defineFunction({
|
|
|
431
419
|
type: "op",
|
|
432
420
|
mode: parser.mode,
|
|
433
421
|
limits: false,
|
|
422
|
+
parentIsSupSub: false,
|
|
434
423
|
symbol: true,
|
|
435
424
|
name: fName,
|
|
436
425
|
};
|
|
@@ -101,8 +101,7 @@ defineFunction({
|
|
|
101
101
|
if (isAllString) {
|
|
102
102
|
// Write a single TextNode instead of multiple nested tags.
|
|
103
103
|
const word = expression.map(node => node.toText()).join("");
|
|
104
|
-
|
|
105
|
-
expression = [new mathMLTree.TextNode(word, false)];
|
|
104
|
+
expression = [new mathMLTree.TextNode(word)];
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
const identifier = new mathMLTree.MathNode("mi", expression);
|
|
@@ -8,6 +8,10 @@ import * as mml from "../buildMathML";
|
|
|
8
8
|
defineFunctionBuilders({
|
|
9
9
|
type: "ordgroup",
|
|
10
10
|
htmlBuilder(group, options) {
|
|
11
|
+
if (group.semisimple) {
|
|
12
|
+
return buildCommon.makeFragment(
|
|
13
|
+
html.buildExpression(group.body, options, false));
|
|
14
|
+
}
|
|
11
15
|
return buildCommon.makeSpan(
|
|
12
16
|
["mord"], html.buildExpression(group.body, options, true), options);
|
|
13
17
|
},
|
package/src/functions/phantom.js
CHANGED
|
@@ -71,12 +71,15 @@ defineFunction({
|
|
|
71
71
|
children: [{type: "elem", elem: node}],
|
|
72
72
|
}, options);
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
// For spacing, TeX treats \smash as a math group (same spacing as ord).
|
|
75
|
+
return buildCommon.makeSpan(["mord"], [node], options);
|
|
75
76
|
},
|
|
76
77
|
mathmlBuilder: (group, options) => {
|
|
77
78
|
const inner = mml.buildExpression(ordargument(group.body), options);
|
|
78
|
-
const
|
|
79
|
+
const phantom = new mathMLTree.MathNode("mphantom", inner);
|
|
80
|
+
const node = new mathMLTree.MathNode("mpadded", [phantom]);
|
|
79
81
|
node.setAttribute("height", "0px");
|
|
82
|
+
node.setAttribute("depth", "0px");
|
|
80
83
|
return node;
|
|
81
84
|
},
|
|
82
85
|
});
|
|
@@ -106,7 +109,8 @@ defineFunction({
|
|
|
106
109
|
},
|
|
107
110
|
mathmlBuilder: (group, options) => {
|
|
108
111
|
const inner = mml.buildExpression(ordargument(group.body), options);
|
|
109
|
-
const
|
|
112
|
+
const phantom = new mathMLTree.MathNode("mphantom", inner);
|
|
113
|
+
const node = new mathMLTree.MathNode("mpadded", [phantom]);
|
|
110
114
|
node.setAttribute("width", "0px");
|
|
111
115
|
return node;
|
|
112
116
|
},
|
package/src/functions/rule.js
CHANGED
|
@@ -30,13 +30,9 @@ defineFunction({
|
|
|
30
30
|
const rule = buildCommon.makeSpan(["mord", "rule"], [], options);
|
|
31
31
|
|
|
32
32
|
// Calculate the shift, width, and height of the rule, and account for units
|
|
33
|
-
let shift = 0;
|
|
34
|
-
if (group.shift) {
|
|
35
|
-
shift = calculateSize(group.shift, options);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
33
|
const width = calculateSize(group.width, options);
|
|
39
34
|
const height = calculateSize(group.height, options);
|
|
35
|
+
const shift = (group.shift) ? calculateSize(group.shift, options) : 0;
|
|
40
36
|
|
|
41
37
|
// Style the rule to the right size
|
|
42
38
|
rule.style.borderRightWidth = width + "em";
|
|
@@ -55,10 +51,25 @@ defineFunction({
|
|
|
55
51
|
return rule;
|
|
56
52
|
},
|
|
57
53
|
mathmlBuilder(group, options) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
54
|
+
const width = calculateSize(group.width, options);
|
|
55
|
+
const height = calculateSize(group.height, options);
|
|
56
|
+
const shift = (group.shift) ? calculateSize(group.shift, options) : 0;
|
|
57
|
+
const color = options.color && options.getColor() || "black";
|
|
58
|
+
|
|
59
|
+
const rule = new mathMLTree.MathNode("mspace");
|
|
60
|
+
rule.setAttribute("mathbackground", color);
|
|
61
|
+
rule.setAttribute("width", width + "em");
|
|
62
|
+
rule.setAttribute("height", height + "em");
|
|
63
|
+
|
|
64
|
+
const wrapper = new mathMLTree.MathNode("mpadded", [rule]);
|
|
65
|
+
if (shift >= 0) {
|
|
66
|
+
wrapper.setAttribute("height", "+" + shift + "em");
|
|
67
|
+
} else {
|
|
68
|
+
wrapper.setAttribute("height", shift + "em");
|
|
69
|
+
wrapper.setAttribute("depth", "+" + (-shift) + "em");
|
|
70
|
+
}
|
|
71
|
+
wrapper.setAttribute("voffset", shift + "em");
|
|
61
72
|
|
|
62
|
-
return
|
|
73
|
+
return wrapper;
|
|
63
74
|
},
|
|
64
75
|
});
|
package/src/functions/sizing.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import buildCommon from "../buildCommon";
|
|
3
3
|
import defineFunction from "../defineFunction";
|
|
4
4
|
import mathMLTree from "../mathMLTree";
|
|
5
|
-
import utils from "../utils";
|
|
6
5
|
|
|
7
6
|
import * as html from "../buildHTML";
|
|
8
7
|
import * as mml from "../buildMathML";
|
|
@@ -23,7 +22,7 @@ export function sizingGroup(
|
|
|
23
22
|
// Add size-resetting classes to the inner list and set maxFontSize
|
|
24
23
|
// manually. Handle nested size changes.
|
|
25
24
|
for (let i = 0; i < inner.length; i++) {
|
|
26
|
-
const pos =
|
|
25
|
+
const pos = inner[i].classes.indexOf("sizing");
|
|
27
26
|
if (pos < 0) {
|
|
28
27
|
Array.prototype.push.apply(inner[i].classes,
|
|
29
28
|
options.sizingClasses(baseOptions));
|
|
@@ -62,14 +61,13 @@ defineFunction({
|
|
|
62
61
|
allowedInText: true,
|
|
63
62
|
},
|
|
64
63
|
handler: ({breakOnTokenText, funcName, parser}, args) => {
|
|
65
|
-
parser.consumeSpaces();
|
|
66
64
|
const body = parser.parseExpression(false, breakOnTokenText);
|
|
67
65
|
|
|
68
66
|
return {
|
|
69
67
|
type: "sizing",
|
|
70
68
|
mode: parser.mode,
|
|
71
69
|
// Figure out what size to use based on the list of functions above
|
|
72
|
-
size:
|
|
70
|
+
size: sizeFuncs.indexOf(funcName) + 1,
|
|
73
71
|
body,
|
|
74
72
|
};
|
|
75
73
|
},
|
package/src/functions/smash.js
CHANGED
|
@@ -55,7 +55,7 @@ defineFunction({
|
|
|
55
55
|
},
|
|
56
56
|
htmlBuilder: (group, options) => {
|
|
57
57
|
const node = buildCommon.makeSpan(
|
|
58
|
-
[
|
|
58
|
+
[], [html.buildGroup(group.body, options)]);
|
|
59
59
|
|
|
60
60
|
if (!group.smashHeight && !group.smashDepth) {
|
|
61
61
|
return node;
|
|
@@ -85,10 +85,13 @@ defineFunction({
|
|
|
85
85
|
// makeVList applies "display: table-cell", which prevents the browser
|
|
86
86
|
// from acting on that line height. So we'll call makeVList now.
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
const smashedNode = buildCommon.makeVList({
|
|
89
89
|
positionType: "firstBaseline",
|
|
90
90
|
children: [{type: "elem", elem: node}],
|
|
91
91
|
}, options);
|
|
92
|
+
|
|
93
|
+
// For spacing, TeX treats \hphantom as a math group (same spacing as ord).
|
|
94
|
+
return buildCommon.makeSpan(["mord"], [smashedNode], options);
|
|
92
95
|
},
|
|
93
96
|
mathmlBuilder: (group, options) => {
|
|
94
97
|
const node = new mathMLTree.MathNode(
|
package/src/functions/sqrt.js
CHANGED
|
@@ -5,7 +5,6 @@ import mathMLTree from "../mathMLTree";
|
|
|
5
5
|
import delimiter from "../delimiter";
|
|
6
6
|
import Style from "../Style";
|
|
7
7
|
|
|
8
|
-
import {DocumentFragment} from "../tree";
|
|
9
8
|
import * as html from "../buildHTML";
|
|
10
9
|
import * as mml from "../buildMathML";
|
|
11
10
|
|
|
@@ -39,9 +38,7 @@ defineFunction({
|
|
|
39
38
|
|
|
40
39
|
// Some groups can return document fragments. Handle those by wrapping
|
|
41
40
|
// them in a span.
|
|
42
|
-
|
|
43
|
-
inner = buildCommon.makeSpan([], [inner], options);
|
|
44
|
-
}
|
|
41
|
+
inner = buildCommon.wrapFragment(inner, options);
|
|
45
42
|
|
|
46
43
|
// Calculate the minimum size for the \surd delimiter
|
|
47
44
|
const metrics = options.fontMetrics();
|
package/src/functions/styling.js
CHANGED
|
@@ -25,7 +25,6 @@ defineFunction({
|
|
|
25
25
|
},
|
|
26
26
|
handler({breakOnTokenText, funcName, parser}, args) {
|
|
27
27
|
// parse out the implicit body
|
|
28
|
-
parser.consumeSpaces();
|
|
29
28
|
const body = parser.parseExpression(true, breakOnTokenText);
|
|
30
29
|
|
|
31
30
|
// TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
|
package/src/functions/supsub.js
CHANGED
|
@@ -201,6 +201,10 @@ defineFunctionBuilders({
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
if (group.base && group.base.type === "op") {
|
|
205
|
+
group.base.parentIsSupSub = true;
|
|
206
|
+
}
|
|
207
|
+
|
|
204
208
|
const children = [mml.buildGroup(group.base, options)];
|
|
205
209
|
|
|
206
210
|
if (group.sub) {
|
|
@@ -217,7 +221,7 @@ defineFunctionBuilders({
|
|
|
217
221
|
} else if (!group.sub) {
|
|
218
222
|
const base = group.base;
|
|
219
223
|
if (base && base.type === "op" && base.limits &&
|
|
220
|
-
options.style === Style.DISPLAY) {
|
|
224
|
+
(options.style === Style.DISPLAY || base.alwaysHandleSupSub)) {
|
|
221
225
|
nodeType = "mover";
|
|
222
226
|
} else {
|
|
223
227
|
nodeType = "msup";
|
|
@@ -225,7 +229,7 @@ defineFunctionBuilders({
|
|
|
225
229
|
} else if (!group.sup) {
|
|
226
230
|
const base = group.base;
|
|
227
231
|
if (base && base.type === "op" && base.limits &&
|
|
228
|
-
options.style === Style.DISPLAY) {
|
|
232
|
+
(options.style === Style.DISPLAY || base.alwaysHandleSupSub)) {
|
|
229
233
|
nodeType = "munder";
|
|
230
234
|
} else {
|
|
231
235
|
nodeType = "msub";
|
|
@@ -23,6 +23,10 @@ defineFunctionBuilders({
|
|
|
23
23
|
}
|
|
24
24
|
} else if (group.family === "punct") {
|
|
25
25
|
node.setAttribute("separator", "true");
|
|
26
|
+
} else if (group.family === "open" || group.family === "close") {
|
|
27
|
+
// Delims built here should not stretch vertically.
|
|
28
|
+
// See delimsizing.js for stretchy delims.
|
|
29
|
+
node.setAttribute("stretchy", "false");
|
|
26
30
|
}
|
|
27
31
|
return node;
|
|
28
32
|
},
|
|
@@ -4,13 +4,36 @@ import buildCommon from "../buildCommon";
|
|
|
4
4
|
import mathMLTree from "../mathMLTree";
|
|
5
5
|
import ParseError from "../ParseError";
|
|
6
6
|
|
|
7
|
+
// A map of CSS-based spacing functions to their CSS class.
|
|
8
|
+
const cssSpace: {[string]: string} = {
|
|
9
|
+
"\\nobreak": "nobreak",
|
|
10
|
+
"\\allowbreak": "allowbreak",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// A lookup table to determine whether a spacing function/symbol should be
|
|
14
|
+
// treated like a regular space character. If a symbol or command is a key
|
|
15
|
+
// in this table, then it should be a regular space character. Furthermore,
|
|
16
|
+
// the associated value may have a `className` specifying an extra CSS class
|
|
17
|
+
// to add to the created `span`.
|
|
18
|
+
const regularSpace: {[string]: { className?: string }} = {
|
|
19
|
+
" ": {},
|
|
20
|
+
"\\ ": {},
|
|
21
|
+
"~": {
|
|
22
|
+
className: "nobreak",
|
|
23
|
+
},
|
|
24
|
+
"\\space": {},
|
|
25
|
+
"\\nobreakspace": {
|
|
26
|
+
className: "nobreak",
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
7
30
|
// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
|
|
8
31
|
// src/symbols.js.
|
|
9
32
|
defineFunctionBuilders({
|
|
10
33
|
type: "spacing",
|
|
11
34
|
htmlBuilder(group, options) {
|
|
12
|
-
if (
|
|
13
|
-
const className =
|
|
35
|
+
if (regularSpace.hasOwnProperty(group.text)) {
|
|
36
|
+
const className = regularSpace[group.text].className || "";
|
|
14
37
|
// Spaces are generated by adding an actual space. Each of these
|
|
15
38
|
// things has an entry in the symbols table, so these will be turned
|
|
16
39
|
// into appropriate outputs.
|
|
@@ -23,10 +46,10 @@ defineFunctionBuilders({
|
|
|
23
46
|
[buildCommon.mathsym(group.text, group.mode, options)],
|
|
24
47
|
options);
|
|
25
48
|
}
|
|
26
|
-
} else if (
|
|
49
|
+
} else if (cssSpace.hasOwnProperty(group.text)) {
|
|
27
50
|
// Spaces based on just a CSS class.
|
|
28
51
|
return buildCommon.makeSpan(
|
|
29
|
-
["mspace",
|
|
52
|
+
["mspace", cssSpace[group.text]],
|
|
30
53
|
[], options);
|
|
31
54
|
} else {
|
|
32
55
|
throw new ParseError(`Unknown type of space "${group.text}"`);
|
|
@@ -35,10 +58,10 @@ defineFunctionBuilders({
|
|
|
35
58
|
mathmlBuilder(group, options) {
|
|
36
59
|
let node;
|
|
37
60
|
|
|
38
|
-
if (
|
|
61
|
+
if (regularSpace.hasOwnProperty(group.text)) {
|
|
39
62
|
node = new mathMLTree.MathNode(
|
|
40
63
|
"mtext", [new mathMLTree.TextNode("\u00a0")]);
|
|
41
|
-
} else if (
|
|
64
|
+
} else if (cssSpace.hasOwnProperty(group.text)) {
|
|
42
65
|
// CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
|
|
43
66
|
return new mathMLTree.MathNode("mspace");
|
|
44
67
|
} else {
|
package/src/functions/tag.js
CHANGED
|
@@ -4,21 +4,37 @@ import mathMLTree from "../mathMLTree";
|
|
|
4
4
|
|
|
5
5
|
import * as mml from "../buildMathML";
|
|
6
6
|
|
|
7
|
+
const pad = () => {
|
|
8
|
+
const padNode = new mathMLTree.MathNode("mtd", []);
|
|
9
|
+
padNode.setAttribute("width", "50%");
|
|
10
|
+
return padNode;
|
|
11
|
+
};
|
|
12
|
+
|
|
7
13
|
defineFunctionBuilders({
|
|
8
14
|
type: "tag",
|
|
9
15
|
mathmlBuilder(group, options) {
|
|
10
16
|
const table = new mathMLTree.MathNode("mtable", [
|
|
11
|
-
new mathMLTree.MathNode("
|
|
17
|
+
new mathMLTree.MathNode("mtr", [
|
|
18
|
+
pad(),
|
|
12
19
|
new mathMLTree.MathNode("mtd", [
|
|
13
|
-
mml.buildExpressionRow(group.
|
|
20
|
+
mml.buildExpressionRow(group.body, options),
|
|
14
21
|
]),
|
|
22
|
+
pad(),
|
|
15
23
|
new mathMLTree.MathNode("mtd", [
|
|
16
|
-
mml.buildExpressionRow(group.
|
|
24
|
+
mml.buildExpressionRow(group.tag, options),
|
|
17
25
|
]),
|
|
18
26
|
]),
|
|
19
27
|
]);
|
|
20
|
-
table.setAttribute("
|
|
28
|
+
table.setAttribute("width", "100%");
|
|
21
29
|
return table;
|
|
30
|
+
|
|
31
|
+
// TODO: Left-aligned tags.
|
|
32
|
+
// Currently, the group and options passed here do not contain
|
|
33
|
+
// enough info to set tag alignment. `leqno` is in Settings but it is
|
|
34
|
+
// not passed to Options. On the HTML side, leqno is
|
|
35
|
+
// set by a CSS class applied in buildTree.js. That would have worked
|
|
36
|
+
// in MathML if browsers supported <mlabeledtr>. Since they don't, we
|
|
37
|
+
// need to rewrite the way this function is called.
|
|
22
38
|
},
|
|
23
39
|
});
|
|
24
40
|
|
package/src/functions/text.js
CHANGED
|
@@ -13,10 +13,12 @@ const textFontFamilies = {
|
|
|
13
13
|
|
|
14
14
|
const textFontWeights = {
|
|
15
15
|
"\\textbf": "textbf",
|
|
16
|
+
"\\textmd": "textmd",
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const textFontShapes = {
|
|
19
20
|
"\\textit": "textit",
|
|
21
|
+
"\\textup": "textup",
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const optionsWithFont = (group, options) => {
|
|
@@ -39,9 +41,9 @@ defineFunction({
|
|
|
39
41
|
// Font families
|
|
40
42
|
"\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
|
|
41
43
|
// Font weights
|
|
42
|
-
"\\textbf",
|
|
44
|
+
"\\textbf", "\\textmd",
|
|
43
45
|
// Font Shapes
|
|
44
|
-
"\\textit",
|
|
46
|
+
"\\textit", "\\textup",
|
|
45
47
|
],
|
|
46
48
|
props: {
|
|
47
49
|
numArgs: 1,
|
|
@@ -62,8 +64,8 @@ defineFunction({
|
|
|
62
64
|
htmlBuilder(group, options) {
|
|
63
65
|
const newOptions = optionsWithFont(group, options);
|
|
64
66
|
const inner = html.buildExpression(group.body, newOptions, true);
|
|
65
|
-
buildCommon.
|
|
66
|
-
|
|
67
|
+
return buildCommon.makeSpan(
|
|
68
|
+
["mord", "text"], buildCommon.tryCombineChars(inner), newOptions);
|
|
67
69
|
},
|
|
68
70
|
mathmlBuilder(group, options) {
|
|
69
71
|
const newOptions = optionsWithFont(group, options);
|