temml 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +44 -0
- package/contrib/auto-render/README.md +89 -0
- package/contrib/auto-render/auto-render.js +128 -0
- package/contrib/auto-render/dist/auto-render.js +217 -0
- package/contrib/auto-render/dist/auto-render.min.js +1 -0
- package/contrib/auto-render/splitAtDelimiters.js +84 -0
- package/contrib/auto-render/test/auto-render-spec.js +234 -0
- package/contrib/auto-render/test/auto-render.js +217 -0
- package/contrib/auto-render/test/test_page.html +59 -0
- package/contrib/mhchem/README.md +26 -0
- package/contrib/mhchem/mhchem.js +1705 -0
- package/contrib/mhchem/mhchem.min.js +1 -0
- package/contrib/physics/README.md +20 -0
- package/contrib/physics/physics.js +131 -0
- package/contrib/texvc/README.md +23 -0
- package/contrib/texvc/texvc.js +61 -0
- package/dist/Temml-Asana.css +201 -0
- package/dist/Temml-Latin-Modern.css +216 -0
- package/dist/Temml-Libertinus.css +214 -0
- package/dist/Temml-Local.css +194 -0
- package/dist/Temml-STIX2.css +203 -0
- package/dist/Temml.woff2 +0 -0
- package/dist/temml.cjs +13122 -0
- package/dist/temml.js +11225 -0
- package/dist/temml.min.js +1 -0
- package/dist/temml.mjs +13120 -0
- package/dist/temmlPostProcess.js +70 -0
- package/package.json +34 -0
- package/src/Lexer.js +121 -0
- package/src/MacroExpander.js +437 -0
- package/src/Namespace.js +107 -0
- package/src/ParseError.js +64 -0
- package/src/Parser.js +977 -0
- package/src/Settings.js +49 -0
- package/src/SourceLocation.js +29 -0
- package/src/Style.js +144 -0
- package/src/Token.js +40 -0
- package/src/buildMathML.js +235 -0
- package/src/constants.js +25 -0
- package/src/defineEnvironment.js +25 -0
- package/src/defineFunction.js +69 -0
- package/src/defineMacro.js +11 -0
- package/src/domTree.js +185 -0
- package/src/environments/array.js +791 -0
- package/src/environments/cd.js +252 -0
- package/src/environments.js +8 -0
- package/src/functions/accent.js +127 -0
- package/src/functions/accentunder.js +38 -0
- package/src/functions/arrow.js +204 -0
- package/src/functions/cancelto.js +36 -0
- package/src/functions/char.js +33 -0
- package/src/functions/color.js +253 -0
- package/src/functions/cr.js +46 -0
- package/src/functions/def.js +259 -0
- package/src/functions/delimsizing.js +304 -0
- package/src/functions/enclose.js +193 -0
- package/src/functions/envTag.js +38 -0
- package/src/functions/environment.js +59 -0
- package/src/functions/font.js +123 -0
- package/src/functions/genfrac.js +333 -0
- package/src/functions/hbox.js +29 -0
- package/src/functions/horizBrace.js +32 -0
- package/src/functions/href.js +90 -0
- package/src/functions/html.js +95 -0
- package/src/functions/includegraphics.js +131 -0
- package/src/functions/kern.js +75 -0
- package/src/functions/label.js +29 -0
- package/src/functions/lap.js +75 -0
- package/src/functions/math.js +40 -0
- package/src/functions/mathchoice.js +41 -0
- package/src/functions/mclass.js +201 -0
- package/src/functions/multiscript.js +91 -0
- package/src/functions/not.js +46 -0
- package/src/functions/op.js +338 -0
- package/src/functions/operatorname.js +139 -0
- package/src/functions/ordgroup.js +9 -0
- package/src/functions/phantom.js +73 -0
- package/src/functions/pmb.js +31 -0
- package/src/functions/raise.js +68 -0
- package/src/functions/ref.js +28 -0
- package/src/functions/relax.js +16 -0
- package/src/functions/rule.js +52 -0
- package/src/functions/sizing.js +64 -0
- package/src/functions/smash.js +66 -0
- package/src/functions/sqrt.js +31 -0
- package/src/functions/styling.js +58 -0
- package/src/functions/supsub.js +135 -0
- package/src/functions/symbolsOp.js +53 -0
- package/src/functions/symbolsOrd.js +102 -0
- package/src/functions/symbolsSpacing.js +53 -0
- package/src/functions/tag.js +8 -0
- package/src/functions/text.js +75 -0
- package/src/functions/tip.js +63 -0
- package/src/functions/toggle.js +13 -0
- package/src/functions/verb.js +33 -0
- package/src/functions.js +57 -0
- package/src/linebreaking.js +159 -0
- package/src/macros.js +708 -0
- package/src/mathMLTree.js +175 -0
- package/src/parseNode.js +42 -0
- package/src/parseTree.js +40 -0
- package/src/postProcess.js +57 -0
- package/src/replace.js +225 -0
- package/src/stretchy.js +66 -0
- package/src/svg.js +110 -0
- package/src/symbols.js +972 -0
- package/src/tree.js +50 -0
- package/src/unicodeAccents.js +16 -0
- package/src/unicodeScripts.js +119 -0
- package/src/unicodeSupOrSub.js +108 -0
- package/src/unicodeSymbolBuilder.js +31 -0
- package/src/unicodeSymbols.js +320 -0
- package/src/units.js +109 -0
- package/src/utils.js +109 -0
- package/src/variant.js +103 -0
- package/temml.js +181 -0
package/src/macros.js
ADDED
@@ -0,0 +1,708 @@
|
|
1
|
+
/**
|
2
|
+
* Predefined macros for Temml.
|
3
|
+
* This can be used to define some commands in terms of others.
|
4
|
+
*/
|
5
|
+
|
6
|
+
// Export global macros object from defineMacro
|
7
|
+
import defineMacro, { _macros } from "./defineMacro";
|
8
|
+
const macros = _macros;
|
9
|
+
export default macros;
|
10
|
+
|
11
|
+
import symbols from "./symbols";
|
12
|
+
import ParseError from "./ParseError";
|
13
|
+
|
14
|
+
//////////////////////////////////////////////////////////////////////
|
15
|
+
// macro tools
|
16
|
+
|
17
|
+
defineMacro("\\noexpand", function(context) {
|
18
|
+
// The expansion is the token itself; but that token is interpreted
|
19
|
+
// as if its meaning were ‘\relax’ if it is a control sequence that
|
20
|
+
// would ordinarily be expanded by TeX’s expansion rules.
|
21
|
+
const t = context.popToken();
|
22
|
+
if (context.isExpandable(t.text)) {
|
23
|
+
t.noexpand = true;
|
24
|
+
t.treatAsRelax = true;
|
25
|
+
}
|
26
|
+
return { tokens: [t], numArgs: 0 };
|
27
|
+
});
|
28
|
+
|
29
|
+
defineMacro("\\expandafter", function(context) {
|
30
|
+
// TeX first reads the token that comes immediately after \expandafter,
|
31
|
+
// without expanding it; let’s call this token t. Then TeX reads the
|
32
|
+
// token that comes after t (and possibly more tokens, if that token
|
33
|
+
// has an argument), replacing it by its expansion. Finally TeX puts
|
34
|
+
// t back in front of that expansion.
|
35
|
+
const t = context.popToken();
|
36
|
+
context.expandOnce(true); // expand only an expandable token
|
37
|
+
return { tokens: [t], numArgs: 0 };
|
38
|
+
});
|
39
|
+
|
40
|
+
// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
|
41
|
+
// TeX source: \long\def\@firstoftwo#1#2{#1}
|
42
|
+
defineMacro("\\@firstoftwo", function(context) {
|
43
|
+
const args = context.consumeArgs(2);
|
44
|
+
return { tokens: args[0], numArgs: 0 };
|
45
|
+
});
|
46
|
+
|
47
|
+
// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
|
48
|
+
// TeX source: \long\def\@secondoftwo#1#2{#2}
|
49
|
+
defineMacro("\\@secondoftwo", function(context) {
|
50
|
+
const args = context.consumeArgs(2);
|
51
|
+
return { tokens: args[1], numArgs: 0 };
|
52
|
+
});
|
53
|
+
|
54
|
+
// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
|
55
|
+
// symbol that isn't a space, consuming any spaces but not consuming the
|
56
|
+
// first nonspace character. If that nonspace character matches #1, then
|
57
|
+
// the macro expands to #2; otherwise, it expands to #3.
|
58
|
+
defineMacro("\\@ifnextchar", function(context) {
|
59
|
+
const args = context.consumeArgs(3); // symbol, if, else
|
60
|
+
context.consumeSpaces();
|
61
|
+
const nextToken = context.future();
|
62
|
+
if (args[0].length === 1 && args[0][0].text === nextToken.text) {
|
63
|
+
return { tokens: args[1], numArgs: 0 };
|
64
|
+
} else {
|
65
|
+
return { tokens: args[2], numArgs: 0 };
|
66
|
+
}
|
67
|
+
});
|
68
|
+
|
69
|
+
// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
|
70
|
+
// If it is `*`, then it consumes the symbol, and the macro expands to #1;
|
71
|
+
// otherwise, the macro expands to #2 (without consuming the symbol).
|
72
|
+
// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
|
73
|
+
defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}");
|
74
|
+
|
75
|
+
// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
|
76
|
+
defineMacro("\\TextOrMath", function(context) {
|
77
|
+
const args = context.consumeArgs(2);
|
78
|
+
if (context.mode === "text") {
|
79
|
+
return { tokens: args[0], numArgs: 0 };
|
80
|
+
} else {
|
81
|
+
return { tokens: args[1], numArgs: 0 };
|
82
|
+
}
|
83
|
+
});
|
84
|
+
|
85
|
+
const stringFromArg = arg => {
|
86
|
+
// Reverse the order of the arg and return a string.
|
87
|
+
let str = ""
|
88
|
+
for (let i = arg.length - 1; i > -1; i--) {
|
89
|
+
str += arg[i].text
|
90
|
+
}
|
91
|
+
return str
|
92
|
+
}
|
93
|
+
|
94
|
+
// Lookup table for parsing numbers in base 8 through 16
|
95
|
+
const digitToNumber = {
|
96
|
+
0: 0,
|
97
|
+
1: 1,
|
98
|
+
2: 2,
|
99
|
+
3: 3,
|
100
|
+
4: 4,
|
101
|
+
5: 5,
|
102
|
+
6: 6,
|
103
|
+
7: 7,
|
104
|
+
8: 8,
|
105
|
+
9: 9,
|
106
|
+
a: 10,
|
107
|
+
A: 10,
|
108
|
+
b: 11,
|
109
|
+
B: 11,
|
110
|
+
c: 12,
|
111
|
+
C: 12,
|
112
|
+
d: 13,
|
113
|
+
D: 13,
|
114
|
+
e: 14,
|
115
|
+
E: 14,
|
116
|
+
f: 15,
|
117
|
+
F: 15
|
118
|
+
};
|
119
|
+
|
120
|
+
const nextCharNumber = context => {
|
121
|
+
const numStr = context.future().text
|
122
|
+
if (numStr === "EOF") { return [null, ""] }
|
123
|
+
return [digitToNumber[numStr.charAt(0)], numStr]
|
124
|
+
}
|
125
|
+
|
126
|
+
const appendCharNumbers = (number, numStr, base) => {
|
127
|
+
for (let i = 1; i < numStr.length; i++) {
|
128
|
+
const digit = digitToNumber[numStr.charAt(i)]
|
129
|
+
number *= base;
|
130
|
+
number += digit;
|
131
|
+
}
|
132
|
+
return number
|
133
|
+
}
|
134
|
+
|
135
|
+
// TeX \char makes a literal character (catcode 12) using the following forms:
|
136
|
+
// (see The TeXBook, p. 43)
|
137
|
+
// \char123 -- decimal
|
138
|
+
// \char'123 -- octal
|
139
|
+
// \char"123 -- hex
|
140
|
+
// \char`x -- character that can be written (i.e. isn't active)
|
141
|
+
// \char`\x -- character that cannot be written (e.g. %)
|
142
|
+
// These all refer to characters from the font, so we turn them into special
|
143
|
+
// calls to a function \@char dealt with in the Parser.
|
144
|
+
defineMacro("\\char", function(context) {
|
145
|
+
let token = context.popToken();
|
146
|
+
let base;
|
147
|
+
let number = "";
|
148
|
+
if (token.text === "'") {
|
149
|
+
base = 8;
|
150
|
+
token = context.popToken();
|
151
|
+
} else if (token.text === '"') {
|
152
|
+
base = 16;
|
153
|
+
token = context.popToken();
|
154
|
+
} else if (token.text === "`") {
|
155
|
+
token = context.popToken();
|
156
|
+
if (token.text[0] === "\\") {
|
157
|
+
number = token.text.charCodeAt(1);
|
158
|
+
} else if (token.text === "EOF") {
|
159
|
+
throw new ParseError("\\char` missing argument");
|
160
|
+
} else {
|
161
|
+
number = token.text.charCodeAt(0);
|
162
|
+
}
|
163
|
+
} else {
|
164
|
+
base = 10;
|
165
|
+
}
|
166
|
+
if (base) {
|
167
|
+
// Parse a number in the given base, starting with first `token`.
|
168
|
+
let numStr = token.text
|
169
|
+
number = digitToNumber[numStr.charAt(0)];
|
170
|
+
if (number == null || number >= base) {
|
171
|
+
throw new ParseError(`Invalid base-${base} digit ${token.text}`);
|
172
|
+
}
|
173
|
+
number = appendCharNumbers(number, numStr, base)
|
174
|
+
let digit;
|
175
|
+
[digit, numStr] = nextCharNumber(context)
|
176
|
+
while (digit != null && digit < base) {
|
177
|
+
number *= base;
|
178
|
+
number += digit;
|
179
|
+
number = appendCharNumbers(number, numStr, base)
|
180
|
+
context.popToken();
|
181
|
+
[digit, numStr] = nextCharNumber(context)
|
182
|
+
}
|
183
|
+
}
|
184
|
+
return `\\@char{${number}}`;
|
185
|
+
});
|
186
|
+
|
187
|
+
// The Latin Modern font renders <mi>√</mi> at the wrong vertical alignment.
|
188
|
+
// This macro provides a better rendering.
|
189
|
+
defineMacro("\\surd", '\\sqrt{\\vphantom{|}}')
|
190
|
+
|
191
|
+
defineMacro("\\hbox", "\\text{#1}");
|
192
|
+
|
193
|
+
// Per TeXbook p.122, "/" gets zero operator spacing.
|
194
|
+
// And MDN recommends using U+2044 instead of / for inline
|
195
|
+
defineMacro("/", "{\u2044}")
|
196
|
+
|
197
|
+
// Since Temml has no \par, ignore \long.
|
198
|
+
defineMacro("\\long", "")
|
199
|
+
|
200
|
+
//////////////////////////////////////////////////////////////////////
|
201
|
+
// Grouping
|
202
|
+
// \let\bgroup={ \let\egroup=}
|
203
|
+
defineMacro("\\bgroup", "{");
|
204
|
+
defineMacro("\\egroup", "}");
|
205
|
+
|
206
|
+
// Symbols from latex.ltx:
|
207
|
+
// \def~{\nobreakspace{}}
|
208
|
+
// \def\lq{`}
|
209
|
+
// \def\rq{'}
|
210
|
+
// \def \aa {\r a}
|
211
|
+
defineMacro("~", "\\nobreakspace");
|
212
|
+
defineMacro("\\lq", "`");
|
213
|
+
defineMacro("\\rq", "'");
|
214
|
+
defineMacro("\\aa", "\\r a");
|
215
|
+
|
216
|
+
defineMacro("\\Bbbk", "\\Bbb{k}");
|
217
|
+
|
218
|
+
// \mathstrut from the TeXbook, p 360
|
219
|
+
defineMacro("\\mathstrut", "\\vphantom{(}");
|
220
|
+
|
221
|
+
// \underbar from TeXbook p 353
|
222
|
+
defineMacro("\\underbar", "\\underline{\\text{#1}}");
|
223
|
+
|
224
|
+
//////////////////////////////////////////////////////////////////////
|
225
|
+
// LaTeX_2ε
|
226
|
+
|
227
|
+
// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@
|
228
|
+
// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
|
229
|
+
// We'll call \varvdots, which gets a glyph from symbols.js.
|
230
|
+
// The zero-width rule gets us an equivalent to the vertical 6pt kern.
|
231
|
+
defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}");
|
232
|
+
defineMacro("\u22ee", "\\vdots");
|
233
|
+
|
234
|
+
//////////////////////////////////////////////////////////////////////
|
235
|
+
// amsmath.sty
|
236
|
+
// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
|
237
|
+
|
238
|
+
//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
|
239
|
+
defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}");
|
240
|
+
|
241
|
+
// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
|
242
|
+
defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}");
|
243
|
+
|
244
|
+
// \def\iff{\DOTSB\;\Longleftrightarrow\;}
|
245
|
+
// \def\implies{\DOTSB\;\Longrightarrow\;}
|
246
|
+
// \def\impliedby{\DOTSB\;\Longleftarrow\;}
|
247
|
+
defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
|
248
|
+
defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
|
249
|
+
defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;");
|
250
|
+
|
251
|
+
// AMSMath's automatic \dots, based on \mdots@@ macro.
|
252
|
+
const dotsByToken = {
|
253
|
+
",": "\\dotsc",
|
254
|
+
"\\not": "\\dotsb",
|
255
|
+
// \keybin@ checks for the following:
|
256
|
+
"+": "\\dotsb",
|
257
|
+
"=": "\\dotsb",
|
258
|
+
"<": "\\dotsb",
|
259
|
+
">": "\\dotsb",
|
260
|
+
"-": "\\dotsb",
|
261
|
+
"*": "\\dotsb",
|
262
|
+
":": "\\dotsb",
|
263
|
+
// Symbols whose definition starts with \DOTSB:
|
264
|
+
"\\DOTSB": "\\dotsb",
|
265
|
+
"\\coprod": "\\dotsb",
|
266
|
+
"\\bigvee": "\\dotsb",
|
267
|
+
"\\bigwedge": "\\dotsb",
|
268
|
+
"\\biguplus": "\\dotsb",
|
269
|
+
"\\bigcap": "\\dotsb",
|
270
|
+
"\\bigcup": "\\dotsb",
|
271
|
+
"\\prod": "\\dotsb",
|
272
|
+
"\\sum": "\\dotsb",
|
273
|
+
"\\bigotimes": "\\dotsb",
|
274
|
+
"\\bigoplus": "\\dotsb",
|
275
|
+
"\\bigodot": "\\dotsb",
|
276
|
+
"\\bigsqcap": "\\dotsb",
|
277
|
+
"\\bigsqcup": "\\dotsb",
|
278
|
+
"\\And": "\\dotsb",
|
279
|
+
"\\longrightarrow": "\\dotsb",
|
280
|
+
"\\Longrightarrow": "\\dotsb",
|
281
|
+
"\\longleftarrow": "\\dotsb",
|
282
|
+
"\\Longleftarrow": "\\dotsb",
|
283
|
+
"\\longleftrightarrow": "\\dotsb",
|
284
|
+
"\\Longleftrightarrow": "\\dotsb",
|
285
|
+
"\\mapsto": "\\dotsb",
|
286
|
+
"\\longmapsto": "\\dotsb",
|
287
|
+
"\\hookrightarrow": "\\dotsb",
|
288
|
+
"\\doteq": "\\dotsb",
|
289
|
+
// Symbols whose definition starts with \mathbin:
|
290
|
+
"\\mathbin": "\\dotsb",
|
291
|
+
// Symbols whose definition starts with \mathrel:
|
292
|
+
"\\mathrel": "\\dotsb",
|
293
|
+
"\\relbar": "\\dotsb",
|
294
|
+
"\\Relbar": "\\dotsb",
|
295
|
+
"\\xrightarrow": "\\dotsb",
|
296
|
+
"\\xleftarrow": "\\dotsb",
|
297
|
+
// Symbols whose definition starts with \DOTSI:
|
298
|
+
"\\DOTSI": "\\dotsi",
|
299
|
+
"\\int": "\\dotsi",
|
300
|
+
"\\oint": "\\dotsi",
|
301
|
+
"\\iint": "\\dotsi",
|
302
|
+
"\\iiint": "\\dotsi",
|
303
|
+
"\\iiiint": "\\dotsi",
|
304
|
+
"\\idotsint": "\\dotsi",
|
305
|
+
// Symbols whose definition starts with \DOTSX:
|
306
|
+
"\\DOTSX": "\\dotsx"
|
307
|
+
};
|
308
|
+
|
309
|
+
defineMacro("\\dots", function(context) {
|
310
|
+
// TODO: If used in text mode, should expand to \textellipsis.
|
311
|
+
// However, in Temml, \textellipsis and \ldots behave the same
|
312
|
+
// (in text mode), and it's unlikely we'd see any of the math commands
|
313
|
+
// that affect the behavior of \dots when in text mode. So fine for now
|
314
|
+
// (until we support \ifmmode ... \else ... \fi).
|
315
|
+
let thedots = "\\dotso";
|
316
|
+
const next = context.expandAfterFuture().text;
|
317
|
+
if (next in dotsByToken) {
|
318
|
+
thedots = dotsByToken[next];
|
319
|
+
} else if (next.slice(0, 4) === "\\not") {
|
320
|
+
thedots = "\\dotsb";
|
321
|
+
} else if (next in symbols.math) {
|
322
|
+
if (["bin", "rel"].includes(symbols.math[next].group)) {
|
323
|
+
thedots = "\\dotsb";
|
324
|
+
}
|
325
|
+
}
|
326
|
+
return thedots;
|
327
|
+
});
|
328
|
+
|
329
|
+
const spaceAfterDots = {
|
330
|
+
// \rightdelim@ checks for the following:
|
331
|
+
")": true,
|
332
|
+
"]": true,
|
333
|
+
"\\rbrack": true,
|
334
|
+
"\\}": true,
|
335
|
+
"\\rbrace": true,
|
336
|
+
"\\rangle": true,
|
337
|
+
"\\rceil": true,
|
338
|
+
"\\rfloor": true,
|
339
|
+
"\\rgroup": true,
|
340
|
+
"\\rmoustache": true,
|
341
|
+
"\\right": true,
|
342
|
+
"\\bigr": true,
|
343
|
+
"\\biggr": true,
|
344
|
+
"\\Bigr": true,
|
345
|
+
"\\Biggr": true,
|
346
|
+
// \extra@ also tests for the following:
|
347
|
+
$: true,
|
348
|
+
// \extrap@ checks for the following:
|
349
|
+
";": true,
|
350
|
+
".": true,
|
351
|
+
",": true
|
352
|
+
};
|
353
|
+
|
354
|
+
defineMacro("\\dotso", function(context) {
|
355
|
+
const next = context.future().text;
|
356
|
+
if (next in spaceAfterDots) {
|
357
|
+
return "\\ldots\\,";
|
358
|
+
} else {
|
359
|
+
return "\\ldots";
|
360
|
+
}
|
361
|
+
});
|
362
|
+
|
363
|
+
defineMacro("\\dotsc", function(context) {
|
364
|
+
const next = context.future().text;
|
365
|
+
// \dotsc uses \extra@ but not \extrap@, instead specially checking for
|
366
|
+
// ';' and '.', but doesn't check for ','.
|
367
|
+
if (next in spaceAfterDots && next !== ",") {
|
368
|
+
return "\\ldots\\,";
|
369
|
+
} else {
|
370
|
+
return "\\ldots";
|
371
|
+
}
|
372
|
+
});
|
373
|
+
|
374
|
+
defineMacro("\\cdots", function(context) {
|
375
|
+
const next = context.future().text;
|
376
|
+
if (next in spaceAfterDots) {
|
377
|
+
return "\\@cdots\\,";
|
378
|
+
} else {
|
379
|
+
return "\\@cdots";
|
380
|
+
}
|
381
|
+
});
|
382
|
+
|
383
|
+
defineMacro("\\dotsb", "\\cdots");
|
384
|
+
defineMacro("\\dotsm", "\\cdots");
|
385
|
+
defineMacro("\\dotsi", "\\!\\cdots");
|
386
|
+
defineMacro("\\idotsint", "\\dotsi");
|
387
|
+
// amsmath doesn't actually define \dotsx, but \dots followed by a macro
|
388
|
+
// starting with \DOTSX implies \dotso, and then \extra@ detects this case
|
389
|
+
// and forces the added `\,`.
|
390
|
+
defineMacro("\\dotsx", "\\ldots\\,");
|
391
|
+
|
392
|
+
// \let\DOTSI\relax
|
393
|
+
// \let\DOTSB\relax
|
394
|
+
// \let\DOTSX\relax
|
395
|
+
defineMacro("\\DOTSI", "\\relax");
|
396
|
+
defineMacro("\\DOTSB", "\\relax");
|
397
|
+
defineMacro("\\DOTSX", "\\relax");
|
398
|
+
|
399
|
+
// Spacing, based on amsmath.sty's override of LaTeX defaults
|
400
|
+
// \DeclareRobustCommand{\tmspace}[3]{%
|
401
|
+
// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
|
402
|
+
defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax");
|
403
|
+
// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
|
404
|
+
// TODO: math mode should use \thinmuskip
|
405
|
+
defineMacro("\\,", "{\\tmspace+{3mu}{.1667em}}");
|
406
|
+
// \let\thinspace\,
|
407
|
+
defineMacro("\\thinspace", "\\,");
|
408
|
+
// \def\>{\mskip\medmuskip}
|
409
|
+
// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
|
410
|
+
// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
|
411
|
+
defineMacro("\\>", "\\mskip{4mu}");
|
412
|
+
defineMacro("\\:", "{\\tmspace+{4mu}{.2222em}}");
|
413
|
+
// \let\medspace\:
|
414
|
+
defineMacro("\\medspace", "\\:");
|
415
|
+
// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
|
416
|
+
// TODO: math mode should use \thickmuskip = 5mu plus 5mu
|
417
|
+
defineMacro("\\;", "{\\tmspace+{5mu}{.2777em}}");
|
418
|
+
// \let\thickspace\;
|
419
|
+
defineMacro("\\thickspace", "\\;");
|
420
|
+
// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
|
421
|
+
// TODO: math mode should use \thinmuskip
|
422
|
+
defineMacro("\\!", "{\\tmspace-{3mu}{.1667em}}");
|
423
|
+
// \let\negthinspace\!
|
424
|
+
defineMacro("\\negthinspace", "\\!");
|
425
|
+
// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
|
426
|
+
// TODO: math mode should use \medmuskip
|
427
|
+
defineMacro("\\negmedspace", "{\\tmspace-{4mu}{.2222em}}");
|
428
|
+
// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
|
429
|
+
// TODO: math mode should use \thickmuskip
|
430
|
+
defineMacro("\\negthickspace", "{\\tmspace-{5mu}{.277em}}");
|
431
|
+
// \def\enspace{\kern.5em }
|
432
|
+
defineMacro("\\enspace", "\\kern.5em ");
|
433
|
+
// \def\enskip{\hskip.5em\relax}
|
434
|
+
defineMacro("\\enskip", "\\hskip.5em\\relax");
|
435
|
+
// \def\quad{\hskip1em\relax}
|
436
|
+
defineMacro("\\quad", "\\hskip1em\\relax");
|
437
|
+
// \def\qquad{\hskip2em\relax}
|
438
|
+
defineMacro("\\qquad", "\\hskip2em\\relax");
|
439
|
+
|
440
|
+
// \tag@in@display form of \tag
|
441
|
+
defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
|
442
|
+
defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
|
443
|
+
defineMacro("\\tag@literal", (context) => {
|
444
|
+
if (context.macros.get("\\df@tag")) {
|
445
|
+
throw new ParseError("Multiple \\tag");
|
446
|
+
}
|
447
|
+
return "\\def\\df@tag{\\text{#1}}";
|
448
|
+
});
|
449
|
+
|
450
|
+
// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
|
451
|
+
// {\operator@font mod}\penalty900
|
452
|
+
// \mkern5mu\nonscript\mskip-\medmuskip}
|
453
|
+
// \newcommand{\pod}[1]{\allowbreak
|
454
|
+
// \if@display\mkern18mu\else\mkern8mu\fi(#1)}
|
455
|
+
// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
|
456
|
+
// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
|
457
|
+
// \else\mkern12mu\fi{\operator@font mod}\,\,#1}
|
458
|
+
// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
|
459
|
+
defineMacro("\\bmod", "\\mathbin{\\text{mod}}");
|
460
|
+
defineMacro(
|
461
|
+
"\\pod",
|
462
|
+
"\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"
|
463
|
+
);
|
464
|
+
defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
|
465
|
+
defineMacro(
|
466
|
+
"\\mod",
|
467
|
+
"\\allowbreak" +
|
468
|
+
"\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" +
|
469
|
+
"{\\rm mod}\\,\\,#1"
|
470
|
+
);
|
471
|
+
|
472
|
+
//////////////////////////////////////////////////////////////////////
|
473
|
+
// LaTeX source2e
|
474
|
+
|
475
|
+
// \expandafter\let\expandafter\@normalcr
|
476
|
+
// \csname\expandafter\@gobble\string\\ \endcsname
|
477
|
+
// \DeclareRobustCommand\newline{\@normalcr\relax}
|
478
|
+
defineMacro("\\newline", "\\\\\\relax");
|
479
|
+
|
480
|
+
// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
|
481
|
+
// TODO: Doesn't normally work in math mode because \@ fails.
|
482
|
+
defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}");
|
483
|
+
|
484
|
+
defineMacro(
|
485
|
+
"\\LaTeX",
|
486
|
+
"\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX"
|
487
|
+
);
|
488
|
+
|
489
|
+
defineMacro(
|
490
|
+
"\\Temml",
|
491
|
+
// eslint-disable-next-line max-len
|
492
|
+
"\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}"
|
493
|
+
);
|
494
|
+
|
495
|
+
// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
|
496
|
+
// \def\@hspace#1{\hskip #1\relax}
|
497
|
+
// \def\@hspacer#1{\vrule \@width\z@\nobreak
|
498
|
+
// \hskip #1\hskip \z@skip}
|
499
|
+
defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
|
500
|
+
defineMacro("\\@hspace", "\\hskip #1\\relax");
|
501
|
+
defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax");
|
502
|
+
|
503
|
+
defineMacro("\\colon", `\\mathpunct{\\char"3a}`)
|
504
|
+
|
505
|
+
//////////////////////////////////////////////////////////////////////
|
506
|
+
// mathtools.sty
|
507
|
+
|
508
|
+
defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}")
|
509
|
+
|
510
|
+
//\providecommand\ordinarycolon{:}
|
511
|
+
defineMacro("\\ordinarycolon", `\\char"3a`);
|
512
|
+
// Raise to center on the math axis, as closely as possible.
|
513
|
+
defineMacro("\\vcentcolon", "\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}");
|
514
|
+
// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
|
515
|
+
defineMacro("\\coloneq", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}');
|
516
|
+
// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
|
517
|
+
defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}');
|
518
|
+
// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
|
519
|
+
defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}');
|
520
|
+
// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
|
521
|
+
defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}');
|
522
|
+
// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
|
523
|
+
defineMacro("\\colonapprox", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}');
|
524
|
+
// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
|
525
|
+
defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}');
|
526
|
+
// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
|
527
|
+
defineMacro("\\colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}');
|
528
|
+
// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
|
529
|
+
defineMacro("\\Colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}');
|
530
|
+
|
531
|
+
//////////////////////////////////////////////////////////////////////
|
532
|
+
// colonequals.sty
|
533
|
+
|
534
|
+
// Alternate names for mathtools's macros:
|
535
|
+
defineMacro("\\ratio", "\\vcentcolon");
|
536
|
+
defineMacro("\\coloncolon", "\\dblcolon");
|
537
|
+
defineMacro("\\colonequals", "\\coloneqq");
|
538
|
+
defineMacro("\\coloncolonequals", "\\Coloneqq");
|
539
|
+
defineMacro("\\equalscolon", "\\eqqcolon");
|
540
|
+
defineMacro("\\equalscoloncolon", "\\Eqqcolon");
|
541
|
+
defineMacro("\\colonminus", "\\coloneq");
|
542
|
+
defineMacro("\\coloncolonminus", "\\Coloneq");
|
543
|
+
defineMacro("\\minuscolon", "\\eqcolon");
|
544
|
+
defineMacro("\\minuscoloncolon", "\\Eqcolon");
|
545
|
+
// \colonapprox name is same in mathtools and colonequals.
|
546
|
+
defineMacro("\\coloncolonapprox", "\\Colonapprox");
|
547
|
+
// \colonsim name is same in mathtools and colonequals.
|
548
|
+
defineMacro("\\coloncolonsim", "\\Colonsim");
|
549
|
+
|
550
|
+
// Present in newtxmath, pxfonts and txfonts
|
551
|
+
defineMacro("\\notni", "\\mathrel{\\char`\u220C}");
|
552
|
+
defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
|
553
|
+
defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}");
|
554
|
+
|
555
|
+
//////////////////////////////////////////////////////////////////////
|
556
|
+
// From amsopn.sty
|
557
|
+
defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
|
558
|
+
defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
|
559
|
+
defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}");
|
560
|
+
defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}");
|
561
|
+
defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}");
|
562
|
+
defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}");
|
563
|
+
|
564
|
+
defineMacro("\\centerdot", "{\\medspace\\rule{0.167em}{0.189em}\\medspace}")
|
565
|
+
|
566
|
+
//////////////////////////////////////////////////////////////////////
|
567
|
+
// statmath.sty
|
568
|
+
// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
|
569
|
+
|
570
|
+
defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
|
571
|
+
defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
|
572
|
+
defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}");
|
573
|
+
|
574
|
+
//////////////////////////////////////////////////////////////////////
|
575
|
+
// braket.sty
|
576
|
+
// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
|
577
|
+
|
578
|
+
defineMacro("\\bra", "\\mathinner{\\langle{#1}|}");
|
579
|
+
defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
|
580
|
+
defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
|
581
|
+
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
582
|
+
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
583
|
+
const braketHelper = (one) => (context) => {
|
584
|
+
const left = context.consumeArg().tokens;
|
585
|
+
const middle = context.consumeArg().tokens;
|
586
|
+
const middleDouble = context.consumeArg().tokens;
|
587
|
+
const right = context.consumeArg().tokens;
|
588
|
+
const oldMiddle = context.macros.get("|");
|
589
|
+
const oldMiddleDouble = context.macros.get("\\|");
|
590
|
+
context.macros.beginGroup();
|
591
|
+
const midMacro = (double) => (context) => {
|
592
|
+
if (one) {
|
593
|
+
// Only modify the first instance of | or \|
|
594
|
+
context.macros.set("|", oldMiddle);
|
595
|
+
if (middleDouble.length) {
|
596
|
+
context.macros.set("\\|", oldMiddleDouble);
|
597
|
+
}
|
598
|
+
}
|
599
|
+
let doubled = double;
|
600
|
+
if (!double && middleDouble.length) {
|
601
|
+
// Mimic \@ifnextchar
|
602
|
+
const nextToken = context.future();
|
603
|
+
if (nextToken.text === "|") {
|
604
|
+
context.popToken();
|
605
|
+
doubled = true;
|
606
|
+
}
|
607
|
+
}
|
608
|
+
return {
|
609
|
+
tokens: doubled ? middleDouble : middle,
|
610
|
+
numArgs: 0
|
611
|
+
};
|
612
|
+
};
|
613
|
+
context.macros.set("|", midMacro(false));
|
614
|
+
if (middleDouble.length) {
|
615
|
+
context.macros.set("\\|", midMacro(true));
|
616
|
+
}
|
617
|
+
const arg = context.consumeArg().tokens;
|
618
|
+
const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed
|
619
|
+
context.macros.endGroup();
|
620
|
+
return {
|
621
|
+
tokens: expanded.reverse(),
|
622
|
+
numArgs: 0
|
623
|
+
};
|
624
|
+
};
|
625
|
+
defineMacro("\\bra@ket", braketHelper(false));
|
626
|
+
defineMacro("\\bra@set", braketHelper(true));
|
627
|
+
defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" +
|
628
|
+
"{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");
|
629
|
+
defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" +
|
630
|
+
"{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");
|
631
|
+
defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");
|
632
|
+
// has no support for special || or \|
|
633
|
+
|
634
|
+
//////////////////////////////////////////////////////////////////////
|
635
|
+
// actuarialangle.dtx
|
636
|
+
defineMacro("\\angln", "{\\angl n}");
|
637
|
+
|
638
|
+
//////////////////////////////////////////////////////////////////////
|
639
|
+
// derivative.sty
|
640
|
+
defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator");
|
641
|
+
defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}")
|
642
|
+
defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1")
|
643
|
+
defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator");
|
644
|
+
|
645
|
+
const pdvHelper = args => {
|
646
|
+
const numerator = args[0][0].text
|
647
|
+
const denoms = stringFromArg(args[1]).split(",")
|
648
|
+
const power = String(denoms.length)
|
649
|
+
const numOp = power === "1" ? "\\partial" : `\\partial^${power}`
|
650
|
+
let denominator = ""
|
651
|
+
denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,"})
|
652
|
+
return [numerator, numOp, denominator.replace(/\\,$/, "")]
|
653
|
+
}
|
654
|
+
defineMacro("\\pdv@numerator", function(context) {
|
655
|
+
const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2))
|
656
|
+
return `\\frac{${numOp} ${numerator}}{${denominator}}`
|
657
|
+
})
|
658
|
+
defineMacro("\\pdv@next", function(context) {
|
659
|
+
const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2))
|
660
|
+
return `\\frac{${numOp}}{${denominator}} ${numerator}`
|
661
|
+
})
|
662
|
+
|
663
|
+
//////////////////////////////////////////////////////////////////////
|
664
|
+
// upgreek.dtx
|
665
|
+
defineMacro("\\upalpha", "\\up@greek{\\alpha}");
|
666
|
+
defineMacro("\\upbeta", "\\up@greek{\\beta}");
|
667
|
+
defineMacro("\\upgamma", "\\up@greek{\\gamma}");
|
668
|
+
defineMacro("\\updelta", "\\up@greek{\\delta}");
|
669
|
+
defineMacro("\\upepsilon", "\\up@greek{\\epsilon}");
|
670
|
+
defineMacro("\\upzeta", "\\up@greek{\\zeta}");
|
671
|
+
defineMacro("\\upeta", "\\up@greek{\\eta}");
|
672
|
+
defineMacro("\\uptheta", "\\up@greek{\\theta}");
|
673
|
+
defineMacro("\\upiota", "\\up@greek{\\iota}");
|
674
|
+
defineMacro("\\upkappa", "\\up@greek{\\kappa}");
|
675
|
+
defineMacro("\\uplambda", "\\up@greek{\\lambda}");
|
676
|
+
defineMacro("\\upmu", "\\up@greek{\\mu}");
|
677
|
+
defineMacro("\\upnu", "\\up@greek{\\nu}");
|
678
|
+
defineMacro("\\upxi", "\\up@greek{\\xi}");
|
679
|
+
defineMacro("\\upomicron", "\\up@greek{\\omicron}");
|
680
|
+
defineMacro("\\uppi", "\\up@greek{\\pi}");
|
681
|
+
defineMacro("\\upalpha", "\\up@greek{\\alpha}");
|
682
|
+
defineMacro("\\uprho", "\\up@greek{\\rho}");
|
683
|
+
defineMacro("\\upsigma", "\\up@greek{\\sigma}");
|
684
|
+
defineMacro("\\uptau", "\\up@greek{\\tau}");
|
685
|
+
defineMacro("\\upupsilon", "\\up@greek{\\upsilon}");
|
686
|
+
defineMacro("\\upphi", "\\up@greek{\\phi}");
|
687
|
+
defineMacro("\\upchi", "\\up@greek{\\chi}");
|
688
|
+
defineMacro("\\uppsi", "\\up@greek{\\psi}");
|
689
|
+
defineMacro("\\upomega", "\\up@greek{\\omega}");
|
690
|
+
|
691
|
+
//////////////////////////////////////////////////////////////////////
|
692
|
+
// cmll package
|
693
|
+
defineMacro("\\invamp", '\\mathbin{\\char"214b}')
|
694
|
+
defineMacro("\\parr", '\\mathbin{\\char"214b}')
|
695
|
+
defineMacro("\\with", '\\mathbin{\\char"26}')
|
696
|
+
defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}')
|
697
|
+
defineMacro("\\multimapboth", '\\mathrel{\\char"29df}')
|
698
|
+
defineMacro("\\scoh", '{\\mkern5mu\\char"2322\\mkern5mu}')
|
699
|
+
defineMacro("\\sincoh", '{\\mkern5mu\\char"2323\\mkern5mu}')
|
700
|
+
defineMacro("\\coh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}}
|
701
|
+
{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}`)
|
702
|
+
defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}}
|
703
|
+
{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}`)
|
704
|
+
|
705
|
+
|
706
|
+
//////////////////////////////////////////////////////////////////////
|
707
|
+
// chemstyle package
|
708
|
+
defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}");
|