fizzex 0.1.0 → 0.1.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.
- package/README.md +73 -310
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,42 +1,10 @@
|
|
|
1
1
|
# Fizzex
|
|
2
2
|
|
|
3
|
-
> Canvas-based mathematical expression editor — light
|
|
3
|
+
> Canvas-based mathematical expression editor — light, fast, framework-agnostic.
|
|
4
4
|
|
|
5
|
-
**[Website](https://ibare.github.io/fizzex)**
|
|
5
|
+
**[Website](https://ibare.github.io/fizzex)** · **[GitHub](https://github.com/ibare/fizzex)**
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
**Fizzex** = **Fizz** + **TeX**
|
|
10
|
-
|
|
11
|
-
- **Fizz**: The sound of bubbles rising in sparkling wine
|
|
12
|
-
- **TeX**: The gold standard for mathematical typesetting
|
|
13
|
-
|
|
14
|
-
Like a sparkling Prosecco, Fizzex is:
|
|
15
|
-
- **Light** — no complex setup, ready to use
|
|
16
|
-
- **Easy** — removes the friction of traditional math input
|
|
17
|
-
- **Delightful** — formulas naturally bubble into shape
|
|
18
|
-
|
|
19
|
-
## Features
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
23
|
-
│ Fizzex │
|
|
24
|
-
├─────────────────────────────────────────────────────────────┤
|
|
25
|
-
│ Input │ LaTeX ←→ AST ←→ Editor │
|
|
26
|
-
├─────────────────────────────────────────────────────────────┤
|
|
27
|
-
│ Rendering │ AST → Box Model → Canvas │
|
|
28
|
-
├─────────────────────────────────────────────────────────────┤
|
|
29
|
-
│ Analysis │ AST → Analyzer → Domain/Variable/Viz │
|
|
30
|
-
├─────────────────────────────────────────────────────────────┤
|
|
31
|
-
│ Computation │ Evaluator (scalar/matrix/complex/autodiff) │
|
|
32
|
-
├─────────────────────────────────────────────────────────────┤
|
|
33
|
-
│ Visualization│ Catalog-matched interactive visualizers │
|
|
34
|
-
├─────────────────────────────────────────────────────────────┤
|
|
35
|
-
│ UX │ Autocomplete │ Coefficient slider │ i18n │
|
|
36
|
-
├─────────────────────────────────────────────────────────────┤
|
|
37
|
-
│ Integration │ Headless adapter │ Tiptap │ Plugin system │
|
|
38
|
-
└─────────────────────────────────────────────────────────────┘
|
|
39
|
-
```
|
|
7
|
+
---
|
|
40
8
|
|
|
41
9
|
## Installation
|
|
42
10
|
|
|
@@ -44,24 +12,22 @@ Like a sparkling Prosecco, Fizzex is:
|
|
|
44
12
|
npm install fizzex
|
|
45
13
|
```
|
|
46
14
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
Fizzex provides multiple entry points for different use cases:
|
|
15
|
+
## Entry Points
|
|
50
16
|
|
|
51
|
-
| Import | Purpose | Peer
|
|
52
|
-
|
|
53
|
-
| `fizzex` | Core
|
|
54
|
-
| `fizzex/headless` | Framework-agnostic renderer & editor |
|
|
55
|
-
| `fizzex/react` | React components
|
|
56
|
-
| `fizzex/tiptap` | Tiptap
|
|
17
|
+
| Import | Purpose | Peer dependencies |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `fizzex` | Core — parser, renderer, analyzer, evaluator | – |
|
|
20
|
+
| `fizzex/headless` | Framework-agnostic renderer & editor | – |
|
|
21
|
+
| `fizzex/react` | React components | `react`, `react-dom` |
|
|
22
|
+
| `fizzex/tiptap` | Tiptap extensions | `@tiptap/core` |
|
|
57
23
|
|
|
58
|
-
All peer dependencies are
|
|
24
|
+
All peer dependencies are optional — import only what you need.
|
|
59
25
|
|
|
60
26
|
## Quick Start
|
|
61
27
|
|
|
62
|
-
### Headless
|
|
28
|
+
### Headless rendering (read-only)
|
|
63
29
|
|
|
64
|
-
```
|
|
30
|
+
```ts
|
|
65
31
|
import { DOMRendererView } from 'fizzex/headless';
|
|
66
32
|
|
|
67
33
|
const renderer = new DOMRendererView(container, {
|
|
@@ -71,19 +37,17 @@ const renderer = new DOMRendererView(container, {
|
|
|
71
37
|
renderer.render('\\frac{1}{2} + x^2');
|
|
72
38
|
```
|
|
73
39
|
|
|
74
|
-
### Headless
|
|
40
|
+
### Headless editor (interactive)
|
|
75
41
|
|
|
76
|
-
```
|
|
42
|
+
```ts
|
|
77
43
|
import { DOMEditorView } from 'fizzex/headless';
|
|
78
44
|
|
|
79
|
-
const editor = new DOMEditorView(container, {
|
|
80
|
-
baseFontSize: 20,
|
|
81
|
-
});
|
|
45
|
+
const editor = new DOMEditorView(container, { baseFontSize: 20 });
|
|
82
46
|
editor.setLatex('x^2 + 2x - 3 = 0');
|
|
83
47
|
editor.onChange((latex) => console.log(latex));
|
|
84
48
|
```
|
|
85
49
|
|
|
86
|
-
### React
|
|
50
|
+
### React
|
|
87
51
|
|
|
88
52
|
```tsx
|
|
89
53
|
import { EditorView } from 'fizzex/react';
|
|
@@ -101,9 +65,9 @@ function App() {
|
|
|
101
65
|
}
|
|
102
66
|
```
|
|
103
67
|
|
|
104
|
-
### Tiptap
|
|
68
|
+
### Tiptap
|
|
105
69
|
|
|
106
|
-
```
|
|
70
|
+
```ts
|
|
107
71
|
import { MathInline, MathBlock } from 'fizzex/tiptap';
|
|
108
72
|
|
|
109
73
|
const editor = new Editor({
|
|
@@ -115,31 +79,31 @@ const editor = new Editor({
|
|
|
115
79
|
});
|
|
116
80
|
```
|
|
117
81
|
|
|
118
|
-
### LaTeX
|
|
82
|
+
### LaTeX ↔ AST
|
|
119
83
|
|
|
120
|
-
```
|
|
84
|
+
```ts
|
|
121
85
|
import { parseLatex, astToLatex } from 'fizzex';
|
|
122
86
|
|
|
123
|
-
const ast = parseLatex('\\frac{1}{2} + x^2');
|
|
87
|
+
const { ast } = parseLatex('\\frac{1}{2} + x^2');
|
|
124
88
|
const latex = astToLatex(ast);
|
|
125
89
|
```
|
|
126
90
|
|
|
127
|
-
### Expression
|
|
91
|
+
### Expression analysis
|
|
128
92
|
|
|
129
|
-
```
|
|
93
|
+
```ts
|
|
130
94
|
import { parseLatex, analyzeExpression } from 'fizzex';
|
|
131
95
|
|
|
132
|
-
const ast = parseLatex('x^2 + 2x - 3 = 0');
|
|
96
|
+
const { ast } = parseLatex('x^2 + 2x - 3 = 0');
|
|
133
97
|
const analysis = analyzeExpression(ast);
|
|
134
98
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
99
|
+
analysis.primaryDomain; // 'polynomial'
|
|
100
|
+
analysis.polynomial?.degree; // 2
|
|
101
|
+
analysis.visualization.graphable2D; // true
|
|
138
102
|
```
|
|
139
103
|
|
|
140
|
-
### Numeric
|
|
104
|
+
### Numeric evaluation
|
|
141
105
|
|
|
142
|
-
```
|
|
106
|
+
```ts
|
|
143
107
|
import {
|
|
144
108
|
parseLatex,
|
|
145
109
|
evaluateSync,
|
|
@@ -148,26 +112,28 @@ import {
|
|
|
148
112
|
differentiateAt,
|
|
149
113
|
} from 'fizzex';
|
|
150
114
|
|
|
151
|
-
// Scalar
|
|
115
|
+
// Scalar
|
|
152
116
|
const { ast } = parseLatex('x^2 + 2x - 3');
|
|
153
|
-
evaluateSync(ast, { x: 2 });
|
|
117
|
+
evaluateSync(ast, { x: 2 }); // 5
|
|
154
118
|
|
|
155
119
|
// Automatic differentiation (forward-mode dual numbers)
|
|
156
|
-
differentiateAt(ast, 'x', { x: 2 });
|
|
120
|
+
differentiateAt(ast, 'x', { x: 2 }); // 6
|
|
157
121
|
|
|
158
|
-
// Complex
|
|
122
|
+
// Complex (Euler's identity). LaTeX commands like `\pi` are normalized
|
|
123
|
+
// to their Unicode form, so the binding key is 'π', not '\pi'.
|
|
159
124
|
const euler = parseLatex('e^{i \\pi}').ast;
|
|
160
|
-
evaluateComplexSync(euler, { e: Math.E, '
|
|
161
|
-
// { re: -1, im: 0 }
|
|
125
|
+
evaluateComplexSync(euler, { e: Math.E, 'π': Math.PI });
|
|
126
|
+
// { re: -1, im: ~0 }
|
|
162
127
|
|
|
163
|
-
// Matrix
|
|
128
|
+
// Matrix
|
|
164
129
|
const m = parseLatex('\\begin{pmatrix} 1 & 2 \\\\ 3 & 4 \\end{pmatrix}').ast;
|
|
165
|
-
evaluateMatrixSync(m, {});
|
|
130
|
+
evaluateMatrixSync(m, {});
|
|
131
|
+
// { rows: 2, cols: 2, data: [[1,2],[3,4]] }
|
|
166
132
|
```
|
|
167
133
|
|
|
168
134
|
### Visualization
|
|
169
135
|
|
|
170
|
-
```
|
|
136
|
+
```ts
|
|
171
137
|
import {
|
|
172
138
|
parseLatex,
|
|
173
139
|
buildSemanticMap,
|
|
@@ -175,28 +141,20 @@ import {
|
|
|
175
141
|
createVisualizer,
|
|
176
142
|
createVisualizerRegistry,
|
|
177
143
|
} from 'fizzex';
|
|
178
|
-
import { ExplorerOverlay } from 'fizzex/headless';
|
|
179
144
|
|
|
180
|
-
// The host
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
//
|
|
145
|
+
// The host hosts the visualizer assets (manifest.json + spec files) as
|
|
146
|
+
// static resources and points `baseUrl` at the directory URL. You can
|
|
147
|
+
// either reuse the bundled catalog shipped at
|
|
148
|
+
// `node_modules/fizzex/dist/visualizers/` (copy/proxy it to your public
|
|
149
|
+
// path) or publish your own catalog.
|
|
185
150
|
const registry = createVisualizerRegistry({
|
|
186
|
-
baseUrl:
|
|
151
|
+
baseUrl: '/visualizers/',
|
|
187
152
|
});
|
|
188
153
|
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const semanticMap = buildSemanticMap(ast);
|
|
192
|
-
const catalogId = semanticMap.get(ast.id)?.catalogId;
|
|
193
|
-
|
|
194
|
-
// Discover every visualizer linked to this formula
|
|
154
|
+
const { ast } = parseLatex('T^2 = \\frac{4\\pi^2}{GM} a^3');
|
|
155
|
+
const catalogId = buildSemanticMap(ast).get(ast.id)?.catalogId;
|
|
195
156
|
const refs = catalogId ? getVisualizersForCatalog(catalogId) : [];
|
|
196
|
-
// refs: [{ id: 'kepler-orbit-2d', name: '지구 궤도 — 2D', ... },
|
|
197
|
-
// { id: 'kepler-orbit-3d', name: '지구 궤도 — 3D', ... }]
|
|
198
157
|
|
|
199
|
-
// Mount on demand — registry fetches the spec JSON and picks the renderer chunk.
|
|
200
158
|
const instance = refs[0]
|
|
201
159
|
? await createVisualizer(container, {
|
|
202
160
|
registry,
|
|
@@ -205,239 +163,44 @@ const instance = refs[0]
|
|
|
205
163
|
height: 400,
|
|
206
164
|
})
|
|
207
165
|
: null;
|
|
208
|
-
|
|
209
|
-
// Or let ExplorerOverlay surface them as toggleable banner buttons
|
|
210
|
-
const overlay = new ExplorerOverlay({ ast, theme: 'light', visualizerRegistry: registry });
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## Plugin Architecture
|
|
214
|
-
|
|
215
|
-
Fizzex uses a three-layer architecture that makes it easy to integrate into any host editor:
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
fizzex (Core)
|
|
219
|
-
│ Parser, renderer, analysis, evaluator — framework-agnostic
|
|
220
|
-
│
|
|
221
|
-
├── fizzex/headless
|
|
222
|
-
│ DOMRendererView (read-only) & DOMEditorView (interactive)
|
|
223
|
-
│ Give it a DOM element — it handles everything
|
|
224
|
-
│
|
|
225
|
-
└── fizzex/tiptap, fizzex/slate, ...
|
|
226
|
-
Thin wrappers (~20 lines) over the headless adapter
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Building Your Own Plugin
|
|
230
|
-
|
|
231
|
-
Any editor that supports custom node rendering can integrate Fizzex:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
// 1. Get a container from your host editor
|
|
235
|
-
const container = nodeView.dom;
|
|
236
|
-
|
|
237
|
-
// 2. Create a renderer
|
|
238
|
-
const renderer = new DOMRendererView(container, { baseFontSize: 20 });
|
|
239
|
-
|
|
240
|
-
// 3. Render when data changes
|
|
241
|
-
renderer.render(node.attrs.latex);
|
|
242
|
-
|
|
243
|
-
// 4. Clean up
|
|
244
|
-
renderer.destroy();
|
|
245
166
|
```
|
|
246
167
|
|
|
247
|
-
|
|
168
|
+
## What's exported
|
|
248
169
|
|
|
249
|
-
|
|
170
|
+
### `fizzex`
|
|
250
171
|
|
|
251
|
-
|
|
172
|
+
- **Parser** — `parseLatex`, `astToLatex`
|
|
173
|
+
- **Editor primitives** — `MathEditor`, `createInitialState`, `createStateFromLatex`, node creators (`createNumber`, `createFrac`, `createIntegral`, `createMatrix`, …)
|
|
174
|
+
- **Analyzer** — `analyzeExpression`, `analyzeBindings`, `analyzeEvaluability`, `buildSemanticMap`
|
|
175
|
+
- **Evaluator** — `evaluateSync` / `evaluate`, `evaluateMatrixSync` / `evaluateMatrix`, `evaluateComplexSync` / `evaluateComplex`, `differentiateAt` / `differentiate`
|
|
176
|
+
- **Visualization** — `createVisualizer`, `createVisualizerRegistry`, `getVisualizersForCatalog`
|
|
177
|
+
- **Types** — `MathNode`, `EditorState`, `ExpressionAnalysis`, `Bindings`, `EvalResult`, `Matrix`, `Complex`, `Dual`, …
|
|
252
178
|
|
|
253
|
-
|
|
254
|
-
// Editor
|
|
255
|
-
import { MathEditor, createInitialState, createStateFromLatex } from 'fizzex';
|
|
256
|
-
|
|
257
|
-
// LaTeX
|
|
258
|
-
import { parseLatex, astToLatex } from 'fizzex';
|
|
259
|
-
|
|
260
|
-
// Analysis & Evaluator
|
|
261
|
-
import { analyzeExpression, analyzeBindings, analyzeEvaluability } from 'fizzex';
|
|
262
|
-
import {
|
|
263
|
-
evaluateSync, evaluate,
|
|
264
|
-
evaluateMatrixSync, evaluateMatrix,
|
|
265
|
-
differentiateAt, differentiate,
|
|
266
|
-
evaluateComplexSync, evaluateComplex,
|
|
267
|
-
} from 'fizzex';
|
|
179
|
+
### `fizzex/headless`
|
|
268
180
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
createVisualizerRegistry,
|
|
273
|
-
getVisualizersForCatalog,
|
|
274
|
-
} from 'fizzex';
|
|
275
|
-
|
|
276
|
-
// Node creators
|
|
277
|
-
import {
|
|
278
|
-
createNumber, createVariable, createOperator,
|
|
279
|
-
createFrac, createPower, createParen, createSubscript,
|
|
280
|
-
createAbs, createSqrt, createFunc,
|
|
281
|
-
createIntegral, createSum, createLimit, createProduct,
|
|
282
|
-
createOverline, createMatrix, createText,
|
|
283
|
-
} from 'fizzex';
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### Headless (`fizzex/headless`)
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
import { DOMRendererView, DOMEditorView } from 'fizzex/headless';
|
|
290
|
-
import type { FizzexConfig, FizzexSize, FizzexChangeHandler } from 'fizzex/headless';
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
### React (`fizzex/react`)
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
import {
|
|
297
|
-
EditorView, StreamView,
|
|
298
|
-
SuggestionChips, SuggestionPopover,
|
|
299
|
-
ExpressionExplorer,
|
|
300
|
-
} from 'fizzex/react';
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Tiptap (`fizzex/tiptap`)
|
|
304
|
-
|
|
305
|
-
```typescript
|
|
306
|
-
import { MathInline, MathBlock } from 'fizzex/tiptap';
|
|
307
|
-
import type { MathInlineOptions, MathBlockOptions } from 'fizzex/tiptap';
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### Types
|
|
311
|
-
|
|
312
|
-
```typescript
|
|
313
|
-
import type {
|
|
314
|
-
// AST
|
|
315
|
-
MathNode, RootNode, NumberNode, VariableNode, OperatorNode,
|
|
316
|
-
FracNode, PowerNode, SubscriptNode, SqrtNode, ParenNode, AbsNode,
|
|
317
|
-
FuncNode, IntegralNode, SumNode, LimitNode, ProductNode,
|
|
318
|
-
OverlineNode, MatrixNode, TextNode,
|
|
319
|
-
// Editor
|
|
320
|
-
EditorState, CursorPosition,
|
|
321
|
-
// Analysis
|
|
322
|
-
ExpressionAnalysis, VariableClassification, VisualizationType,
|
|
323
|
-
// Evaluator
|
|
324
|
-
Bindings, EvalResult, EvalStatus, EvalDetail,
|
|
325
|
-
Matrix, MatrixValue, MatrixResult,
|
|
326
|
-
Dual, DiffResult,
|
|
327
|
-
Complex, ComplexResult,
|
|
328
|
-
BindingAnalysis, EvaluabilityAnalysis,
|
|
329
|
-
// Visualization
|
|
330
|
-
GraphConfig, GraphRange,
|
|
331
|
-
} from 'fizzex';
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
## Architecture
|
|
335
|
-
|
|
336
|
-
```
|
|
337
|
-
src/
|
|
338
|
-
├── types.ts # AST type definitions (MathNode, EditorState)
|
|
339
|
-
├── editor.ts # Editor logic (keyboard input, node creation)
|
|
340
|
-
├── headless/ # Headless adapter layer
|
|
341
|
-
│ ├── renderer.ts # DOMRendererView — read-only rendering
|
|
342
|
-
│ ├── editor-view.ts # DOMEditorView — interactive editor
|
|
343
|
-
│ └── types.ts # FizzexConfig, FizzexSize
|
|
344
|
-
├── integrations/ # Host editor plugins
|
|
345
|
-
│ └── tiptap/ # Tiptap extensions (MathInline, MathBlock)
|
|
346
|
-
├── box/ # Box model (TeX-style layout)
|
|
347
|
-
│ ├── types.ts # Box type definitions
|
|
348
|
-
│ ├── constants.ts # TeX constants
|
|
349
|
-
│ ├── font-metrics.ts # Font metrics (LRU cached)
|
|
350
|
-
│ ├── box-builder.ts # Box creation helpers
|
|
351
|
-
│ ├── box-layout.ts # Layout calculation
|
|
352
|
-
│ ├── projector.ts # Box → Surface projection
|
|
353
|
-
│ ├── surface.ts # Projection target abstraction
|
|
354
|
-
│ └── ast-to-box.ts # AST → Box conversion
|
|
355
|
-
├── latex/ # LaTeX support
|
|
356
|
-
│ ├── latex-parser.ts # LaTeX → AST parser
|
|
357
|
-
│ ├── ast-to-latex.ts # AST → LaTeX conversion
|
|
358
|
-
│ ├── node-factory.ts # Generic node creation factory
|
|
359
|
-
│ ├── command-registry.ts # Command registry (187+ commands)
|
|
360
|
-
│ └── commands/ # Modularized command handlers
|
|
361
|
-
├── suggestion/ # Context-aware autocomplete
|
|
362
|
-
├── analyzer/ # Expression analysis (9 modules)
|
|
363
|
-
├── evaluator/ # Numeric evaluator (scalar/matrix/complex/autodiff)
|
|
364
|
-
├── visualizer/ # Visualization components
|
|
365
|
-
├── fonts/ # New Computer Modern Math font management
|
|
366
|
-
├── i18n/ # Internationalization
|
|
367
|
-
├── export/ # PNG export
|
|
368
|
-
├── utils/ # LRU cache, ID generation, benchmarks
|
|
369
|
-
└── react/ # React components
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
## Development
|
|
373
|
-
|
|
374
|
-
### Requirements
|
|
375
|
-
|
|
376
|
-
- Node.js 20+
|
|
377
|
-
- pnpm 8+
|
|
378
|
-
|
|
379
|
-
### Setup
|
|
380
|
-
|
|
381
|
-
```bash
|
|
382
|
-
pnpm install
|
|
383
|
-
pnpm dev # Type watch mode
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
### Test
|
|
387
|
-
|
|
388
|
-
```bash
|
|
389
|
-
pnpm test # Run all tests
|
|
390
|
-
pnpm test:watch # Watch mode
|
|
391
|
-
pnpm test:coverage # Coverage report
|
|
392
|
-
pnpm test:layout # TeX layout compliance check
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
### Build
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
pnpm build # Full build (tsc + vite)
|
|
399
|
-
pnpm typecheck # Type check only
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### Website
|
|
403
|
-
|
|
404
|
-
```bash
|
|
405
|
-
cd website
|
|
406
|
-
pnpm install
|
|
407
|
-
pnpm dev # Local dev server
|
|
408
|
-
pnpm build # Production build
|
|
409
|
-
```
|
|
181
|
+
- **Renderers** — `DOMRendererView`, `DOMEditorView`, `DOMStreamView`
|
|
182
|
+
- **Explorer** — `ExplorerOverlay`, `ExplorerInlineControls`, `ExplorerSceneChips`, `ExplorerVisualizerController`
|
|
183
|
+
- **Modification utilities** — `cloneAst`, `createModificationState`, `modifyNumberNode`, `resetNode`, `resetAll`, `hasModifications`, `getControlType`, `buildInlineControlConfig`, `buildConfidenceRegions`, `classifyConfidence`
|
|
410
184
|
|
|
411
|
-
|
|
185
|
+
### `fizzex/react`
|
|
412
186
|
|
|
413
|
-
|
|
187
|
+
- `EditorView`, `StreamView`, `SuggestionChips`, `SuggestionPopover`, `ExpressionExplorer`
|
|
414
188
|
|
|
415
|
-
###
|
|
189
|
+
### `fizzex/tiptap`
|
|
416
190
|
|
|
417
|
-
-
|
|
418
|
-
- [ ] **Super/subscript gap condition** (TeX Rule 18e) — When both super and subscript are present, enforce minimum gap of 4*xi8 between them, and ensure superscript bottom >= 4/5 * xHeight. Requires combined detection of simultaneous super/subscript in parser or layout.
|
|
191
|
+
- `MathInline`, `MathBlock`
|
|
419
192
|
|
|
420
|
-
|
|
193
|
+
## Compatibility
|
|
421
194
|
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
-
|
|
425
|
-
- [ ] **`\left\|`…`\right\|` double vertical bar delimiter** — Recognize `\|` as a delimiter after `\left`/`\right` and render ‖ (double vertical bar) that stretches to match content height. Requires extending `leftHandler` delimiter parsing + adding ‖ extensible data to delimiter-paths.
|
|
426
|
-
- [ ] **Fixed-size delimiters** (`\big`, `\Big`, `\bigg`, `\Bigg`) — Four fixed-size delimiter commands. Requires scale factor definitions per size, a new CommandHandler to parse the next token as a delimiter, and Box rendering logic for sized delimiters.
|
|
427
|
-
- [ ] **Wide accent rendering** (`\widetilde`, `\widehat`) — Currently rendered as a single glyph (˜, ˆ) placed over only the first character. Needs extensible accent rendering that stretches to cover the full content width, using OpenType MATH table MathGlyphVariantRecord or rule-based dynamic drawing.
|
|
428
|
-
- [ ] **Overbrace/Underbrace** (`\overbrace{...}^{...}`, `\underbrace{...}_{...}`) — Draws an extensible brace above/below content with annotation text above/below the brace. Requires a new AST node type + extensible brace rendering + annotation layout.
|
|
429
|
-
- [ ] **Extensible over-arrow** (`\overleftarrow`, `\overrightarrow`, `\overleftrightarrow`) — Arrows placed above content that stretch to match content width. Currently `\overrightarrow` maps to a single `\vec` glyph covering only the first character. Requires rule + arrowhead extensible rendering.
|
|
430
|
-
- [ ] **Stackrel/Overset/Underset** (`\stackrel`, `\overset`, `\underset`) — Structure commands that place text above/below a symbol. Requires a new AST node type + VBox-based layout + reduced font size rendering.
|
|
431
|
-
- [ ] **Boxed** (`\boxed`) — Draws a rectangular border around an expression. Requires stroke rectangle rendering on Box output. Can be implemented as a new AST node type or an accent variant.
|
|
432
|
-
- [ ] **Cancel family** (`\cancel`, `\bcancel`, `\xcancel`) — Draws diagonal lines or X marks over an expression. Requires a new AST node type + Canvas path-based diagonal rendering. Originates from the `cancel` package.
|
|
433
|
-
- [ ] **Simultaneous super/subscript alignment** (`x^a_b`) — Optimize vertical alignment when both superscript and subscript are present. Currently processed independently, resulting in different spacing compared to KaTeX/MathJax. Requires unifying super/subscripts into a single SupersubNode structure. See also "Super/subscript gap condition" in Layout Engine TODO.
|
|
195
|
+
- Node.js **20+**
|
|
196
|
+
- React **19+** (for `fizzex/react`)
|
|
197
|
+
- Modern browsers with Canvas 2D and ES2020 support
|
|
434
198
|
|
|
435
|
-
##
|
|
199
|
+
## Links
|
|
436
200
|
|
|
437
|
-
-
|
|
438
|
-
-
|
|
439
|
-
-
|
|
440
|
-
- Edge 90+
|
|
201
|
+
- [Website & live demos](https://ibare.github.io/fizzex)
|
|
202
|
+
- [Plugin guide](https://ibare.github.io/fizzex/en/plugins) — integrate Fizzex into any host editor
|
|
203
|
+
- [GitHub](https://github.com/ibare/fizzex) — issues, roadmap, contributing
|
|
441
204
|
|
|
442
205
|
## License
|
|
443
206
|
|