kmap-term-tree 0.9.21 → 0.9.22

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.
@@ -0,0 +1,554 @@
1
+ import { TermNode, GERMAN_LABELS, OPERATOR_SYMBOLS } from './model.js';
2
+
3
+ const KNOWN_FUNCTIONS = new Set([
4
+ 'sin',
5
+ 'cos',
6
+ 'tan',
7
+ 'cot',
8
+ 'sec',
9
+ 'csc',
10
+ 'arcsin',
11
+ 'arccos',
12
+ 'arctan',
13
+ 'sinh',
14
+ 'cosh',
15
+ 'tanh',
16
+ 'exp',
17
+ 'ln',
18
+ 'log',
19
+ 'sqrt',
20
+ 'abs',
21
+ ]);
22
+
23
+ const FUNCTION_MAP: Record<string, string> = {
24
+ sin: 'Sin',
25
+ cos: 'Cos',
26
+ tan: 'Tan',
27
+ cot: 'Cot',
28
+ arcsin: 'Arcsin',
29
+ arccos: 'Arccos',
30
+ arctan: 'Arctan',
31
+ sinh: 'Sinh',
32
+ cosh: 'Cosh',
33
+ tanh: 'Tanh',
34
+ ln: 'Ln',
35
+ log: 'Log',
36
+ sqrt: 'Sqrt',
37
+ abs: 'Abs',
38
+ exp: 'Exp',
39
+ };
40
+
41
+ const GREEK_LETTERS = new Set([
42
+ 'alpha',
43
+ 'beta',
44
+ 'gamma',
45
+ 'delta',
46
+ 'epsilon',
47
+ 'zeta',
48
+ 'eta',
49
+ 'theta',
50
+ 'iota',
51
+ 'kappa',
52
+ 'lambda',
53
+ 'mu',
54
+ 'nu',
55
+ 'xi',
56
+ 'pi',
57
+ 'rho',
58
+ 'sigma',
59
+ 'tau',
60
+ 'upsilon',
61
+ 'phi',
62
+ 'chi',
63
+ 'psi',
64
+ 'omega',
65
+ ]);
66
+
67
+ type TokenType =
68
+ | 'NUMBER'
69
+ | 'VARIABLE'
70
+ | 'FUNCTION'
71
+ | 'OPERATOR'
72
+ | 'LPAREN'
73
+ | 'RPAREN'
74
+ | 'COMMA'
75
+ | 'EOF';
76
+
77
+ interface Token {
78
+ type: TokenType;
79
+ value: string;
80
+ implicit?: boolean;
81
+ }
82
+
83
+ class Tokenizer {
84
+ private input: string;
85
+ private pos = 0;
86
+
87
+ constructor(input: string) {
88
+ this.input = input.trim();
89
+ }
90
+
91
+ tokenize(): Token[] {
92
+ const rawTokens: Token[] = [];
93
+
94
+ while (this.pos < this.input.length) {
95
+ const ch = this.input[this.pos];
96
+
97
+ if (/\s/.test(ch)) {
98
+ this.pos++;
99
+ continue;
100
+ }
101
+
102
+ // Numbers: integer or floating point
103
+ if (/\d/.test(ch)) {
104
+ let num = '';
105
+ while (
106
+ this.pos < this.input.length &&
107
+ /[\d.]/.test(this.input[this.pos])
108
+ ) {
109
+ num += this.input[this.pos++];
110
+ }
111
+ rawTokens.push({ type: 'NUMBER', value: num });
112
+ continue;
113
+ }
114
+
115
+ // Words: functions, greek letters, or sequences of variable characters
116
+ if (/[a-zA-Z]/.test(ch)) {
117
+ let word = '';
118
+ while (
119
+ this.pos < this.input.length &&
120
+ /[a-zA-Z]/.test(this.input[this.pos])
121
+ ) {
122
+ word += this.input[this.pos++];
123
+ }
124
+ const lower = word.toLowerCase();
125
+
126
+ if (KNOWN_FUNCTIONS.has(lower)) {
127
+ rawTokens.push({ type: 'FUNCTION', value: lower });
128
+ } else if (GREEK_LETTERS.has(lower)) {
129
+ rawTokens.push({ type: 'VARIABLE', value: lower });
130
+ } else {
131
+ // In school mathematics, "2ab" or "xy" means 2 * a * b or x * y
132
+ for (const char of word) {
133
+ rawTokens.push({ type: 'VARIABLE', value: char });
134
+ }
135
+ }
136
+ continue;
137
+ }
138
+
139
+ // 'xx' or '·' or '*' as multiplication
140
+ if (ch === 'x' && this.input[this.pos + 1] === 'x') {
141
+ rawTokens.push({ type: 'OPERATOR', value: '*' });
142
+ this.pos += 2;
143
+ continue;
144
+ }
145
+ if (ch === '·' || ch === '*') {
146
+ rawTokens.push({ type: 'OPERATOR', value: '*' });
147
+ this.pos++;
148
+ continue;
149
+ }
150
+
151
+ // Division: '/' or ':'
152
+ if (ch === '/' || ch === ':') {
153
+ rawTokens.push({ type: 'OPERATOR', value: ch });
154
+ this.pos++;
155
+ continue;
156
+ }
157
+
158
+ // Other operators
159
+ if (ch === '+' || ch === '-' || ch === '^') {
160
+ rawTokens.push({ type: 'OPERATOR', value: ch });
161
+ this.pos++;
162
+ continue;
163
+ }
164
+
165
+ // Parentheses & brackets
166
+ if (ch === '(' || ch === '[') {
167
+ rawTokens.push({ type: 'LPAREN', value: ch });
168
+ this.pos++;
169
+ continue;
170
+ }
171
+ if (ch === ')' || ch === ']') {
172
+ rawTokens.push({ type: 'RPAREN', value: ch });
173
+ this.pos++;
174
+ continue;
175
+ }
176
+
177
+ if (ch === ',') {
178
+ rawTokens.push({ type: 'COMMA', value: ch });
179
+ this.pos++;
180
+ continue;
181
+ }
182
+
183
+ // Fallback: skip unrecognized characters
184
+ this.pos++;
185
+ }
186
+
187
+ // Insert implicit multiplication between operands where appropriate
188
+ const tokens: Token[] = [];
189
+ for (let i = 0; i < rawTokens.length; i++) {
190
+ const cur = rawTokens[i];
191
+ tokens.push(cur);
192
+
193
+ if (i < rawTokens.length - 1) {
194
+ const next = rawTokens[i + 1];
195
+ const curEndsOperand =
196
+ cur.type === 'NUMBER' ||
197
+ cur.type === 'VARIABLE' ||
198
+ cur.type === 'RPAREN';
199
+ const nextStartsOperand =
200
+ next.type === 'NUMBER' ||
201
+ next.type === 'VARIABLE' ||
202
+ next.type === 'FUNCTION' ||
203
+ next.type === 'LPAREN';
204
+
205
+ if (curEndsOperand && nextStartsOperand) {
206
+ tokens.push({ type: 'OPERATOR', value: '*', implicit: true });
207
+ }
208
+ }
209
+ }
210
+
211
+ tokens.push({ type: 'EOF', value: '' });
212
+ return tokens;
213
+ }
214
+ }
215
+
216
+ let nodeIdCounter = 1;
217
+
218
+ export function resetNodeIdCounter() {
219
+ nodeIdCounter = 1;
220
+ }
221
+
222
+ class PrattParser {
223
+ private tokens: Token[];
224
+ private pos = 0;
225
+
226
+ constructor(tokens: Token[]) {
227
+ this.tokens = tokens;
228
+ }
229
+
230
+ private current(): Token {
231
+ return this.tokens[this.pos];
232
+ }
233
+
234
+ private consume(expectedType?: TokenType): Token {
235
+ const token = this.current();
236
+ if (expectedType && token.type !== expectedType) {
237
+ throw new Error(
238
+ `Erwartet ${expectedType}, aber erhalten: ${token.type} (${token.value})`
239
+ );
240
+ }
241
+ this.pos++;
242
+ return token;
243
+ }
244
+
245
+ parse(precedence = 0): TermNode {
246
+ let left = this.parsePrefix();
247
+
248
+ while (true) {
249
+ const token = this.current();
250
+ if (token.type !== 'OPERATOR') break;
251
+
252
+ const opPrec = this.getInfixPrecedence(token.value);
253
+ if (opPrec <= precedence) break;
254
+
255
+ this.pos++;
256
+ left = this.parseInfix(left, token, opPrec);
257
+ }
258
+
259
+ return left;
260
+ }
261
+
262
+ private parsePrefix(): TermNode {
263
+ const token = this.current();
264
+
265
+ if (token.type === 'NUMBER') {
266
+ this.pos++;
267
+ const val = parseFloat(token.value);
268
+ return {
269
+ id: `n${nodeIdCounter++}`,
270
+ type: 'literal',
271
+ value: val,
272
+ raw: token.value,
273
+ symbol: token.value,
274
+ label: `Zahl ${token.value}`,
275
+ mathJson: val,
276
+ children: [],
277
+ depth: 0,
278
+ };
279
+ }
280
+
281
+ if (token.type === 'VARIABLE') {
282
+ this.pos++;
283
+ return {
284
+ id: `n${nodeIdCounter++}`,
285
+ type: 'variable',
286
+ raw: token.value,
287
+ symbol: token.value,
288
+ label: `Variable ${token.value}`,
289
+ mathJson: token.value,
290
+ children: [],
291
+ depth: 0,
292
+ };
293
+ }
294
+
295
+ if (token.type === 'FUNCTION') {
296
+ this.pos++;
297
+ const fnName = FUNCTION_MAP[token.value] || token.value;
298
+ let arg: TermNode;
299
+
300
+ if (this.current().type === 'LPAREN') {
301
+ this.consume('LPAREN');
302
+ arg = this.parse(0);
303
+ this.consume('RPAREN');
304
+ } else {
305
+ arg = this.parse(35); // higher than *, /, ^
306
+ }
307
+
308
+ const symbol = token.value === 'sqrt' ? '√' : token.value;
309
+
310
+ return {
311
+ id: `n${nodeIdCounter++}`,
312
+ type: 'function',
313
+ op: fnName,
314
+ symbol,
315
+ label: GERMAN_LABELS[fnName] || fnName,
316
+ mathJson: [fnName, arg.mathJson],
317
+ children: [arg],
318
+ depth: 0,
319
+ };
320
+ }
321
+
322
+ // Unary plus or minus
323
+ if (
324
+ token.type === 'OPERATOR' &&
325
+ (token.value === '-' || token.value === '+')
326
+ ) {
327
+ this.pos++;
328
+ const op = token.value;
329
+ const operand = this.parse(30); // Prefix unary precedence
330
+
331
+ if (op === '-') {
332
+ return {
333
+ id: `n${nodeIdCounter++}`,
334
+ type: 'operator',
335
+ isUnary: true,
336
+ op: 'Negate',
337
+ symbol: '−',
338
+ label: GERMAN_LABELS['Negate'],
339
+ mathJson: ['Negate', operand.mathJson],
340
+ children: [operand],
341
+ depth: 0,
342
+ };
343
+ } else {
344
+ return operand;
345
+ }
346
+ }
347
+
348
+ // Parentheses
349
+ if (token.type === 'LPAREN') {
350
+ this.pos++;
351
+ const expr = this.parse(0);
352
+ this.consume('RPAREN');
353
+ expr.isParenthesized = true;
354
+ return expr;
355
+ }
356
+
357
+ throw new Error(`Unerwartetes Zeichen: ${token.value || token.type}`);
358
+ }
359
+
360
+ private getInfixPrecedence(op: string): number {
361
+ switch (op) {
362
+ case '+':
363
+ case '-':
364
+ return 10;
365
+ case '*':
366
+ case '/':
367
+ case ':':
368
+ return 20;
369
+ case '^':
370
+ return 40;
371
+ default:
372
+ return 0;
373
+ }
374
+ }
375
+
376
+ private parseInfix(
377
+ left: TermNode,
378
+ token: Token,
379
+ precedence: number
380
+ ): TermNode {
381
+ const op = token.value;
382
+ const isRightAssoc = op === '^';
383
+ const nextPrec = isRightAssoc ? precedence - 1 : precedence;
384
+ const right = this.parse(nextPrec);
385
+
386
+ let opName = 'Add';
387
+ if (op === '-') opName = 'Subtract';
388
+ else if (op === '*') opName = 'Multiply';
389
+ else if (op === '/' || op === ':') opName = 'Divide';
390
+ else if (op === '^') opName = 'Power';
391
+
392
+ const symbol = OPERATOR_SYMBOLS[opName] || op;
393
+ const label = GERMAN_LABELS[opName] || opName;
394
+
395
+ return {
396
+ id: `n${nodeIdCounter++}`,
397
+ type: 'operator',
398
+ op: opName,
399
+ symbol,
400
+ label,
401
+ implicit: token.implicit,
402
+ mathJson: [opName, left.mathJson, right.mathJson],
403
+ children: [left, right],
404
+ depth: 0,
405
+ };
406
+ }
407
+ }
408
+
409
+ /**
410
+ * Calculates depths bottom-up:
411
+ * Leaves have depth 0.
412
+ * A parent node has depth = max(children.depth) + 1.
413
+ * Returns the maximum depth of the tree.
414
+ */
415
+ export function calculateDepths(node: TermNode): number {
416
+ if (node.children.length === 0) {
417
+ node.depth = 0;
418
+ return 0;
419
+ }
420
+ let maxChild = 0;
421
+ for (const child of node.children) {
422
+ maxChild = Math.max(maxChild, calculateDepths(child));
423
+ }
424
+ node.depth = maxChild + 1;
425
+ return node.depth;
426
+ }
427
+
428
+ /**
429
+ * Parses an AsciiMath string into a TermNode AST with Math-JSON support.
430
+ */
431
+ export function parseAsciiMath(input: string): TermNode {
432
+ resetNodeIdCounter();
433
+ const tokenizer = new Tokenizer(input);
434
+ const tokens = tokenizer.tokenize();
435
+ const parser = new PrattParser(tokens);
436
+ const root = parser.parse(0);
437
+ calculateDepths(root);
438
+ return root;
439
+ }
440
+
441
+ function getOperatorPrecedence(node: TermNode): number {
442
+ if (node.type !== 'operator') return 999;
443
+ if (node.isUnary) return 30;
444
+ switch (node.op) {
445
+ case 'Add':
446
+ case 'Subtract':
447
+ return 10;
448
+ case 'Multiply':
449
+ case 'Divide':
450
+ return 20;
451
+ case 'Power':
452
+ return 40;
453
+ default:
454
+ return 0;
455
+ }
456
+ }
457
+
458
+ function needsParens(
459
+ parent: TermNode,
460
+ child: TermNode,
461
+ isLeft: boolean
462
+ ): boolean {
463
+ if (child.isParenthesized) return true;
464
+ if (child.type !== 'operator') return false;
465
+
466
+ const pPrec = getOperatorPrecedence(parent);
467
+ const cPrec = getOperatorPrecedence(child);
468
+
469
+ if (cPrec < pPrec) return true;
470
+ if (cPrec === pPrec) {
471
+ // Subtraction and division are left-associative, right operand needs parentheses
472
+ if (!isLeft && (parent.op === 'Subtract' || parent.op === 'Divide'))
473
+ return true;
474
+ }
475
+ return false;
476
+ }
477
+
478
+ /**
479
+ * Generates LaTeX from the AST with embedded `\htmlId{...}` for KaTeX.
480
+ */
481
+ export function astToAnnotatedLatex(node: TermNode): string {
482
+ if (node.type === 'literal') {
483
+ return `\\htmlId{${node.id}}{${node.raw}}`;
484
+ }
485
+
486
+ if (node.type === 'variable') {
487
+ // Greek letters support (e.g. \pi, \alpha)
488
+ const varName = GREEK_LETTERS.has(node.symbol)
489
+ ? `\\${node.symbol}`
490
+ : node.symbol;
491
+ return `\\htmlId{${node.id}}{${varName}}`;
492
+ }
493
+
494
+ if (node.type === 'function') {
495
+ const childLatex = astToAnnotatedLatex(node.children[0]);
496
+ let fnSymbol: string;
497
+ if (node.op === 'Sqrt' || node.symbol === '√' || node.symbol === 'sqrt') {
498
+ fnSymbol = `\\sqrt{${childLatex}}`;
499
+ } else if (node.symbol === 'abs') {
500
+ fnSymbol = `\\left|${childLatex}\\right|`;
501
+ } else {
502
+ fnSymbol = `\\operatorname{${node.symbol}}\\left(${childLatex}\\right)`;
503
+ }
504
+ return `\\htmlId{${node.id}}{${fnSymbol}}`;
505
+ }
506
+
507
+ if (node.type === 'operator') {
508
+ if (node.isUnary) {
509
+ const childLatex = astToAnnotatedLatex(node.children[0]);
510
+ return `\\htmlId{${node.id}}{-${childLatex}}`;
511
+ }
512
+
513
+ const left = node.children[0];
514
+ const right = node.children[1];
515
+
516
+ let leftLatex = astToAnnotatedLatex(left);
517
+ let rightLatex = astToAnnotatedLatex(right);
518
+
519
+ if (needsParens(node, left, true)) {
520
+ leftLatex = `\\left(${leftLatex}\\right)`;
521
+ }
522
+ if (needsParens(node, right, false)) {
523
+ rightLatex = `\\left(${rightLatex}\\right)`;
524
+ }
525
+
526
+ if (node.op === 'Add') {
527
+ return `\\htmlId{${node.id}}{${leftLatex} \\htmlId{op_${node.id}}{+} ${rightLatex}}`;
528
+ }
529
+ if (node.op === 'Subtract') {
530
+ return `\\htmlId{${node.id}}{${leftLatex} \\htmlId{op_${node.id}}{-} ${rightLatex}}`;
531
+ }
532
+ if (node.op === 'Multiply') {
533
+ // Implicit multiplication styling (e.g. 2a, 4ac, (2+a)(3-b))
534
+ const isImplicit =
535
+ node.implicit ||
536
+ (left.type === 'literal' &&
537
+ (right.type === 'variable' || right.type === 'function')) ||
538
+ (left.type === 'variable' && right.type === 'variable') ||
539
+ right.isParenthesized;
540
+ const opSymbol = isImplicit
541
+ ? ''
542
+ : ' \\htmlId{op_' + node.id + '}{\\cdot} ';
543
+ return `\\htmlId{${node.id}}{${leftLatex}${opSymbol}${rightLatex}}`;
544
+ }
545
+ if (node.op === 'Divide') {
546
+ return `\\htmlId{${node.id}}{\\frac{${leftLatex}}{${rightLatex}}}`;
547
+ }
548
+ if (node.op === 'Power') {
549
+ return `\\htmlId{${node.id}}{${leftLatex}^{${rightLatex}}}`;
550
+ }
551
+ }
552
+
553
+ return '';
554
+ }
package/src/index.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { KmapTermTree } from './KmapTermTree.js';
2
+ export { parseAsciiMath } from './asciimath-parser.js';
3
+ export * from './model.js';
@@ -0,0 +1,7 @@
1
+ import { css, CSSResult } from 'lit';
2
+
3
+ // language=CSS
4
+ export const katexStyles: CSSResult = css`
5
+ @font-face{font-display:block;font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_AMS-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-display:block;font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Script-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size1-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size2-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size3-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size4-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-display:block;font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,math,Times New Roman,serif;line-height:1.2;position:relative;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.19.1"}.katex .katex-mathml{border:0;-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.katex-newline{display:block}.katex .katex-base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .katex-base,.katex .katex-strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .mathsfit,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .katex-vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .katex-thinbox{display:inline-flex;flex-direction:row;max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .katex-hdashline,.katex .katex-hline,.katex .katex-overline .overline-line,.katex .katex-rule,.katex .katex-underline .underline-line,.katex .mfrac .frac-line{min-height:1px}.katex .mspace{display:inline-block}.katex .katex-smash{display:inline;line-height:0}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.katex-inner,.katex .llap>.katex-inner,.katex .rlap>.katex-inner{position:absolute}.katex .clap>.katex-fix,.katex .llap>.katex-fix,.katex .rlap>.katex-fix{display:inline-block}.katex .llap>.katex-inner{right:0}.katex .clap>.katex-inner,.katex .rlap>.katex-inner{left:0}.katex .clap>.katex-inner>span{margin-left:-50%;margin-right:50%}.katex .katex-rule{border:0 solid;display:inline-block;position:relative}.katex .katex-hline,.katex .katex-overline .overline-line,.katex .katex-underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .katex-hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.katex-root{margin-left:.2777777778em;margin-right:-.5555555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .katex-sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .katex-sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .katex-sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .katex-sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .katex-sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .katex-sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .katex-sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .katex-sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .katex-sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .katex-sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .katex-sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .katex-sizing.reset-size2.size1{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .katex-sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .katex-sizing.reset-size2.size3{font-size:1.1666666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .katex-sizing.reset-size2.size4{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .katex-sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .katex-sizing.reset-size2.size6{font-size:1.6666666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .katex-sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .katex-sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .katex-sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .katex-sizing.reset-size2.size10{font-size:3.4566666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .katex-sizing.reset-size2.size11{font-size:4.1466666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .katex-sizing.reset-size3.size1{font-size:.7142857143em}.katex .fontsize-ensurer.reset-size3.size2,.katex .katex-sizing.reset-size3.size2{font-size:.8571428571em}.katex .fontsize-ensurer.reset-size3.size3,.katex .katex-sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .katex-sizing.reset-size3.size4{font-size:1.1428571429em}.katex .fontsize-ensurer.reset-size3.size5,.katex .katex-sizing.reset-size3.size5{font-size:1.2857142857em}.katex .fontsize-ensurer.reset-size3.size6,.katex .katex-sizing.reset-size3.size6{font-size:1.4285714286em}.katex .fontsize-ensurer.reset-size3.size7,.katex .katex-sizing.reset-size3.size7{font-size:1.7142857143em}.katex .fontsize-ensurer.reset-size3.size8,.katex .katex-sizing.reset-size3.size8{font-size:2.0571428571em}.katex .fontsize-ensurer.reset-size3.size9,.katex .katex-sizing.reset-size3.size9{font-size:2.4685714286em}.katex .fontsize-ensurer.reset-size3.size10,.katex .katex-sizing.reset-size3.size10{font-size:2.9628571429em}.katex .fontsize-ensurer.reset-size3.size11,.katex .katex-sizing.reset-size3.size11{font-size:3.5542857143em}.katex .fontsize-ensurer.reset-size4.size1,.katex .katex-sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .katex-sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .katex-sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .katex-sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .katex-sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .katex-sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .katex-sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .katex-sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .katex-sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .katex-sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .katex-sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .katex-sizing.reset-size5.size1{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .katex-sizing.reset-size5.size2{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .katex-sizing.reset-size5.size3{font-size:.7777777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .katex-sizing.reset-size5.size4{font-size:.8888888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .katex-sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .katex-sizing.reset-size5.size6{font-size:1.1111111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .katex-sizing.reset-size5.size7{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .katex-sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .katex-sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .katex-sizing.reset-size5.size10{font-size:2.3044444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .katex-sizing.reset-size5.size11{font-size:2.7644444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .katex-sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .katex-sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .katex-sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .katex-sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .katex-sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .katex-sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .katex-sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .katex-sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .katex-sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .katex-sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .katex-sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .katex-sizing.reset-size7.size1{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .katex-sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .katex-sizing.reset-size7.size3{font-size:.5833333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .katex-sizing.reset-size7.size4{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .katex-sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .katex-sizing.reset-size7.size6{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .katex-sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .katex-sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .katex-sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .katex-sizing.reset-size7.size10{font-size:1.7283333333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .katex-sizing.reset-size7.size11{font-size:2.0733333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .katex-sizing.reset-size8.size1{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .katex-sizing.reset-size8.size2{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .katex-sizing.reset-size8.size3{font-size:.4861111111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .katex-sizing.reset-size8.size4{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .katex-sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .katex-sizing.reset-size8.size6{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .katex-sizing.reset-size8.size7{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .katex-sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .katex-sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .katex-sizing.reset-size8.size10{font-size:1.4402777778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .katex-sizing.reset-size8.size11{font-size:1.7277777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .katex-sizing.reset-size9.size1{font-size:.2893518519em}.katex .fontsize-ensurer.reset-size9.size2,.katex .katex-sizing.reset-size9.size2{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .katex-sizing.reset-size9.size3{font-size:.4050925926em}.katex .fontsize-ensurer.reset-size9.size4,.katex .katex-sizing.reset-size9.size4{font-size:.462962963em}.katex .fontsize-ensurer.reset-size9.size5,.katex .katex-sizing.reset-size9.size5{font-size:.5208333333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .katex-sizing.reset-size9.size6{font-size:.5787037037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .katex-sizing.reset-size9.size7{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .katex-sizing.reset-size9.size8{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .katex-sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .katex-sizing.reset-size9.size10{font-size:1.2002314815em}.katex .fontsize-ensurer.reset-size9.size11,.katex .katex-sizing.reset-size9.size11{font-size:1.4398148148em}.katex .fontsize-ensurer.reset-size10.size1,.katex .katex-sizing.reset-size10.size1{font-size:.2410800386em}.katex .fontsize-ensurer.reset-size10.size2,.katex .katex-sizing.reset-size10.size2{font-size:.2892960463em}.katex .fontsize-ensurer.reset-size10.size3,.katex .katex-sizing.reset-size10.size3{font-size:.337512054em}.katex .fontsize-ensurer.reset-size10.size4,.katex .katex-sizing.reset-size10.size4{font-size:.3857280617em}.katex .fontsize-ensurer.reset-size10.size5,.katex .katex-sizing.reset-size10.size5{font-size:.4339440694em}.katex .fontsize-ensurer.reset-size10.size6,.katex .katex-sizing.reset-size10.size6{font-size:.4821600771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .katex-sizing.reset-size10.size7{font-size:.5785920926em}.katex .fontsize-ensurer.reset-size10.size8,.katex .katex-sizing.reset-size10.size8{font-size:.6943105111em}.katex .fontsize-ensurer.reset-size10.size9,.katex .katex-sizing.reset-size10.size9{font-size:.8331726133em}.katex .fontsize-ensurer.reset-size10.size10,.katex .katex-sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .katex-sizing.reset-size10.size11{font-size:1.1996142719em}.katex .fontsize-ensurer.reset-size11.size1,.katex .katex-sizing.reset-size11.size1{font-size:.2009646302em}.katex .fontsize-ensurer.reset-size11.size2,.katex .katex-sizing.reset-size11.size2{font-size:.2411575563em}.katex .fontsize-ensurer.reset-size11.size3,.katex .katex-sizing.reset-size11.size3{font-size:.2813504823em}.katex .fontsize-ensurer.reset-size11.size4,.katex .katex-sizing.reset-size11.size4{font-size:.3215434084em}.katex .fontsize-ensurer.reset-size11.size5,.katex .katex-sizing.reset-size11.size5{font-size:.3617363344em}.katex .fontsize-ensurer.reset-size11.size6,.katex .katex-sizing.reset-size11.size6{font-size:.4019292605em}.katex .fontsize-ensurer.reset-size11.size7,.katex .katex-sizing.reset-size11.size7{font-size:.4823151125em}.katex .fontsize-ensurer.reset-size11.size8,.katex .katex-sizing.reset-size11.size8{font-size:.578778135em}.katex .fontsize-ensurer.reset-size11.size9,.katex .katex-sizing.reset-size11.size9{font-size:.6945337621em}.katex .fontsize-ensurer.reset-size11.size10,.katex .katex-sizing.reset-size11.size10{font-size:.8336012862em}.katex .fontsize-ensurer.reset-size11.size11,.katex .katex-sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .katex-accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .katex-accent .accent-body{position:relative}.katex .katex-accent .accent-body:not(.accent-full){width:0}.katex .katex-overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex svg{fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .katex-stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .katex-stretchy:after,.katex .katex-stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .katex-sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .reflectbox{display:inline-block;transform:scaleX(-1)}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.katex-tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.katex-tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo}
6
+
7
+ `;
package/src/model.ts ADDED
@@ -0,0 +1,57 @@
1
+ export type NodeType = 'literal' | 'variable' | 'operator' | 'function';
2
+
3
+ export interface TermNode {
4
+ id: string;
5
+ type: NodeType;
6
+ op?: string;
7
+ symbol: string;
8
+ label: string;
9
+ raw?: string;
10
+ value?: number;
11
+ isUnary?: boolean;
12
+ isParenthesized?: boolean;
13
+ implicit?: boolean;
14
+ mathJson: any;
15
+ children: TermNode[];
16
+ depth: number;
17
+ x?: number;
18
+ y?: number;
19
+ width?: number;
20
+ height?: number;
21
+ }
22
+
23
+ export interface TreeEdge {
24
+ fromNodeId: string;
25
+ toNodeId: string;
26
+ fromX: number;
27
+ fromY: number;
28
+ toX: number;
29
+ toY: number;
30
+ }
31
+
32
+ export const GERMAN_LABELS: Record<string, string> = {
33
+ Add: 'Summe',
34
+ Subtract: 'Differenz',
35
+ Multiply: 'Produkt',
36
+ Divide: 'Quotient',
37
+ Power: 'Potenz',
38
+ Negate: 'Gegenzahl (Negation)',
39
+ Sqrt: 'Quadratwurzel',
40
+ Sin: 'Sinus',
41
+ Cos: 'Kosinus',
42
+ Tan: 'Tangens',
43
+ Cot: 'Kotangens',
44
+ Ln: 'Natürlicher Logarithmus',
45
+ Log: 'Logarithmus',
46
+ Abs: 'Betrag',
47
+ Exp: 'Exponentialfunktion',
48
+ };
49
+
50
+ export const OPERATOR_SYMBOLS: Record<string, string> = {
51
+ Add: '+',
52
+ Subtract: '−',
53
+ Multiply: '·',
54
+ Divide: ':',
55
+ Power: '^',
56
+ Negate: '−',
57
+ };