temml 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/contrib/auto-render/README.md +89 -0
  4. package/contrib/auto-render/auto-render.js +128 -0
  5. package/contrib/auto-render/dist/auto-render.js +217 -0
  6. package/contrib/auto-render/dist/auto-render.min.js +1 -0
  7. package/contrib/auto-render/splitAtDelimiters.js +84 -0
  8. package/contrib/auto-render/test/auto-render-spec.js +234 -0
  9. package/contrib/auto-render/test/auto-render.js +217 -0
  10. package/contrib/auto-render/test/test_page.html +59 -0
  11. package/contrib/mhchem/README.md +26 -0
  12. package/contrib/mhchem/mhchem.js +1705 -0
  13. package/contrib/mhchem/mhchem.min.js +1 -0
  14. package/contrib/physics/README.md +20 -0
  15. package/contrib/physics/physics.js +131 -0
  16. package/contrib/texvc/README.md +23 -0
  17. package/contrib/texvc/texvc.js +61 -0
  18. package/dist/Temml-Asana.css +201 -0
  19. package/dist/Temml-Latin-Modern.css +216 -0
  20. package/dist/Temml-Libertinus.css +214 -0
  21. package/dist/Temml-Local.css +194 -0
  22. package/dist/Temml-STIX2.css +203 -0
  23. package/dist/Temml.woff2 +0 -0
  24. package/dist/temml.cjs +13122 -0
  25. package/dist/temml.js +11225 -0
  26. package/dist/temml.min.js +1 -0
  27. package/dist/temml.mjs +13120 -0
  28. package/dist/temmlPostProcess.js +70 -0
  29. package/package.json +34 -0
  30. package/src/Lexer.js +121 -0
  31. package/src/MacroExpander.js +437 -0
  32. package/src/Namespace.js +107 -0
  33. package/src/ParseError.js +64 -0
  34. package/src/Parser.js +977 -0
  35. package/src/Settings.js +49 -0
  36. package/src/SourceLocation.js +29 -0
  37. package/src/Style.js +144 -0
  38. package/src/Token.js +40 -0
  39. package/src/buildMathML.js +235 -0
  40. package/src/constants.js +25 -0
  41. package/src/defineEnvironment.js +25 -0
  42. package/src/defineFunction.js +69 -0
  43. package/src/defineMacro.js +11 -0
  44. package/src/domTree.js +185 -0
  45. package/src/environments/array.js +791 -0
  46. package/src/environments/cd.js +252 -0
  47. package/src/environments.js +8 -0
  48. package/src/functions/accent.js +127 -0
  49. package/src/functions/accentunder.js +38 -0
  50. package/src/functions/arrow.js +204 -0
  51. package/src/functions/cancelto.js +36 -0
  52. package/src/functions/char.js +33 -0
  53. package/src/functions/color.js +253 -0
  54. package/src/functions/cr.js +46 -0
  55. package/src/functions/def.js +259 -0
  56. package/src/functions/delimsizing.js +304 -0
  57. package/src/functions/enclose.js +193 -0
  58. package/src/functions/envTag.js +38 -0
  59. package/src/functions/environment.js +59 -0
  60. package/src/functions/font.js +123 -0
  61. package/src/functions/genfrac.js +333 -0
  62. package/src/functions/hbox.js +29 -0
  63. package/src/functions/horizBrace.js +32 -0
  64. package/src/functions/href.js +90 -0
  65. package/src/functions/html.js +95 -0
  66. package/src/functions/includegraphics.js +131 -0
  67. package/src/functions/kern.js +75 -0
  68. package/src/functions/label.js +29 -0
  69. package/src/functions/lap.js +75 -0
  70. package/src/functions/math.js +40 -0
  71. package/src/functions/mathchoice.js +41 -0
  72. package/src/functions/mclass.js +201 -0
  73. package/src/functions/multiscript.js +91 -0
  74. package/src/functions/not.js +46 -0
  75. package/src/functions/op.js +338 -0
  76. package/src/functions/operatorname.js +139 -0
  77. package/src/functions/ordgroup.js +9 -0
  78. package/src/functions/phantom.js +73 -0
  79. package/src/functions/pmb.js +31 -0
  80. package/src/functions/raise.js +68 -0
  81. package/src/functions/ref.js +28 -0
  82. package/src/functions/relax.js +16 -0
  83. package/src/functions/rule.js +52 -0
  84. package/src/functions/sizing.js +64 -0
  85. package/src/functions/smash.js +66 -0
  86. package/src/functions/sqrt.js +31 -0
  87. package/src/functions/styling.js +58 -0
  88. package/src/functions/supsub.js +135 -0
  89. package/src/functions/symbolsOp.js +53 -0
  90. package/src/functions/symbolsOrd.js +102 -0
  91. package/src/functions/symbolsSpacing.js +53 -0
  92. package/src/functions/tag.js +8 -0
  93. package/src/functions/text.js +75 -0
  94. package/src/functions/tip.js +63 -0
  95. package/src/functions/toggle.js +13 -0
  96. package/src/functions/verb.js +33 -0
  97. package/src/functions.js +57 -0
  98. package/src/linebreaking.js +159 -0
  99. package/src/macros.js +708 -0
  100. package/src/mathMLTree.js +175 -0
  101. package/src/parseNode.js +42 -0
  102. package/src/parseTree.js +40 -0
  103. package/src/postProcess.js +57 -0
  104. package/src/replace.js +225 -0
  105. package/src/stretchy.js +66 -0
  106. package/src/svg.js +110 -0
  107. package/src/symbols.js +972 -0
  108. package/src/tree.js +50 -0
  109. package/src/unicodeAccents.js +16 -0
  110. package/src/unicodeScripts.js +119 -0
  111. package/src/unicodeSupOrSub.js +108 -0
  112. package/src/unicodeSymbolBuilder.js +31 -0
  113. package/src/unicodeSymbols.js +320 -0
  114. package/src/units.js +109 -0
  115. package/src/utils.js +109 -0
  116. package/src/variant.js +103 -0
  117. package/temml.js +181 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * This is a module for storing settings passed into Temml. It correctly handles
3
+ * default settings.
4
+ */
5
+
6
+ import utils from "./utils";
7
+
8
+ /**
9
+ * The main Settings object
10
+ */
11
+ export default class Settings {
12
+ constructor(options) {
13
+ // allow null options
14
+ options = options || {};
15
+ this.displayMode = utils.deflt(options.displayMode, false); // boolean
16
+ this.annotate = utils.deflt(options.annotate, false) // boolean
17
+ this.leqno = utils.deflt(options.leqno, false); // boolean
18
+ this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string
19
+ this.macros = options.macros || {};
20
+ this.wrap = utils.deflt(options.wrap, "none") // "none" | "tex" | "="
21
+ this.xml = utils.deflt(options.xml, false); // boolean
22
+ this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean
23
+ this.strict = utils.deflt(options.strict, false); // boolean
24
+ this.trust = utils.deflt(options.trust, false); // trust context. See html.js.
25
+ this.maxSize = (options.maxSize === undefined
26
+ ? [Infinity, Infinity]
27
+ : Array.isArray(options.maxSize)
28
+ ? options.maxSize
29
+ : [Infinity, Infinity]
30
+ )
31
+ this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number
32
+ }
33
+
34
+ /**
35
+ * Check whether to test potentially dangerous input, and return
36
+ * `true` (trusted) or `false` (untrusted). The sole argument `context`
37
+ * should be an object with `command` field specifying the relevant LaTeX
38
+ * command (as a string starting with `\`), and any other arguments, etc.
39
+ * If `context` has a `url` field, a `protocol` field will automatically
40
+ * get added by this function (changing the specified object).
41
+ */
42
+ isTrusted(context) {
43
+ if (context.url && !context.protocol) {
44
+ context.protocol = utils.protocolFromUrl(context.url);
45
+ }
46
+ const trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
47
+ return Boolean(trust);
48
+ }
49
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Lexing or parsing positional information for error reporting.
3
+ * This object is immutable.
4
+ */
5
+ export default class SourceLocation {
6
+ constructor(lexer, start, end) {
7
+ this.lexer = lexer; // Lexer holding the input string.
8
+ this.start = start; // Start offset, zero-based inclusive.
9
+ this.end = end; // End offset, zero-based exclusive.
10
+ }
11
+
12
+ /**
13
+ * Merges two `SourceLocation`s from location providers, given they are
14
+ * provided in order of appearance.
15
+ * - Returns the first one's location if only the first is provided.
16
+ * - Returns a merged range of the first and the last if both are provided
17
+ * and their lexers match.
18
+ * - Otherwise, returns null.
19
+ */
20
+ static range(first, second) {
21
+ if (!second) {
22
+ return first && first.loc;
23
+ } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
24
+ return null;
25
+ } else {
26
+ return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
27
+ }
28
+ }
29
+ }
package/src/Style.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * This file contains information about the style that the mathmlBuilder carries
3
+ * around with it. Data is held in an `Style` object, and when
4
+ * recursing, a new `Style` object can be created with the `.with*` functions.
5
+ */
6
+
7
+ const subOrSupLevel = [2, 2, 3, 3];
8
+
9
+ /**
10
+ * This is the main Style class. It contains the current style.level, color, and font.
11
+ *
12
+ * Style objects should not be modified. To create a new Style with
13
+ * different properties, call a `.with*` method.
14
+ */
15
+ class Style {
16
+ constructor(data) {
17
+ // Style.level can be 0 | 1 | 2 | 3, which correspond to
18
+ // displaystyle, textstyle, scriptstyle, and scriptscriptstyle.
19
+ // style.level does not directly set MathML's script level. MathML does that itself.
20
+ // We use style.level to track, not set, math style so that we can get the
21
+ // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em.
22
+ this.level = data.level;
23
+ this.color = data.color; // string | void
24
+ // A font family applies to a group of fonts (i.e. SansSerif), while a font
25
+ // represents a specific font (i.e. SansSerif Bold).
26
+ // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
27
+ this.font = data.font || ""; // string
28
+ this.fontFamily = data.fontFamily || ""; // string
29
+ this.fontSize = data.fontSize || 1.0; // number
30
+ this.fontWeight = data.fontWeight || "";
31
+ this.fontShape = data.fontShape || "";
32
+ this.maxSize = data.maxSize; // [number, number]
33
+ }
34
+
35
+ /**
36
+ * Returns a new style object with the same properties as "this". Properties
37
+ * from "extension" will be copied to the new style object.
38
+ */
39
+ extend(extension) {
40
+ const data = {
41
+ level: this.level,
42
+ color: this.color,
43
+ font: this.font,
44
+ fontFamily: this.fontFamily,
45
+ fontSize: this.fontSize,
46
+ fontWeight: this.fontWeight,
47
+ fontShape: this.fontShape,
48
+ maxSize: this.maxSize
49
+ };
50
+
51
+ for (const key in extension) {
52
+ if (Object.prototype.hasOwnProperty.call(extension, key)) {
53
+ data[key] = extension[key];
54
+ }
55
+ }
56
+
57
+ return new Style(data);
58
+ }
59
+
60
+ withLevel(n) {
61
+ return this.extend({
62
+ level: n
63
+ });
64
+ }
65
+
66
+ incrementLevel() {
67
+ return this.extend({
68
+ level: Math.min(this.level + 1, 3)
69
+ });
70
+ }
71
+
72
+ inSubOrSup() {
73
+ return this.extend({
74
+ level: subOrSupLevel[this.level]
75
+ })
76
+ }
77
+
78
+ /**
79
+ * Create a new style object with the given color.
80
+ */
81
+ withColor(color) {
82
+ return this.extend({
83
+ color: color
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Creates a new style object with the given math font or old text font.
89
+ * @type {[type]}
90
+ */
91
+ withFont(font) {
92
+ return this.extend({
93
+ font
94
+ });
95
+ }
96
+
97
+ /**
98
+ * Create a new style objects with the given fontFamily.
99
+ */
100
+ withTextFontFamily(fontFamily) {
101
+ return this.extend({
102
+ fontFamily,
103
+ font: ""
104
+ });
105
+ }
106
+
107
+ /**
108
+ * Creates a new style object with the given font size
109
+ */
110
+ withFontSize(num) {
111
+ return this.extend({
112
+ fontSize: num
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Creates a new style object with the given font weight
118
+ */
119
+ withTextFontWeight(fontWeight) {
120
+ return this.extend({
121
+ fontWeight,
122
+ font: ""
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Creates a new style object with the given font weight
128
+ */
129
+ withTextFontShape(fontShape) {
130
+ return this.extend({
131
+ fontShape,
132
+ font: ""
133
+ });
134
+ }
135
+
136
+ /**
137
+ * Gets the CSS color of the current style object
138
+ */
139
+ getColor() {
140
+ return this.color;
141
+ }
142
+ }
143
+
144
+ export default Style;
package/src/Token.js ADDED
@@ -0,0 +1,40 @@
1
+ import SourceLocation from "./SourceLocation";
2
+
3
+ /**
4
+ * Interface required to break circular dependency between Token, Lexer, and
5
+ * ParseError.
6
+ */
7
+
8
+ /**
9
+ * The resulting token returned from `lex`.
10
+ *
11
+ * It consists of the token text plus some position information.
12
+ * The position information is essentially a range in an input string,
13
+ * but instead of referencing the bare input string, we refer to the lexer.
14
+ * That way it is possible to attach extra metadata to the input string,
15
+ * like for example a file name or similar.
16
+ *
17
+ * The position information is optional, so it is OK to construct synthetic
18
+ * tokens if appropriate. Not providing available position information may
19
+ * lead to degraded error reporting, though.
20
+ */
21
+ export class Token {
22
+ constructor(
23
+ text, // the text of this token
24
+ loc
25
+ ) {
26
+ this.text = text;
27
+ this.loc = loc;
28
+ }
29
+
30
+ /**
31
+ * Given a pair of tokens (this and endToken), compute a `Token` encompassing
32
+ * the whole input range enclosed by these two.
33
+ */
34
+ range(
35
+ endToken, // last token of the range, inclusive
36
+ text // the text of the newly constructed token
37
+ ) {
38
+ return new Token(text, SourceLocation.range(this, endToken));
39
+ }
40
+ }
@@ -0,0 +1,235 @@
1
+ /**
2
+ * This file converts a parse tree into a cooresponding MathML tree. The main
3
+ * entry point is the `buildMathML` function, which takes a parse tree from the
4
+ * parser.
5
+ */
6
+
7
+ import mathMLTree from "./mathMLTree"
8
+ import ParseError from "./ParseError"
9
+ import symbols, { ligatures } from "./symbols"
10
+ import { _mathmlGroupBuilders as groupBuilders } from "./defineFunction"
11
+ import { MathNode } from "./mathMLTree"
12
+ import setLineBreaks from "./linebreaking"
13
+
14
+ /**
15
+ * Takes a symbol and converts it into a MathML text node after performing
16
+ * optional replacement from symbols.js.
17
+ */
18
+ export const makeText = function(text, mode, style) {
19
+ if (
20
+ symbols[mode][text] &&
21
+ symbols[mode][text].replace &&
22
+ text.charCodeAt(0) !== 0xd835 &&
23
+ !(
24
+ Object.prototype.hasOwnProperty.call(ligatures, text) &&
25
+ style &&
26
+ ((style.fontFamily && style.fontFamily.slice(4, 6) === "tt") ||
27
+ (style.font && style.font.slice(4, 6) === "tt"))
28
+ )
29
+ ) {
30
+ text = symbols[mode][text].replace;
31
+ }
32
+
33
+ return new mathMLTree.TextNode(text);
34
+ };
35
+
36
+ export const consolidateText = mrow => {
37
+ // If possible, consolidate adjacent <mtext> elements into a single element.
38
+ if (mrow.type !== "mrow") { return mrow }
39
+ if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{}
40
+ if (!mrow.children[0].attributes || mrow.children[0].type !== "mtext") { return mrow }
41
+ const variant = mrow.children[0].attributes.mathvariant || ""
42
+ const mtext = new mathMLTree.MathNode(
43
+ "mtext",
44
+ [new mathMLTree.TextNode(mrow.children[0].children[0].text)]
45
+ )
46
+ for (let i = 1; i < mrow.children.length; i++) {
47
+ // Check each child and, if possible, copy the character into child[0].
48
+ const localVariant = mrow.children[i].attributes.mathvariant || ""
49
+ if (mrow.children[i].type === "mrow") {
50
+ const childRow = mrow.children[i]
51
+ for (let j = 0; j < childRow.children.length; j++) {
52
+ // We'll also check the children of a mrow. One level only. No recursion.
53
+ const childVariant = childRow.children[j].attributes.mathvariant || ""
54
+ if (childVariant !== variant || childRow.children[j].type !== "mtext") {
55
+ return mrow // At least one element cannot be consolidated. Get out.
56
+ } else {
57
+ mtext.children[0].text += childRow.children[j].children[0].text
58
+ }
59
+ }
60
+ } else if (localVariant !== variant || mrow.children[i].type !== "mtext") {
61
+ return mrow
62
+ } else {
63
+ mtext.children[0].text += mrow.children[i].children[0].text
64
+ }
65
+ }
66
+ // Firefox does not render a space at either end of an <mtext> string.
67
+ // To get proper rendering, we replace leading or trailing spaces with no-break spaces.
68
+ if (mtext.children[0].text.charAt(0) === " ") {
69
+ mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1)
70
+ }
71
+ const L = mtext.children[0].text.length
72
+ if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") {
73
+ mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"
74
+ }
75
+ return mtext
76
+ }
77
+
78
+ /**
79
+ * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
80
+ * unless the array has length 1. Always returns a single node.
81
+ */
82
+ export const makeRow = function(body) {
83
+ if (body.length === 1) {
84
+ return body[0];
85
+ } else {
86
+ return new mathMLTree.MathNode("mrow", body);
87
+ }
88
+ };
89
+
90
+ const isRel = item => {
91
+ return (item.type === "atom" && item.family === "rel") ||
92
+ (item.type === "mclass" && item.mclass === "mrel")
93
+ }
94
+
95
+ /**
96
+ * Takes a list of nodes, builds them, and returns a list of the generated
97
+ * MathML nodes. Also do a couple chores along the way:
98
+ * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}.
99
+ * (2) Suppress spacing between two adjacent relations.
100
+ */
101
+ export const buildExpression = function(expression, style, isOrdgroup) {
102
+ if (expression.length === 1) {
103
+ const group = buildGroup(expression[0], style);
104
+ if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
105
+ // When TeX writers want to suppress spacing on an operator,
106
+ // they often put the operator by itself inside braces.
107
+ group.setAttribute("lspace", "0em");
108
+ group.setAttribute("rspace", "0em");
109
+ }
110
+ return [group];
111
+ }
112
+
113
+ const groups = [];
114
+ for (let i = 0; i < expression.length; i++) {
115
+ const group = buildGroup(expression[i], style);
116
+ // Suppress spacing between adjacent relations
117
+ if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) {
118
+ group.setAttribute("rspace", "0em")
119
+ }
120
+ if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) {
121
+ group.setAttribute("lspace", "0em")
122
+ }
123
+ groups.push(group);
124
+ }
125
+ return groups;
126
+ };
127
+
128
+ /**
129
+ * Equivalent to buildExpression, but wraps the elements in an <mrow>
130
+ * if there's more than one. Returns a single node instead of an array.
131
+ */
132
+ export const buildExpressionRow = function(expression, style, isOrdgroup) {
133
+ return makeRow(buildExpression(expression, style, isOrdgroup));
134
+ };
135
+
136
+ /**
137
+ * Takes a group from the parser and calls the appropriate groupBuilders function
138
+ * on it to produce a MathML node.
139
+ */
140
+ export const buildGroup = function(group, style) {
141
+ if (!group) {
142
+ return new mathMLTree.MathNode("mrow");
143
+ }
144
+
145
+ if (groupBuilders[group.type]) {
146
+ // Call the groupBuilders function
147
+ const result = groupBuilders[group.type](group, style);
148
+ return result;
149
+ } else {
150
+ throw new ParseError("Got group of unknown type: '" + group.type + "'");
151
+ }
152
+ };
153
+
154
+ const glue = _ => {
155
+ return new mathMLTree.MathNode("mtd", [], [], { padding: "0", width: "50%" })
156
+ }
157
+
158
+ const taggedExpression = (expression, tag, style, leqno) => {
159
+ tag = buildExpressionRow(tag[0].body, style)
160
+ tag = consolidateText(tag)
161
+ tag.classes.push("tml-tag")
162
+
163
+ expression = new mathMLTree.MathNode("mtd", [expression])
164
+ const rowArray = [glue(), expression, glue()]
165
+ if (leqno) {
166
+ rowArray[0].children.push(tag)
167
+ rowArray[0].style.textAlign = "-webkit-left"
168
+ } else {
169
+ rowArray[2].children.push(tag)
170
+ rowArray[2].style.textAlign = "-webkit-right"
171
+ }
172
+ const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"])
173
+ const table = new mathMLTree.MathNode("mtable", [mtr])
174
+ table.style.width = "100%"
175
+ table.setAttribute("displaystyle", "true")
176
+ return table
177
+ }
178
+
179
+ /**
180
+ * Takes a full parse tree and settings and builds a MathML representation of
181
+ * it.
182
+ */
183
+ export default function buildMathML(tree, texExpression, style, settings) {
184
+ // Strip off outer tag wrapper for processing below.
185
+ let tag = null
186
+ if (tree.length === 1 && tree[0].type === "tag") {
187
+ tag = tree[0].tag
188
+ tree = tree[0].body
189
+ }
190
+
191
+ const expression = buildExpression(tree, style);
192
+ const wrap = (settings.displayMode || settings.annotate) ? "none" : settings.wrap
193
+
194
+ const n1 = expression.length === 0 ? null : expression[0]
195
+ let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode)
196
+ && !(n1.type === "mstyle" && n1.attributes.mathcolor)
197
+ ? expression[0]
198
+ : expression.length > 1 && wrap === "none"
199
+ ? new mathMLTree.MathNode("mrow", expression)
200
+ : setLineBreaks(expression, wrap, settings.displayMode)
201
+
202
+ if (tag) {
203
+ wrapper = taggedExpression(wrapper, tag, style, settings.leqno)
204
+ }
205
+
206
+ if (settings.annotate) {
207
+ // Build a TeX annotation of the source
208
+ const annotation = new mathMLTree.MathNode(
209
+ "annotation", [new mathMLTree.TextNode(texExpression)]);
210
+ annotation.setAttribute("encoding", "application/x-tex");
211
+ wrapper = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
212
+ }
213
+
214
+ if (wrap !== "none") {
215
+ const maths = []
216
+ for (let i = 0; i < wrapper.children.length; i++) {
217
+ const math = new mathMLTree.MathNode("math", [wrapper.children[i]])
218
+ if (settings.xml) {
219
+ math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML")
220
+ }
221
+ maths.push(math)
222
+ }
223
+ return mathMLTree.newDocumentFragment(maths)
224
+ }
225
+
226
+ const math = new mathMLTree.MathNode("math", [wrapper])
227
+
228
+ if (settings.xml) {
229
+ math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML")
230
+ }
231
+ if (settings.displayMode) {
232
+ math.setAttribute("display", "block");
233
+ }
234
+ return math;
235
+ }
@@ -0,0 +1,25 @@
1
+ // In TeX, there are actually three sets of dimensions, one for each of
2
+ // textstyle, scriptstyle, and scriptscriptstyle. These are
3
+ // provided in the the arrays below, in that order.
4
+ //
5
+ export const metrics = {
6
+ quad: [1.0, 1.171, 1.472], // Extracted from TeX
7
+
8
+ // The TeX default rule thickness, 0.04 em, often disappears from a browser screen.
9
+ // So we use a thicker rule.
10
+ defaultRuleThickness: [0.06, 0.074, 0.074],
11
+
12
+ // The space between adjacent `|` columns in an array definition.
13
+ doubleRuleSep: [0.3, 0.3, 0.3],
14
+
15
+ // The width of separator lines in {array} environments.
16
+ arrayRuleWidth: [0.06, 0.06, 0.04]
17
+ };
18
+
19
+ // Math style is not quite the same thing as script level.
20
+ export const StyleLevel = {
21
+ DISPLAY: 0,
22
+ TEXT: 1,
23
+ SCRIPT: 2,
24
+ SCRIPTSCRIPT: 3
25
+ };
@@ -0,0 +1,25 @@
1
+ import { _mathmlGroupBuilders } from "./defineFunction";
2
+
3
+ /**
4
+ * All registered environments.
5
+ * `environments.js` exports this same dictionary again and makes it public.
6
+ * `Parser.js` requires this dictionary via `environments.js`.
7
+ */
8
+ export const _environments = {};
9
+
10
+ export default function defineEnvironment({ type, names, props, handler, mathmlBuilder }) {
11
+ // Set default values of environments.
12
+ const data = {
13
+ type,
14
+ numArgs: props.numArgs || 0,
15
+ allowedInText: false,
16
+ numOptionalArgs: 0,
17
+ handler
18
+ };
19
+ for (let i = 0; i < names.length; ++i) {
20
+ _environments[names[i]] = data;
21
+ }
22
+ if (mathmlBuilder) {
23
+ _mathmlGroupBuilders[type] = mathmlBuilder;
24
+ }
25
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * All registered functions.
3
+ * `functions.js` just exports this same dictionary again and makes it public.
4
+ * `Parser.js` requires this dictionary.
5
+ */
6
+ export const _functions = {}
7
+
8
+ /**
9
+ * All MathML builders. Should be only used in the `define*` and the `build*ML`
10
+ * functions.
11
+ */
12
+ export const _mathmlGroupBuilders = {}
13
+
14
+ export default function defineFunction({
15
+ type,
16
+ names,
17
+ props,
18
+ handler,
19
+ mathmlBuilder
20
+ }) {
21
+ // Set default values of functions
22
+ const data = {
23
+ type,
24
+ numArgs: props.numArgs,
25
+ argTypes: props.argTypes,
26
+ allowedInArgument: !!props.allowedInArgument,
27
+ allowedInText: !!props.allowedInText,
28
+ allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath,
29
+ numOptionalArgs: props.numOptionalArgs || 0,
30
+ infix: !!props.infix,
31
+ primitive: !!props.primitive,
32
+ handler: handler
33
+ }
34
+ for (let i = 0; i < names.length; ++i) {
35
+ _functions[names[i]] = data
36
+ }
37
+ if (type) {
38
+ if (mathmlBuilder) {
39
+ _mathmlGroupBuilders[type] = mathmlBuilder
40
+ }
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Use this to register only the MathML builder for a function(e.g.
46
+ * if the function's ParseNode is generated in Parser.js rather than via a
47
+ * stand-alone handler provided to `defineFunction`).
48
+ */
49
+ export function defineFunctionBuilders({ type, mathmlBuilder }) {
50
+ defineFunction({
51
+ type,
52
+ names: [],
53
+ props: { numArgs: 0 },
54
+ handler() {
55
+ throw new Error("Should never be called.")
56
+ },
57
+ mathmlBuilder
58
+ })
59
+ }
60
+
61
+ export const normalizeArgument = function(arg) {
62
+ return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg
63
+ }
64
+
65
+ // Since the corresponding buildMathML function expects a
66
+ // list of elements, we normalize for different kinds of arguments
67
+ export const ordargument = function(arg) {
68
+ return arg.type === "ordgroup" ? arg.body : [arg]
69
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * All registered global/built-in macros.
3
+ * `macros.js` exports this same dictionary again and makes it public.
4
+ * `Parser.js` requires this dictionary via `macros.js`.
5
+ */
6
+ export const _macros = {};
7
+
8
+ // This function might one day accept an additional argument and do more things.
9
+ export default function defineMacro(name, body) {
10
+ _macros[name] = body;
11
+ }