temml 0.9.1

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.
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,46 @@
1
+ import defineFunction, { ordargument } from "../defineFunction";
2
+ import symbols from "../symbols";
3
+ import * as mml from "../buildMathML";
4
+ import utils from "../utils"
5
+
6
+ defineFunction({
7
+ type: "not",
8
+ names: ["\\not"],
9
+ props: {
10
+ numArgs: 1,
11
+ primitive: true,
12
+ allowedInText: false
13
+ },
14
+ handler({ parser }, args) {
15
+ const isCharacterBox = utils.isCharacterBox(args[0])
16
+ let body
17
+ if (isCharacterBox) {
18
+ body = ordargument(args[0])
19
+ if (body[0].text.charAt(0) === "\\") {
20
+ body[0].text = symbols.math[body[0].text].replace
21
+ }
22
+ // \u0338 is the Unicode Combining Long Solidus Overlay
23
+ body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1)
24
+ } else {
25
+ // When the argument is not a character box, TeX does an awkward, poorly placed overlay.
26
+ // We'll do the same.
27
+ const notNode = { type: "textord", mode: "math", text: "\u0338" }
28
+ const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }
29
+ body = [notNode, kernNode, args[0]]
30
+ }
31
+ return {
32
+ type: "not",
33
+ mode: parser.mode,
34
+ body,
35
+ isCharacterBox
36
+ };
37
+ },
38
+ mathmlBuilder(group, style) {
39
+ if (group.isCharacterBox) {
40
+ const inner = mml.buildExpression(group.body, style);
41
+ return inner[0]
42
+ } else {
43
+ return mml.buildExpressionRow(group.body, style, true)
44
+ }
45
+ }
46
+ });
@@ -0,0 +1,338 @@
1
+ // Limits, symbols
2
+ import defineFunction, { ordargument } from "../defineFunction";
3
+ import * as mathMLTree from "../mathMLTree";
4
+ import * as mml from "../buildMathML";
5
+ import { delimiters, delimiterSizes } from "./delimsizing"
6
+
7
+ // Some helpers
8
+
9
+ const ordAtomTypes = ["textord", "mathord", "atom"]
10
+
11
+ // Most operators have a large successor symbol, but these don't.
12
+ const noSuccessor = ["\\smallint"];
13
+
14
+ // Math operators (e.g. \sin) need a space between these types and themselves:
15
+ export const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
16
+
17
+ const dels = ["}", "\\left", "\\middle", "\\right"]
18
+ const isDelimiter = str => str.length > 0 &&
19
+ (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str))
20
+
21
+ // NOTE: Unlike most `builders`s, this one handles not only "op", but also
22
+ // "supsub" since some of them (like \int) can affect super/subscripting.
23
+
24
+ const mathmlBuilder = (group, style) => {
25
+ let node;
26
+
27
+ if (group.symbol) {
28
+ // This is a symbol. Just add the symbol.
29
+ node = new mathMLTree.MathNode("mo", [mml.makeText(group.name, group.mode)]);
30
+ if (noSuccessor.includes(group.name)) {
31
+ node.setAttribute("largeop", "false")
32
+ } else {
33
+ node.setAttribute("movablelimits", "false")
34
+ }
35
+ } else if (group.body) {
36
+ // This is an operator with children. Add them.
37
+ node = new mathMLTree.MathNode("mo", mml.buildExpression(group.body, style));
38
+ } else {
39
+ // This is a text operator. Add all of the characters from the operator's name.
40
+ node = new mathMLTree.MathNode("mi", [new mathMLTree.TextNode(group.name.slice(1))]);
41
+
42
+ if (!group.parentIsSupSub) {
43
+ // Append an invisible <mo>&ApplyFunction;</mo>.
44
+ // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
45
+ const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")]);
46
+ const row = [node, operator]
47
+ // Set spacing
48
+ if (group.needsLeadingSpace) {
49
+ const lead = new mathMLTree.MathNode("mspace")
50
+ lead.setAttribute("width", "0.1667em") // thin space.
51
+ row.unshift(lead)
52
+ }
53
+ if (!group.isFollowedByDelimiter) {
54
+ const trail = new mathMLTree.MathNode("mspace")
55
+ trail.setAttribute("width", "0.1667em") // thin space.
56
+ row.push(trail)
57
+ }
58
+ node = new mathMLTree.MathNode("mrow", row)
59
+ }
60
+ }
61
+
62
+ return node;
63
+ };
64
+
65
+ const singleCharBigOps = {
66
+ "\u220F": "\\prod",
67
+ "\u2210": "\\coprod",
68
+ "\u2211": "\\sum",
69
+ "\u22c0": "\\bigwedge",
70
+ "\u22c1": "\\bigvee",
71
+ "\u22c2": "\\bigcap",
72
+ "\u22c3": "\\bigcup",
73
+ "\u2a00": "\\bigodot",
74
+ "\u2a01": "\\bigoplus",
75
+ "\u2a02": "\\bigotimes",
76
+ "\u2a04": "\\biguplus",
77
+ "\u2a05": "\\bigsqcap",
78
+ "\u2a06": "\\bigsqcup"
79
+ };
80
+
81
+ defineFunction({
82
+ type: "op",
83
+ names: [
84
+ "\\coprod",
85
+ "\\bigvee",
86
+ "\\bigwedge",
87
+ "\\biguplus",
88
+ "\\bigcap",
89
+ "\\bigcup",
90
+ "\\intop",
91
+ "\\prod",
92
+ "\\sum",
93
+ "\\bigotimes",
94
+ "\\bigoplus",
95
+ "\\bigodot",
96
+ "\\bigsqcap",
97
+ "\\bigsqcup",
98
+ "\\smallint",
99
+ "\u220F",
100
+ "\u2210",
101
+ "\u2211",
102
+ "\u22c0",
103
+ "\u22c1",
104
+ "\u22c2",
105
+ "\u22c3",
106
+ "\u2a00",
107
+ "\u2a01",
108
+ "\u2a02",
109
+ "\u2a04",
110
+ "\u2a06"
111
+ ],
112
+ props: {
113
+ numArgs: 0
114
+ },
115
+ handler: ({ parser, funcName }, args) => {
116
+ let fName = funcName;
117
+ if (fName.length === 1) {
118
+ fName = singleCharBigOps[fName];
119
+ }
120
+ return {
121
+ type: "op",
122
+ mode: parser.mode,
123
+ limits: true,
124
+ parentIsSupSub: false,
125
+ symbol: true,
126
+ stack: false, // This is true for \stackrel{}, not here.
127
+ name: fName
128
+ };
129
+ },
130
+ mathmlBuilder
131
+ });
132
+
133
+ // Note: calling defineFunction with a type that's already been defined only
134
+ // works because the same mathmlBuilder is being used.
135
+ defineFunction({
136
+ type: "op",
137
+ names: ["\\mathop"],
138
+ props: {
139
+ numArgs: 1,
140
+ primitive: true
141
+ },
142
+ handler: ({ parser }, args) => {
143
+ const body = args[0];
144
+ // It would be convienient to just wrap a <mo> around the argument.
145
+ // But if the argument is a <mi> or <mord>, that would be invalid MathML.
146
+ // In that case, we instead promote the text contents of the body to the parent.
147
+ const arr = (body.body) ? body.body : [body];
148
+ const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type)
149
+ return {
150
+ type: "op",
151
+ mode: parser.mode,
152
+ limits: true,
153
+ parentIsSupSub: false,
154
+ symbol: isSymbol,
155
+ stack: false,
156
+ name: isSymbol ? arr[0].text : null,
157
+ body: isSymbol ? null : ordargument(body)
158
+ };
159
+ },
160
+ mathmlBuilder
161
+ });
162
+
163
+ // There are 2 flags for operators; whether they produce limits in
164
+ // displaystyle, and whether they are symbols and should grow in
165
+ // displaystyle. These four groups cover the four possible choices.
166
+
167
+ const singleCharIntegrals = {
168
+ "\u222b": "\\int",
169
+ "\u222c": "\\iint",
170
+ "\u222d": "\\iiint",
171
+ "\u222e": "\\oint",
172
+ "\u222f": "\\oiint",
173
+ "\u2230": "\\oiiint",
174
+ "\u2231": "\\intclockwise",
175
+ "\u2232": "\\varointclockwise",
176
+ "\u2a0c": "\\iiiint",
177
+ "\u2a0d": "\\intbar",
178
+ "\u2a0e": "\\intBar",
179
+ "\u2a0f": "\\fint",
180
+ "\u2a12": "\\rppolint",
181
+ "\u2a13": "\\scpolint",
182
+ "\u2a15": "\\pointint",
183
+ "\u2a16": "\\sqint",
184
+ "\u2a17": "\\intlarhk",
185
+ "\u2a18": "\\intx",
186
+ "\u2a19": "\\intcap",
187
+ "\u2a1a": "\\intcup"
188
+ };
189
+
190
+ // No limits, not symbols
191
+ defineFunction({
192
+ type: "op",
193
+ names: [
194
+ "\\arcsin",
195
+ "\\arccos",
196
+ "\\arctan",
197
+ "\\arctg",
198
+ "\\arcctg",
199
+ "\\arg",
200
+ "\\ch",
201
+ "\\cos",
202
+ "\\cosec",
203
+ "\\cosh",
204
+ "\\cot",
205
+ "\\cotg",
206
+ "\\coth",
207
+ "\\csc",
208
+ "\\ctg",
209
+ "\\cth",
210
+ "\\deg",
211
+ "\\dim",
212
+ "\\exp",
213
+ "\\hom",
214
+ "\\ker",
215
+ "\\lg",
216
+ "\\ln",
217
+ "\\log",
218
+ "\\sec",
219
+ "\\sin",
220
+ "\\sinh",
221
+ "\\sh",
222
+ "\\sgn",
223
+ "\\tan",
224
+ "\\tanh",
225
+ "\\tg",
226
+ "\\th"
227
+ ],
228
+ props: {
229
+ numArgs: 0
230
+ },
231
+ handler({ parser, funcName }) {
232
+ const prevAtomType = parser.prevAtomType
233
+ const next = parser.gullet.future().text
234
+ return {
235
+ type: "op",
236
+ mode: parser.mode,
237
+ limits: false,
238
+ parentIsSupSub: false,
239
+ symbol: false,
240
+ stack: false,
241
+ isFollowedByDelimiter: isDelimiter(next),
242
+ needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
243
+ name: funcName
244
+ };
245
+ },
246
+ mathmlBuilder
247
+ });
248
+
249
+ // Limits, not symbols
250
+ defineFunction({
251
+ type: "op",
252
+ names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
253
+ props: {
254
+ numArgs: 0
255
+ },
256
+ handler({ parser, funcName }) {
257
+ const prevAtomType = parser.prevAtomType
258
+ const next = parser.gullet.future().text
259
+ return {
260
+ type: "op",
261
+ mode: parser.mode,
262
+ limits: true,
263
+ parentIsSupSub: false,
264
+ symbol: false,
265
+ stack: false,
266
+ isFollowedByDelimiter: isDelimiter(next),
267
+ needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
268
+ name: funcName
269
+ };
270
+ },
271
+ mathmlBuilder
272
+ });
273
+
274
+ // No limits, symbols
275
+ defineFunction({
276
+ type: "op",
277
+ names: [
278
+ "\\int",
279
+ "\\iint",
280
+ "\\iiint",
281
+ "\\iiiint",
282
+ "\\oint",
283
+ "\\oiint",
284
+ "\\oiiint",
285
+ "\\intclockwise",
286
+ "\\varointclockwise",
287
+ "\\intbar",
288
+ "\\intBar",
289
+ "\\fint",
290
+ "\\rppolint",
291
+ "\\scpolint",
292
+ "\\pointint",
293
+ "\\sqint",
294
+ "\\intlarhk",
295
+ "\\intx",
296
+ "\\intcap",
297
+ "\\intcup",
298
+ "\u222b",
299
+ "\u222c",
300
+ "\u222d",
301
+ "\u222e",
302
+ "\u222f",
303
+ "\u2230",
304
+ "\u2231",
305
+ "\u2232",
306
+ "\u2a0c",
307
+ "\u2a0d",
308
+ "\u2a0e",
309
+ "\u2a0f",
310
+ "\u2a12",
311
+ "\u2a13",
312
+ "\u2a15",
313
+ "\u2a16",
314
+ "\u2a17",
315
+ "\u2a18",
316
+ "\u2a19",
317
+ "\u2a1a"
318
+ ],
319
+ props: {
320
+ numArgs: 0
321
+ },
322
+ handler({ parser, funcName }) {
323
+ let fName = funcName;
324
+ if (fName.length === 1) {
325
+ fName = singleCharIntegrals[fName];
326
+ }
327
+ return {
328
+ type: "op",
329
+ mode: parser.mode,
330
+ limits: false,
331
+ parentIsSupSub: false,
332
+ symbol: true,
333
+ stack: false,
334
+ name: fName
335
+ };
336
+ },
337
+ mathmlBuilder
338
+ });
@@ -0,0 +1,139 @@
1
+ import defineFunction, { ordargument } from "../defineFunction"
2
+ import defineMacro from "../defineMacro";
3
+ import mathMLTree from "../mathMLTree"
4
+ import { spaceCharacter } from "./kern"
5
+ import { ordTypes } from "./op"
6
+ import { delimiters, delimiterSizes } from "./delimsizing"
7
+
8
+ import * as mml from "../buildMathML"
9
+
10
+ const dels = ["}", "\\left", "\\middle", "\\right"]
11
+ const isDelimiter = str => str.length > 0 &&
12
+ (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str))
13
+
14
+ // NOTE: Unlike most builders, this one handles not only
15
+ // "operatorname", but also "supsub" since \operatorname* can
16
+ // affect super/subscripting.
17
+
18
+ const mathmlBuilder = (group, style) => {
19
+ let expression = mml.buildExpression(group.body, style.withFont("mathrm"))
20
+
21
+ // Is expression a string or has it something like a fraction?
22
+ let isAllString = true; // default
23
+ for (let i = 0; i < expression.length; i++) {
24
+ const node = expression[i]
25
+ if (node instanceof mathMLTree.MathNode) {
26
+ switch (node.type) {
27
+ case "mi":
28
+ case "mn":
29
+ case "ms":
30
+ case "mtext":
31
+ break; // Do nothing yet.
32
+ case "mspace":
33
+ {
34
+ if (node.attributes.width) {
35
+ const width = node.attributes.width.replace("em", "")
36
+ const ch = spaceCharacter(Number(width))
37
+ if (ch === "") {
38
+ isAllString = false
39
+ } else {
40
+ expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)])
41
+ }
42
+ }
43
+ }
44
+ break
45
+ case "mo": {
46
+ const child = node.children[0]
47
+ if (node.children.length === 1 && child instanceof mathMLTree.TextNode) {
48
+ child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*")
49
+ } else {
50
+ isAllString = false
51
+ }
52
+ break
53
+ }
54
+ default:
55
+ isAllString = false
56
+ }
57
+ } else {
58
+ isAllString = false
59
+ }
60
+ }
61
+
62
+ if (isAllString) {
63
+ // Write a single TextNode instead of multiple nested tags.
64
+ const word = expression.map((node) => node.toText()).join("")
65
+ expression = [new mathMLTree.TextNode(word)]
66
+ } else if (
67
+ expression.length === 1
68
+ && ["mover", "munder"].includes(expression[0].type) &&
69
+ (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext")
70
+ ) {
71
+ expression[0].children[0].type = "mi"
72
+ if (group.parentIsSupSub) {
73
+ return new mathMLTree.MathNode("mrow", expression)
74
+ } else {
75
+ const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")])
76
+ return mathMLTree.newDocumentFragment([expression[0], operator])
77
+ }
78
+ }
79
+
80
+ let wrapper;
81
+ if (isAllString) {
82
+ wrapper = new mathMLTree.MathNode("mi", expression)
83
+ wrapper.setAttribute("mathvariant", "normal")
84
+ } else {
85
+ wrapper = new mathMLTree.MathNode("mrow", expression)
86
+ }
87
+
88
+ if (!group.parentIsSupSub) {
89
+ // Append an <mo>&ApplyFunction;</mo>.
90
+ // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
91
+ const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")])
92
+ const fragment = [wrapper, operator]
93
+ if (group.needsLeadingSpace) {
94
+ // LaTeX gives operator spacing, but a <mi> gets ord spacing.
95
+ // So add a leading space.
96
+ const space = new mathMLTree.MathNode("mspace")
97
+ space.setAttribute("width", "0.1667em") // thin space.
98
+ fragment.unshift(space)
99
+ }
100
+ if (!group.isFollowedByDelimiter) {
101
+ const trail = new mathMLTree.MathNode("mspace")
102
+ trail.setAttribute("width", "0.1667em") // thin space.
103
+ fragment.push(trail)
104
+ }
105
+ return mathMLTree.newDocumentFragment(fragment)
106
+ }
107
+
108
+ return wrapper
109
+ };
110
+
111
+ // \operatorname
112
+ // amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
113
+ defineFunction({
114
+ type: "operatorname",
115
+ names: ["\\operatorname@", "\\operatornamewithlimits"],
116
+ props: {
117
+ numArgs: 1,
118
+ allowedInArgument: true
119
+ },
120
+ handler: ({ parser, funcName }, args) => {
121
+ const body = args[0]
122
+ const prevAtomType = parser.prevAtomType
123
+ const next = parser.gullet.future().text
124
+ return {
125
+ type: "operatorname",
126
+ mode: parser.mode,
127
+ body: ordargument(body),
128
+ alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"),
129
+ limits: false,
130
+ parentIsSupSub: false,
131
+ isFollowedByDelimiter: isDelimiter(next),
132
+ needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType)
133
+ };
134
+ },
135
+ mathmlBuilder
136
+ });
137
+
138
+ defineMacro("\\operatorname",
139
+ "\\@ifstar\\operatornamewithlimits\\operatorname@");
@@ -0,0 +1,9 @@
1
+ import { defineFunctionBuilders } from "../defineFunction";
2
+ import * as mml from "../buildMathML";
3
+
4
+ defineFunctionBuilders({
5
+ type: "ordgroup",
6
+ mathmlBuilder(group, style) {
7
+ return mml.buildExpressionRow(group.body, style, true);
8
+ }
9
+ });
@@ -0,0 +1,73 @@
1
+ import defineFunction, { ordargument } from "../defineFunction";
2
+ import mathMLTree from "../mathMLTree";
3
+ import * as mml from "../buildMathML";
4
+
5
+ defineFunction({
6
+ type: "phantom",
7
+ names: ["\\phantom"],
8
+ props: {
9
+ numArgs: 1,
10
+ allowedInText: true
11
+ },
12
+ handler: ({ parser }, args) => {
13
+ const body = args[0];
14
+ return {
15
+ type: "phantom",
16
+ mode: parser.mode,
17
+ body: ordargument(body)
18
+ };
19
+ },
20
+ mathmlBuilder: (group, style) => {
21
+ const inner = mml.buildExpression(group.body, style);
22
+ return new mathMLTree.MathNode("mphantom", inner);
23
+ }
24
+ });
25
+
26
+ defineFunction({
27
+ type: "hphantom",
28
+ names: ["\\hphantom"],
29
+ props: {
30
+ numArgs: 1,
31
+ allowedInText: true
32
+ },
33
+ handler: ({ parser }, args) => {
34
+ const body = args[0];
35
+ return {
36
+ type: "hphantom",
37
+ mode: parser.mode,
38
+ body
39
+ };
40
+ },
41
+ mathmlBuilder: (group, style) => {
42
+ const inner = mml.buildExpression(ordargument(group.body), style);
43
+ const phantom = new mathMLTree.MathNode("mphantom", inner);
44
+ const node = new mathMLTree.MathNode("mpadded", [phantom]);
45
+ node.setAttribute("height", "0px");
46
+ node.setAttribute("depth", "0px");
47
+ return node;
48
+ }
49
+ });
50
+
51
+ defineFunction({
52
+ type: "vphantom",
53
+ names: ["\\vphantom"],
54
+ props: {
55
+ numArgs: 1,
56
+ allowedInText: true
57
+ },
58
+ handler: ({ parser }, args) => {
59
+ const body = args[0];
60
+ return {
61
+ type: "vphantom",
62
+ mode: parser.mode,
63
+ body
64
+ };
65
+ },
66
+ mathmlBuilder: (group, style) => {
67
+ const inner = mml.buildExpression(ordargument(group.body), style);
68
+ const phantom = new mathMLTree.MathNode("mphantom", inner);
69
+ const node = new mathMLTree.MathNode("mpadded", [phantom]);
70
+ node.setAttribute("width", "0px");
71
+ return node;
72
+ }
73
+ });
@@ -0,0 +1,31 @@
1
+ import defineFunction, { ordargument } from "../defineFunction"
2
+ import { wrapWithMstyle } from "../mathMLTree"
3
+ import * as mml from "../buildMathML"
4
+
5
+ // \pmb is a simulation of bold font.
6
+ // The version of \pmb in ambsy.sty works by typesetting three copies of the argument
7
+ // with small offsets. We use CSS text-shadow.
8
+ // It's a hack. Not as good as a real bold font. Better than nothing.
9
+
10
+ defineFunction({
11
+ type: "pmb",
12
+ names: ["\\pmb"],
13
+ props: {
14
+ numArgs: 1,
15
+ allowedInText: true
16
+ },
17
+ handler({ parser }, args) {
18
+ return {
19
+ type: "pmb",
20
+ mode: parser.mode,
21
+ body: ordargument(args[0])
22
+ }
23
+ },
24
+ mathmlBuilder(group, style) {
25
+ const inner = mml.buildExpression(group.body, style)
26
+ // Wrap with an <mstyle> element.
27
+ const node = wrapWithMstyle(inner)
28
+ node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px")
29
+ return node
30
+ }
31
+ })
@@ -0,0 +1,68 @@
1
+ import defineFunction from "../defineFunction"
2
+ import { StyleLevel } from "../constants"
3
+ import mathMLTree from "../mathMLTree"
4
+ import { assertNodeType } from "../parseNode"
5
+ import { calculateSize } from "../units"
6
+ import * as mml from "../buildMathML"
7
+
8
+ const sign = num => num >= 0 ? "+" : "-"
9
+
10
+ // \raise, \lower, and \raisebox
11
+
12
+ const mathmlBuilder = (group, style) => {
13
+ const newStyle = style.withLevel(StyleLevel.TEXT)
14
+ const node = new mathMLTree.MathNode("mpadded", [mml.buildGroup(group.body, newStyle)])
15
+ const dy = calculateSize(group.dy, style)
16
+ node.setAttribute("voffset", dy.number + dy.unit)
17
+ const dyAbs = Math.abs(dy.number)
18
+ // The next two lines do not work in Chromium.
19
+ // TODO: Find some other way to adjust height and depth.
20
+ node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit)
21
+ node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit)
22
+ return node
23
+ }
24
+
25
+ defineFunction({
26
+ type: "raise",
27
+ names: ["\\raise", "\\lower"],
28
+ props: {
29
+ numArgs: 2,
30
+ argTypes: ["size", "primitive"],
31
+ primitive: true
32
+ },
33
+ handler({ parser, funcName }, args) {
34
+ const amount = assertNodeType(args[0], "size").value;
35
+ if (funcName === "\\lower") { amount.number *= -1 }
36
+ const body = args[1]
37
+ return {
38
+ type: "raise",
39
+ mode: parser.mode,
40
+ dy: amount,
41
+ body
42
+ };
43
+ },
44
+ mathmlBuilder
45
+ })
46
+
47
+
48
+ defineFunction({
49
+ type: "raise",
50
+ names: ["\\raisebox"],
51
+ props: {
52
+ numArgs: 2,
53
+ argTypes: ["size", "hbox"],
54
+ allowedInText: true
55
+ },
56
+ handler({ parser, funcName }, args) {
57
+ const amount = assertNodeType(args[0], "size").value
58
+ const body = args[1]
59
+ return {
60
+ type: "raise",
61
+ mode: parser.mode,
62
+ dy: amount,
63
+ body
64
+ };
65
+ },
66
+ mathmlBuilder
67
+ })
68
+