@barocss/math-editor 0.4.0 → 0.6.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/API-SESSION.md +35 -1
- package/API-WEB-COMPONENT.md +2 -0
- package/CHANGELOG.md +109 -0
- package/CLIPBOARD.md +54 -0
- package/EDITING-SCENARIOS.md +209 -0
- package/GETTING-STARTED.md +54 -0
- package/IMPLEMENTATION.md +105 -0
- package/KEYBOARD.md +41 -0
- package/LATEX-GUIDE.md +52 -2
- package/LATEX-MODEL.md +12 -0
- package/LATEX-SCOPE.md +10 -1
- package/README.md +119 -23
- package/RELEASING.md +95 -10
- package/RENDERING-TESTS.md +79 -0
- package/ROADMAP.md +238 -6
- package/STYLING.md +28 -1
- package/TEXT-EDITORS.md +157 -0
- package/VALIDATION.md +433 -0
- package/dist/context-tools.d.ts +21 -0
- package/dist/context-tools.js +37 -0
- package/dist/dom/caret-geometry.js +1 -1
- package/dist/dom/context-keyboard.d.ts +2 -0
- package/dist/dom/context-keyboard.js +22 -0
- package/dist/dom/help.d.ts +5 -0
- package/dist/dom/help.js +104 -0
- package/dist/dom/menu-position.d.ts +3 -0
- package/dist/dom/menu-position.js +49 -4
- package/dist/dom/readable-layout.d.ts +3 -0
- package/dist/dom/readable-layout.js +52 -0
- package/dist/dom/toolbar-catalog.d.ts +1 -1
- package/dist/dom/toolbar.d.ts +2 -0
- package/dist/dom/toolbar.js +8 -1
- package/dist/dom.d.ts +13 -1
- package/dist/dom.js +323 -51
- package/dist/enter-policy.js +1 -1
- package/dist/latex.js +11 -0
- package/dist/lines.d.ts +2 -0
- package/dist/lines.js +15 -0
- package/dist/locales/en.js +33 -3
- package/dist/locales/en.json +33 -3
- package/dist/locales/ko.js +33 -3
- package/dist/locales/ko.json +33 -3
- package/dist/math-editor-toolbar.js +2 -1
- package/dist/math-editor.d.ts +4 -1
- package/dist/math-editor.js +506 -296
- package/dist/math-layout.d.ts +12 -0
- package/dist/math-layout.js +59 -0
- package/dist/math-spacing.d.ts +13 -0
- package/dist/math-spacing.js +87 -0
- package/dist/model.d.ts +6 -0
- package/dist/model.js +72 -5
- package/dist/range.d.ts +10 -2
- package/dist/range.js +31 -6
- package/dist/root-transform.d.ts +19 -0
- package/dist/root-transform.js +69 -0
- package/dist/selection-shortcuts.d.ts +13 -0
- package/dist/selection-shortcuts.js +35 -0
- package/dist/session.d.ts +1 -0
- package/dist/session.js +1 -1
- package/dist/suggestions.d.ts +9 -0
- package/dist/suggestions.js +53 -0
- package/dist/symbols.d.ts +1 -1
- package/dist/symbols.js +1 -0
- package/dist/vertical-navigation.d.ts +5 -0
- package/dist/vertical-navigation.js +33 -0
- package/dist/web-component.js +9 -1
- package/package.json +11 -3
- package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/src/fonts/README.md +18 -0
- package/src/shapes/README.md +21 -0
- package/src/shapes/parenthesis-bottom.svg +1 -0
- package/src/shapes/parenthesis-top.svg +1 -0
- package/src/shapes/parenthesis.svg +1 -0
- package/src/shapes/radical.svg +1 -0
- package/src/style.css +882 -61
package/API-SESSION.md
CHANGED
|
@@ -135,7 +135,9 @@ Inline mode means one top-level row, not a fixed visual height. It rejects newli
|
|
|
135
135
|
For a compact draft, pass `menuAvoidElements: () => [actionsElement]` to keep
|
|
136
136
|
suggestions clear of Apply, Cancel and tool-expansion controls. The callback can
|
|
137
137
|
return elements added after mounting. Placement remains constrained by the
|
|
138
|
-
viewport and clipping ancestors;
|
|
138
|
+
viewport and actual CSS clipping ancestors; a dialog role alone does not limit
|
|
139
|
+
the menu to the dialog height. Fixed menus can extend beyond a compact dialog
|
|
140
|
+
while remaining its DOM descendants. The menu scrolls when the available gap is short.
|
|
139
141
|
This option changes presentation only and adds no model data.
|
|
140
142
|
|
|
141
143
|
## Saving without caret-only writes
|
|
@@ -323,3 +325,35 @@ Choose the change appropriate to the target:
|
|
|
323
325
|
`default` removes the explicit metadata. `setMathPresentation(state, id, change)` is the pure equivalent. Unsupported changes or stale IDs return the original state; the session command returns false. This is presentation editing of existing syntax, not algebraic conversion or general TeX styling.
|
|
324
326
|
|
|
325
327
|
Toolbars expose `closePanels()` to dismiss their nonmodal utilities without editing the formula. `onOpenPanel` and `onPasteLatex` are optional mounting callbacks for a host that coordinates its own utility panels. Built-in surfaces keep only one utility/discovery panel open at a time.
|
|
328
|
+
|
|
329
|
+
### Keyboard access to transformations
|
|
330
|
+
|
|
331
|
+
In React and native DOM fields, **Alt+Down** opens or reopens suggestions and
|
|
332
|
+
selects the first available contextual transformation. Up/Down browses and Enter
|
|
333
|
+
applies; Escape dismisses. On macOS, Alt is the Option key. Root and bracket
|
|
334
|
+
transformations preserve the existing operand. The shortcut works with
|
|
335
|
+
`toolbar: false` and `contextTools: false`, including inline mode. Normal text
|
|
336
|
+
input continues to use the standard suggestion ordering; a context-only menu
|
|
337
|
+
requires navigation before Enter can apply a change instead of a host commit.
|
|
338
|
+
|
|
339
|
+
### Low-level boundary and vertical navigation helpers
|
|
340
|
+
|
|
341
|
+
The core exports `unwrapNext(state)` and `joinNextLine(state)` as immutable state operations, symmetric to `unwrapPrevious` and `joinPreviousLine`. Unsupported positions return the original state. Apply a changed state through a session/history transaction; these helpers do not commit it themselves.
|
|
342
|
+
|
|
343
|
+
`moveVertical(state, direction, geometry)` remains stateless. A custom editing surface can use `createVerticalNavigation()` for repeated vertical movement: call `move(state, direction, geometry)` and apply the returned caret. Call `reset()` after horizontal navigation, text/model changes or pointer placement. Keep this helper local to one view; never serialize its preferred column with the formula.
|
|
344
|
+
|
|
345
|
+
### Keyboard help and separate toolbars
|
|
346
|
+
|
|
347
|
+
F1 opens localized keyboard/clipboard help in a focused React or native field. The native `DOMMathEditor.showHelp()` method and rich React `MathEditorHandle.showHelp()` method open the same help for a custom host button. Closing restores the previous input selection; opening help does not add a document/history entry.
|
|
348
|
+
|
|
349
|
+
A toolbar mounted separately from its field must identify the owner explicitly:
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
const field = mountMathEditor(fieldHost, { session, toolbar: false });
|
|
353
|
+
const toolbar = mountMathToolbar(toolbarHost, session, {
|
|
354
|
+
onExecute: () => field.focus(),
|
|
355
|
+
onHelp: () => field.showHelp(),
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Built-in toolbars connect automatically. A separate toolbar without `onHelp` omits its help button instead of guessing which field to target. F1 still works in the field. Destroy the field to remove any open help. The help UI does not read the OS clipboard. Key remapping is not part of this API.
|
package/API-WEB-COMPONENT.md
CHANGED
|
@@ -126,3 +126,5 @@ Persist the `MathDocument` passed to `onChange`; LaTeX is derived output and is
|
|
|
126
126
|
Keep the mount host empty. The editor owns its descendants; framework rendering into the same host can destroy caret and composition state. Use one editing surface per session. Destroy the renderer on teardown; a session supplied by the host remains the host's responsibility.
|
|
127
127
|
|
|
128
128
|
See [session and DOM API](API-SESSION.md) for exact options, commands, events and cleanup, and [renderer differences](ADAPTERS.md#current-renderer-parity) before choosing a native wrapper over the rich React editor.
|
|
129
|
+
|
|
130
|
+
Set `context-tools="false"` to hide the contextual structure footer. Changing this attribute updates the mounted editor. Conversion suggestions remain available.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,114 @@
|
|
|
1
1
|
# @barocss/math-editor
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Keep fraction terms at their resolved TeX size inside norms, absolute values,
|
|
8
|
+
parentheses and roots. Use the same font size for passive glyphs, active inputs
|
|
9
|
+
and measurement spans, including nested fractions and explicit fraction styles.
|
|
10
|
+
- Remove extra inline line-box descent from fence bodies so nested parentheses,
|
|
11
|
+
brackets and norms keep their contents aligned during display and editing.
|
|
12
|
+
Preserve fence height for fractions and other tall bodies.
|
|
13
|
+
- Size radical glyphs from the containing mathematical style and editing minimum.
|
|
14
|
+
Remove anonymous line-box descent and inactive boundary height from radicands,
|
|
15
|
+
so roots in exponents stay smaller than the base while tall contents still fit.
|
|
16
|
+
- Keep nested editing glyphs and inputs at a readable 14px minimum. Expose
|
|
17
|
+
`--me-min-font-size` for host configuration, with 0px preserving TeX size ratios.
|
|
18
|
+
Reserve line space for elevated scripts in React and native DOM editors so
|
|
19
|
+
larger nested math remains inside the editing surface without changing LaTeX.
|
|
20
|
+
- Add Ctrl+Left/Right (Option on macOS) to move by lexical units and whole math
|
|
21
|
+
structures. Add Shift to extend or shrink a selection. Apply the same behavior
|
|
22
|
+
in React and native DOM editors without changing document history. Move matrix
|
|
23
|
+
column deletion to Alt+Shift+Backspace to avoid a selection shortcut conflict.
|
|
24
|
+
|
|
25
|
+
## 0.6.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- Complete forward structural deletion and next-line joining, preserving retained content and one-step Undo. Keep the preferred horizontal caret position across vertical movement in React and native DOM. Reject malformed structured clipboard data without falling back to destructive plain-text insertion, and reject multiline paste in React single-line fields. Share Enter policy so Shift+Enter bypasses suggestions and follows row/newline rules.
|
|
30
|
+
|
|
31
|
+
Add catalog-wide populated/empty deletion scenarios, structured and matrix clipboard checks, vertical/line editing, keyboard transformations, framework lifecycle and option updates, and extended host persistence/read-only scenarios. Provide a repository-owned browser runner and CI workflow alongside existing KaTeX comparisons.
|
|
32
|
+
|
|
33
|
+
Constrain inline surfaces to their host width so long formulas remain horizontally scrollable.
|
|
34
|
+
|
|
35
|
+
- Wrap selected math immediately with opening parentheses, brackets, braces, absolute-value bars, fraction slash, superscript and subscript keys. Preserve the selected content and move to the denominator or script slot for continued input. Share the behavior across React and native DOM fields, including inline adapters, and retain existing literal-text and unselected-input behavior.
|
|
36
|
+
|
|
37
|
+
Add keyboard, native-selection and drag regression scenarios with Undo/Redo checks, plus block and inline KaTeX rendering comparisons for the resulting notation.
|
|
38
|
+
|
|
39
|
+
Correct inline fraction term sizes and compact fraction row spacing to match their resolved mathematical style. Keep active inputs and passive glyphs aligned.
|
|
40
|
+
|
|
41
|
+
- Add localized keyboard and clipboard help in React and native DOM fields, available from the toolbar or F1 in a focused field. Preserve the formula and restore focus when help closes. Include beginner, clipboard and keyboard guides, and link to independent, model-checked practice exercises on the demo site.
|
|
42
|
+
|
|
43
|
+
Expose `showHelp()` on DOM and React handles and `onHelp` for an independently mounted toolbar, so help targets an explicit field. Restore native selection as well as focus after help closes.
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- Center the keyboard-selected suggestion within the available list space in React, DOM and text-source editors. Clamp scrolling at list boundaries, account for sticky source hints, and scroll only the suggestion list so the host document stays in place.
|
|
48
|
+
- Read the native input selection before processing keydown in React and DOM editors. Held arrow keys now cross token and structure boundaries without waiting for keyup or a delayed selection event. Add repeated-keydown browser coverage for both directions, fraction slots, Shift selection, continued typing and Undo.
|
|
49
|
+
- Allow fixed suggestion menus to use viewport space outside compact dialogs. Constrain menus by actual CSS clipping boundaries, not dialog semantics, while retaining host action-control avoidance.
|
|
50
|
+
|
|
51
|
+
## 0.5.0
|
|
52
|
+
|
|
53
|
+
### Minor Changes
|
|
54
|
+
|
|
55
|
+
- Show query-independent radical tools below the active editing surface. Include conversion, index editing, disabled explanations, F6/Escape focus navigation, en/ko labels and a contextTools opt-out (context-tools for Web Components). Preserve model history and hide stale context during range selection or blur.
|
|
56
|
+
- Add contextual bracket transformations to suggestions, with Alt+Down discovery and keyboard acceptance in inline fields without toolbar or footer. Preserve contents, caret and history; target the nearest root/fence and reject stale actions. Include optional footer bracket controls and localized keyboard guidance.
|
|
57
|
+
- Add contextual suggestions to convert a square root to an indexed root while preserving the radicand. Select the new index `2` for immediate editing. Allow conversion back to a square root only for an empty index or `2`. Include English/Korean labels and shared behavior in React and native DOM integrations.
|
|
58
|
+
|
|
59
|
+
### Patch Changes
|
|
60
|
+
|
|
61
|
+
- Resolve operator presentation from mathematical slot context in React and native
|
|
62
|
+
DOM editors. Use text/script-size glyphs and side limits inside fractions and
|
|
63
|
+
scripts, preserve explicit limit placement, and apply smaller nested bounds.
|
|
64
|
+
Add context-resolution unit tests and KaTeX glyph-width/font/position checks.
|
|
65
|
+
- Align named-function and fraction boundaries with mathematical spacing in React
|
|
66
|
+
and native DOM. Remove repeated function glyph padding and fixed fraction outer
|
|
67
|
+
margins. Preserve thin function spacing in script styles and omit it before plain
|
|
68
|
+
opening parentheses.
|
|
69
|
+
- Use bundled KaTeX math faces for variables, upright symbols and display operators. Remove artificial integral skew, scale delimiter widths, and preserve curved over/underbrace ends with licensed KaTeX SVG slices. Refine radical sizing, root-index placement, matrix columns and integral limit spacing in both editable and passive views.
|
|
70
|
+
|
|
71
|
+
Extend the source-only geometry audit with opt-in horizontal-position checks, font asset fingerprints, explicit font loading and multiple-integral/long-brace cases. Retain the KaTeX MIT attribution for bundled assets.
|
|
72
|
+
|
|
73
|
+
- Use shared mathematical spacing for text runs in React and native DOM. Distinguish
|
|
74
|
+
unary signs from binary operators, space relations and punctuation, and suppress
|
|
75
|
+
these gaps inside scripts. Remove excess glyph padding and reduce inactive caret
|
|
76
|
+
boundary width while preserving empty input targets.
|
|
77
|
+
- Use small operator glyphs and side limits in inline mode. Reduce nested script
|
|
78
|
+
size, adjust radicals inside superscripts, and preserve curved end caps on very
|
|
79
|
+
tall parentheses. Extend source-only KaTeX comparisons to large fences, deep
|
|
80
|
+
nesting, and actual inline mode.
|
|
81
|
+
- Fix KaTeX-compatible export and import for literal caret and tilde characters in
|
|
82
|
+
math text runs. Protect complex root-index arguments without changing JSON
|
|
83
|
+
structure. Add clearance between nested radical rules and extend rendering
|
|
84
|
+
regression checks.
|
|
85
|
+
- Use KaTeX-derived SVG contours for radicals and short/tall parentheses. Keep
|
|
86
|
+
existing editing boxes while improving tapered strokes and curved ends. Include
|
|
87
|
+
the outline assets and attribution in the package, and extend visual comparison
|
|
88
|
+
fixtures to simple roots and short parentheses.
|
|
89
|
+
- Correct the size, height and spacing of fraction terms used as scripts. Add editor/KaTeX geometry and screenshot fixtures for fractional powers and subscripts. Allow Delete and Backspace inside empty non-grid slots to remove their wrapper while retaining other content and Undo support.
|
|
90
|
+
- Match ordinary script and root-index font scales more closely to KaTeX in passive and active editing. Add a source-only rendering audit with per-formula measurements, screenshots and a tracked difference ledger.
|
|
91
|
+
- Keep formula selections intact when Up/Down navigates a visible wrapping suggestion menu. Enter applies the highlighted wrapper to the selected content. Left/Right still restores the caret, and Shift+arrows extends the selection. Apply the same behavior to React and native DOM fields used by host integrations.
|
|
92
|
+
- Align nested fraction terms, matrix rows, annotations and operator limits more closely with KaTeX. Scale large and contour integral geometry with the configured font size. Preserve explicit display-fraction sizes and positions inside scripts. Use matching input and passive-text metrics to retain edit positions.
|
|
93
|
+
|
|
94
|
+
Expand the source-only geometry audit to 33 formulas, including two font sizes, React and DOM rendering, active typing checks and a local image comparison gallery.
|
|
95
|
+
|
|
96
|
+
## 0.4.1
|
|
97
|
+
|
|
98
|
+
### Patch Changes
|
|
99
|
+
|
|
100
|
+
- Move each host implementation, tests and host-specific styles into its own plugin
|
|
101
|
+
package. Keep only shared data, draft-field UI and messages in the private common
|
|
102
|
+
package. Preserve the public entry points and stored formula format.
|
|
103
|
+
|
|
104
|
+
Declare ProseMirror as Tiptap's public dependency instead of bundling a second
|
|
105
|
+
copy of its host implementation. Keep host SDKs and the math core external, and
|
|
106
|
+
include common helpers and declarations within each published artifact.
|
|
107
|
+
|
|
108
|
+
Resolve workspace imports from source without a prior build. Use publishConfig
|
|
109
|
+
entry-point overrides for the core and all public plugins, and verify staged npm
|
|
110
|
+
artifacts against their generated runtime and declaration paths.
|
|
111
|
+
|
|
3
112
|
## 0.4.0
|
|
4
113
|
|
|
5
114
|
### Minor Changes
|
package/CLIPBOARD.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Copy and paste formulas
|
|
2
|
+
|
|
3
|
+
Choose the method that matches your source. **Ordinary paste does not automatically parse LaTeX.**
|
|
4
|
+
|
|
5
|
+
| Source and goal | Method | Result |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| Selected math → another math-editor field | Select a model range, copy, then paste at the destination | Editable structure is preserved when the browser retains the custom clipboard format |
|
|
8
|
+
| Ordinary text → a formula slot | Paste normally | Literal text insertion; suggestions can help with subsequent editing |
|
|
9
|
+
| LaTeX source → an editable formula | Open **Paste as LaTeX** with `Alt+Shift+V`, paste the source, then `Ctrl/Cmd+Enter` | Supported syntax becomes editable nodes at the caret or replaces the selected range |
|
|
10
|
+
| Formula → a LaTeX-aware application | Copy a formula range, or use the site's LaTeX Copy button | Plain clipboard text is LaTeX; the receiving application decides how to use it |
|
|
11
|
+
| Formula → a slide, document or image tool | Use **Copy image** or **Download image** in the site's rendering preview | PNG pixels; this is not an editable math model |
|
|
12
|
+
|
|
13
|
+
On macOS, use Cmd for copy/cut/paste and Option for Alt. The editor does not read the system clipboard just because you open the paste panel.
|
|
14
|
+
|
|
15
|
+
## Move part of a formula
|
|
16
|
+
|
|
17
|
+
1. Drag across the math, or extend a range with Shift+Left/Right.
|
|
18
|
+
2. Press Ctrl/Cmd+C to copy. Use Ctrl/Cmd+X to cut.
|
|
19
|
+
3. Click the destination. Place the caret where the formula should go, or select content to replace.
|
|
20
|
+
4. Press Ctrl/Cmd+V. Check the result. Undo restores the previous content.
|
|
21
|
+
|
|
22
|
+
Selection inside one input can be a native text selection. A model range can include multiple tokens and nested structures. To copy the whole formula, focus the formula surface and use Select All; Select All inside an active input can select that input's text first. Check the highlight before copying.
|
|
23
|
+
|
|
24
|
+
Copying leaves the original unchanged. Cut and accepted structured paste are undoable. Pasted nodes receive fresh identities so editing one copy does not change the other.
|
|
25
|
+
|
|
26
|
+
## Insert LaTeX without replacing the whole formula
|
|
27
|
+
|
|
28
|
+
Place the caret after your existing expression. Open Paste as LaTeX and enter:
|
|
29
|
+
|
|
30
|
+
```latex
|
|
31
|
+
+\frac{a}{b}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Press Ctrl/Cmd+Enter to insert. Escape closes the panel. If the source is unsupported or malformed, the panel shows a diagnostic and keeps the existing formula unchanged. Correct the source or close the panel.
|
|
35
|
+
|
|
36
|
+
The site's **Load LaTeX** control replaces the whole formula. **Paste as LaTeX** inserts at the current location. See [LaTeX support](LATEX-SCOPE.md) for parsing limits.
|
|
37
|
+
|
|
38
|
+
## Matrices and multiline formulas
|
|
39
|
+
|
|
40
|
+
A selected rectangle of matrix cells carries row and column boundaries. Paste into a compatible matrix destination to replace that rectangle or grow from the target cell where supported. Tab-separated rectangular text can also supply matrix cells when the caret is in a matrix. Ragged, oversized or incompatible cell data is rejected.
|
|
41
|
+
|
|
42
|
+
Inline fields reject top-level multiline fragments. A multiline fragment also cannot be inserted inside an ordinary nested slot such as a fraction numerator. Matrix rows are internal structure; they are different from top-level formula lines.
|
|
43
|
+
|
|
44
|
+
## When pasting does not produce editable math
|
|
45
|
+
|
|
46
|
+
- Another application or browser can discard custom clipboard formats. If only plain LaTeX remains, use Paste as LaTeX explicitly.
|
|
47
|
+
- Malformed custom formula data is rejected. It does not silently fall back to replacing your selection with plain text.
|
|
48
|
+
- An image contains no editable model. This library does not perform formula OCR.
|
|
49
|
+
- Clipboard permissions can prevent image copying. Use Download image as the site alternative.
|
|
50
|
+
- A host editor can handle clipboard operations outside the active math field. Put the caret inside the math field before pasting there.
|
|
51
|
+
|
|
52
|
+
Controlled browser clipboard tests pass for the recorded scope. Actual exchange through the OS clipboard, other applications and all browsers is not yet certified. See [validation](VALIDATION.md).
|
|
53
|
+
|
|
54
|
+
Try [the practice exercises](https://math-editor.barocss.com/#tutorial) or open [the keyboard reference](KEYBOARD.md).
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Editing scenarios
|
|
2
|
+
|
|
3
|
+
## Current milestone evidence — 2026-09-13
|
|
4
|
+
|
|
5
|
+
The supported-notation milestone passed **113 cases / 4,311 checkpoints** on the current candidate. Use [validation](VALIDATION.md) for exact reports and scope. Run all required suites through `node scripts/check-math-editor.mjs` with both demo servers running.
|
|
6
|
+
|
|
7
|
+
| Scenarios | Required executable coverage in this milestone |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| EDIT-006 / 015 | `deletion`: all 55 structure kinds at populated boundaries; applicable empty slots; grid preservation and exact history |
|
|
10
|
+
| EDIT-007 / 015 | `clipboard`: nested ranges, cross-instance transfer, cell rectangles, rejected malformed/multiline payloads |
|
|
11
|
+
| EDIT-013 / 016 / 034 | `vertical`, `lines`, `arrows`: preferred column, row/line changes, held keys and continued input |
|
|
12
|
+
| EDIT-003–005 / 029 / 033 | `transformations`, `shortcuts`, `continuous`: range selection, keyboard wrapping, nearest radical/fence targeting and history |
|
|
13
|
+
| EDIT-009–011 / 019 | `continuous`: all nine host demos; Apply/Cancel, save/reload/reopen, read-only, inline exit and prose continuation |
|
|
14
|
+
| EDIT-017 / 018 | `narrow`, `frameworks`, `bindings`, rendering audit: width constraints, locale/options, independent instances, cleanup and KaTeX agreement |
|
|
15
|
+
|
|
16
|
+
This table records the bounded milestone. The full register below also includes wider variations, optional tools and platform checks; a suite pass does not certify every variation of a numbered scenario. Real OS clipboard/IME remains manual. Existing historical mappings are retained where a narrower suite does not replace them.
|
|
17
|
+
|
|
18
|
+
Use this document to manage editing behavior. [Supported features](SUPPORT.md)
|
|
19
|
+
lists notation; this register describes what a person does with that notation.
|
|
20
|
+
[Validation](VALIDATION.md) stores dated execution evidence. Neither the number
|
|
21
|
+
of features nor the number of unit tests proves that an editing flow works.
|
|
22
|
+
|
|
23
|
+
## Status and ownership
|
|
24
|
+
|
|
25
|
+
Keep each scenario ID stable. Add the ID to the browser fixture that exercises
|
|
26
|
+
it and to a bug report when that flow fails. The person changing the behavior
|
|
27
|
+
updates its expected result, test mapping and execution record in the same change.
|
|
28
|
+
The release owner reviews unresolved cases before publishing.
|
|
29
|
+
|
|
30
|
+
| Status | Meaning |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Recorded | A dated run is recorded for the stated scope. This is not a pass for every adapter or a future build. |
|
|
33
|
+
| Rerun | Related browser checks exist, but this register does not certify the full scenario on the current source. |
|
|
34
|
+
| Extend | Some assertions exist; additional browser steps or checks are required. |
|
|
35
|
+
| Manual | Requires a person or device. No automated pass is claimed. |
|
|
36
|
+
|
|
37
|
+
P0 covers loss of content, blocked input, invalid output and host persistence.
|
|
38
|
+
P1 covers discoverability, navigation and presentation. P2 covers additional
|
|
39
|
+
platform coverage. A known P0 failure blocks release for the affected scope.
|
|
40
|
+
An unrun or unsupported case must never be counted as passed.
|
|
41
|
+
|
|
42
|
+
## Scenario register
|
|
43
|
+
|
|
44
|
+
Start each case with a fresh editor unless the steps specify saved content.
|
|
45
|
+
Use actual key presses for typing and actual pointer movement for drag cases.
|
|
46
|
+
`Cmd` applies on macOS; `Ctrl` applies on Windows/Linux. Do not substitute a
|
|
47
|
+
programmatic value assignment for a focus or typing assertion.
|
|
48
|
+
|
|
49
|
+
| ID | Priority / flow | Steps | Required result | Status / test mapping |
|
|
50
|
+
| --- | --- | --- | --- | --- |
|
|
51
|
+
| EDIT-001 | P0 — Continuous input | Enter `4ab+12`, one key at a time. Pause after `4`. Resume while suggestions are visible. Move left, insert `x`, then delete it. | Each key appears once. The input retains focus. Numbers and variables remain in order; no key changes host prose. | Rerun — `quill-typing-check.js`, `typing-check.js`, `token-paste-check.js` |
|
|
52
|
+
| EDIT-002 | P0 — Operand wrapping | Type `4ab`. Choose absolute value for the `ab` operand. Continue typing after the structure. Repeat with parentheses, fraction and root. | `ab` remains inside the chosen structure; `4` remains outside. The cursor reaches the intended slot or following boundary. No operand disappears. | Rerun — `operand-size-check.js`; `suggestions.test.ts` |
|
|
53
|
+
| EDIT-003 | P0 — Selected suggestion | Type `abcd`. Select `cd` with Shift+Left twice. Use Down/Up, choose root, then Enter. Repeat with mouse drag. | The range stays selected while options change. Only `cd` is wrapped. The input receives focus after acceptance. | Rerun — `selection-suggestions-check.js`. Recorded 2026-09-09 for React and nine hosts before radical suggestions were added; rerun after suggestion changes. |
|
|
54
|
+
| EDIT-004 | P0 — Return to a caret | Select part of `abcd`, press Left or Right, then type `q`. Repeat with a selection that includes a fraction. In the native field, dismiss the menu with Escape before testing Up/Down collapse. | Left uses the ordered start; Right uses the ordered end. Typing inserts at that edge instead of replacing the old range. A fraction boundary does not enter the wrong slot. | Rerun — `selection-collapse-check.js`, `tinymce-inline-check.js` |
|
|
55
|
+
| EDIT-005 | P0 — Radical conversion | Load `\sqrt{x+1}`. Choose Change to Indexed root. Replace the selected `2` with `3`. Return to the radicand, then edit the index to `2` and convert back. Undo and Redo. | The radicand and nested nodes survive. Index `2` is selected on conversion. Index `3` cannot be silently discarded. One conversion is one Undo step. | Recorded, partial scope — `root-transform-check.js` (React/Quill, pointer and keyboard acceptance, 2026-09-09); `root-transform.test.ts` (Undo/Redo and nested trees). Browser Undo/Redo and the other hosts still need a run. |
|
|
56
|
+
| EDIT-006 | P0 — Structure deletion | Create a fraction, scripts, aligned equations and cases. Test Backspace/Delete at inner and outer boundaries with empty and populated slots. Undo each deletion. | Behavior matches the documented boundary rule. Populated grid cells are not silently merged or lost. Undo restores content and structure. | Recorded, scoped — `test/editing/deletion.browser.js`: 3 surfaces / 2,766 checkpoints, 55 catalog kinds, populated boundaries and applicable empty-slot checks; 2026-09-13. See current validation for explicit non-applicable spacing/grid cases. |
|
|
57
|
+
| EDIT-007 | P0 — Copy and paste a range | Select text plus a nested fraction. Copy, move the caret, paste, then cut and Undo. Repeat across two editor instances. | The selected structure is preserved; unselected content stays unchanged. Cut can be undone. A rejected paste leaves the document unchanged. | Recorded, scoped — `test/editing/clipboard.browser.js`: React/DOM block and inline, 76 checkpoints, nested ranges, cross-instance and matrix clipboard; 2026-09-13. Real OS clipboard remains separate. |
|
|
58
|
+
| EDIT-008 | P0 — LaTeX import failure | Import `\frac{x}{y}+z`. Edit `x`. Attempt an unsupported command and malformed braces. Cancel, then reopen. | Valid input is editable. Invalid or unsupported input reports a diagnostic and retains the previous formula. Cancel does not replace host content. | Rerun — `latex-paste-host-check.js`, `latex-insertion.test.ts`, `latex.test.ts` |
|
|
59
|
+
| EDIT-009 | P0 — Apply, Cancel and history | Open an existing host formula. Edit and Cancel. Reopen, edit and Apply. Run host Undo and Redo. | Cancel leaves the stored host data unchanged. Apply creates one host history operation. Host serialization contains formula data, not input/menu DOM. | Recorded, scoped — `test/editing/continuous.browser.js`, all nine demos on 2026-09-13; exact Apply/Cancel and configured host history. Editor.js host history is not configured. |
|
|
60
|
+
| EDIT-010 | P0 — Save and reopen | Edit nested content, Apply, Save and Restore. Reload the stored host document and reopen the formula. | Structure, LaTeX and configured presentation survive. The formula is editable after restoration. Do not claim persistence from a preview-only check. | Recorded, scoped — `test/editing/continuous.browser.js`, all nine demos on 2026-09-13; actual save/reload/restore, reopened editing and Cancel. |
|
|
61
|
+
| EDIT-011 | P0 — Host boundary and read-only | Move from prose into an inline formula with a boundary arrow. Edit, exit and continue prose. Switch the host to read-only with a draft open. | Math key events do not edit prose. Read-only closes or disables the draft according to the host contract and prevents new mutations. | Recorded, scoped — `test/editing/continuous.browser.js`: inline exit/prose continuation and active-draft read-only transitions. Programmatic read-only toggle isolates the transition from intentional pointer-blur Apply. |
|
|
62
|
+
| EDIT-012 | P1 — Suggestion scrolling | Type `matrix`. Park the pointer over a menu item. Press Down repeatedly with pauses; reverse with Up. Test near the bottom of the viewport and in an iframe. | Each press moves one option. The selected option stays visible. The list does not jump back; the page and host do not scroll unexpectedly. | Rerun — `suggestion-arrow-check.js`, `suggestion-menu-clipping-check.js`, `iframe-field-check.js` |
|
|
63
|
+
| EDIT-013 | P1 — Nested navigation | Enter `x_i^2`, a fraction inside a root, and a limit. Move with Left/Right, Up/Down and Tab at every slot boundary. | The nearest structure owns vertical movement when no suggestion menu is active. Selection and caret positions remain valid. | Recorded, scoped — `vertical-column.browser.js`, `held-arrows.browser.js` and `vertical-navigation.test.ts`; preferred column and horizontal reset pass on 2026-09-13. Wider slot variations retain model tests. |
|
|
64
|
+
| EDIT-014 | P1 — Rectangular matrix | Type `3x7` and accept the matrix. Fill cells; add/delete rows and columns. Test `1x2` and `2x1` boundaries. | Dimensions match the request. Existing cells retain their content. Cursor movement follows the resulting grid. | Rerun — `matrix-size-shortcut-check.js`, `matrix.test.ts`, `native-tools-host-check.js` |
|
|
65
|
+
| EDIT-015 | P0 — Matrix range editing | Select a cell rectangle. Copy/paste, clear, Undo and transpose. Test a mismatched or oversized paste. | Cell boundaries and nested structures survive. Invalid operations leave the matrix unchanged. Draft operations do not create host history entries. | Rerun — `matrix-range-check.js`, `matrix-range-host-check.js`, `matrix-range.test.ts` |
|
|
66
|
+
| EDIT-016 | P1 — Lines, alignment and cases | Create two lines. Insert aligned equations and cases; add a row and edit both columns. Try Enter in inline mode. | Block layouts retain their rows. Inline mode does not create an extra formula line. Enter follows the configured host commit policy. | Recorded, scoped — `test/editing/lines.browser.js`: 2 surfaces / 28 checkpoints, matrix/alignment/cases rows and split/merge; inline Enter also runs in `continuous.browser.js`. Core `embedding.test.ts` checks commit policy. |
|
|
67
|
+
| EDIT-017 | P1 — Preview agreement | Edit a nested root, scripts, tall fences, integrals with limits, and a chemical formula. Compare exported LaTeX in KaTeX at a matched base size. Repeat with the input active. | Mathematical structure agrees. Baselines, fences, indices and limits remain readable. Focus backgrounds and hit areas do not obscure notation. | Recorded metric baseline — 91 formulas / 330 comparisons passed on 2026-09-13; narrow-host editing also passed. See source-only `test/rendering/STATUS.md`; selected metrics do not certify every glyph. |
|
|
68
|
+
| EDIT-018 | P1 — Language and multiple instances | Switch en/ko with a draft open. Open another editor and its suggestions. Repeat with a registered custom locale. | Labels resolve, formulas do not change, focus and menus stay with the right instance, and search aliases use the locale fallback rules. | Recorded, scoped — `frameworks.browser.js` (8 samples / 60 checkpoints) and `bindings.browser.js` (5 bindings / 30 checkpoints), 2026-09-13; locale discovery/fallback remains covered by core tests. |
|
|
69
|
+
| EDIT-019 | P0 — Long edit session | Build a fraction, wrap a selection, convert a radical, insert a matrix, undo five steps, redo five, Apply, Save and reopen. Repeat without resetting the page. | No stuck focus, lost selection, duplicated operation or draft leakage. All checkpoints retain the expected formula. | Recorded, scoped — `test/editing/continuous.browser.js`: 17 targets / 532 checkpoints on 2026-09-13. Includes clipboard/history, Apply/Cancel, save/reload/reopen, read-only and inline prose continuation. Editor.js host history, TinyMCE iframe and installed WordPress admin are not included. |
|
|
70
|
+
| EDIT-020 | P2 — Native IME and clipboard | On a real OS, compose Korean text, move the caret, use suggestions, cancel composition and paste with the system clipboard. | Composed text appears once; composition keys do not apply suggestions or host commands prematurely. Clipboard data is preserved according to the documented formats. | Manual — previously deferred by the user. Synthetic composition/DataTransfer checks do not certify OS behavior. |
|
|
71
|
+
|
|
72
|
+
## Contextual structure tools
|
|
73
|
+
|
|
74
|
+
These scenarios specify the footer independently from the suggestion list. The
|
|
75
|
+
footer has a single target: the nearest enclosing radical or fence. It is shown only
|
|
76
|
+
while that editor is active, outside literal text and model/matrix selections.
|
|
77
|
+
Native text selection within the active slot is allowed, including the selected
|
|
78
|
+
index produced by conversion.
|
|
79
|
+
|
|
80
|
+
| ID | Priority / flow | Steps | Required result | Coverage |
|
|
81
|
+
| --- | --- | --- | --- | --- |
|
|
82
|
+
| EDIT-021 | P1 — Discover without search | Click inside a root. Put the caret at the start of its text. Dismiss suggestions with Escape. Move outside the root. | Footer shows the current structure and conversion even with no query or no open suggestions. Leaving the radical hides it. | `context-tools-check.js` |
|
|
83
|
+
| EDIT-022 | P0 — Footer conversion and index edit | Convert a root using the footer. Replace selected index `2` with `3`. Click the radicand, choose Edit index, type `2`, convert back and Undo. | Content survives, index editing selects the existing index, a non-square index blocks reverse conversion with a visible reason, and Undo restores the structure. | `context-tools-check.js` |
|
|
84
|
+
| EDIT-023 | P0 — Keyboard-only footer | From input, press F6, Escape, F6 and Enter. Tab between available buttons. | F6 enters tools; Escape returns to the same input. Button activation edits the intended structure. Keys do not reach host prose. Tab uses native button order. | F6/Escape/Enter recorded in `context-tools-check.js`; explicit Tab-order assertion remains to add. |
|
|
85
|
+
| EDIT-024 | P0 — Nearest nested target | Open `\sqrt[3]{a+\sqrt{x}}`. Move between `a` and `x`. | Footer identifies the outer indexed root at `a` and inner square root at `x`. Index editing targets the corresponding root. | `context-tools-options-check.js`, `root-transform.test.ts` |
|
|
86
|
+
| EDIT-025 | P1 — Locale without model changes | Show tools, change en to ko, then edit the index. | Structure name, actions, disabled reason and keyboard hint update together. Stored formula content is unchanged by locale selection. | `context-tools-options-check.js`; direct document equality on locale switch remains to add. |
|
|
87
|
+
| EDIT-026 | P0 — Scope and focus | Create a model range, collapse it, blur the field, reopen, then destroy the instance. Repeat focus navigation inside an iframe. | Range mode does not show stale caret actions. Collapse restores context; blur hides it; destroy removes it. Focus stays in the iframe's own document. | `context-tools-check.js`, `context-tools-options-check.js` |
|
|
88
|
+
| EDIT-027 | P0 — Composition guard | Dispatch composition start and end in the native field with context visible. | Actions are disabled during composition and resume afterward. This guard test is not OS IME certification. | Synthetic coverage in `context-tools-options-check.js`; real OS behavior remains EDIT-020. |
|
|
89
|
+
| EDIT-028 | P1 — Embedding opt-out | Set `contextTools: false`, then update to true. Repeat with `context-tools="false"` on a Web Component. | Footer hides without changing the formula or removing suggestion-based conversions. Attribute updates take effect without remounting. | Visibility/update coverage in `context-tools-options-check.js`; per-framework wrapper smoke checks remain to add. |
|
|
90
|
+
|
|
91
|
+
## Inline transformation suggestions
|
|
92
|
+
|
|
93
|
+
The suggestion list is the primary keyboard entry point for structural changes.
|
|
94
|
+
It remains available when both toolbar and context footer are hidden. Alt+Down
|
|
95
|
+
opens or reopens suggestions and highlights the first available transformation;
|
|
96
|
+
Up/Down browses, Enter applies, and Escape dismisses without editing the formula.
|
|
97
|
+
Automatic context-only suggestions require navigation before Enter can apply them,
|
|
98
|
+
so an inline host's commit key is not silently replaced.
|
|
99
|
+
|
|
100
|
+
| ID | Priority / scenario | Steps | Expected result | Coverage |
|
|
101
|
+
| --- | --- | --- | --- | --- |
|
|
102
|
+
| EDIT-029 | P0 — Fence suggestions in inline fields | Type inside parentheses. Press Alt+Down, Enter, then continue typing. Repeat after dismissing the menu. | The list distinguishes changing a fence from wrapping an operand. Existing content and caret are preserved; the menu does not take DOM focus. | `fence-suggestions-check.js`, `context-tools.test.ts` |
|
|
103
|
+
| EDIT-030 | P0 — Browse, cancel and Undo | Open changes, browse with Up/Down, cancel with Escape. Reopen, apply, type, then undo typing and conversion separately. | Browsing and cancellation do not change the formula. Conversion makes one history entry. | `fence-suggestions-check.js` |
|
|
104
|
+
| EDIT-031 | P0 — Nearest wrapper and all fence pairs | Change each of eight fence types. Test nested fractions, roots, mixed delimiters and stale targets. Use F6/Left/Right/Enter if the optional footer is enabled. | Only the nearest supported wrapper changes. Slot IDs, content and caret remain stable. Explicit left/right metadata is removed when selecting a standard pair. | `context-tools.test.ts`, `fence-context-check.js`; browser nested targeting in EDIT-032 |
|
|
105
|
+
| EDIT-032 | P0 — No-toolbar inline iframe | Hide toolbar/footer in an inline iframe field. Change an inner fence with suggestions, switch ko/en and continue typing. Destroy the editor. | The complete workflow works without auxiliary UI. Locale changes leave the document unchanged. Focus uses the iframe document; teardown removes suggestions. | `fence-inline-options-check.js`; installed host/browser breadth remains separate validation work |
|
|
106
|
+
|
|
107
|
+
Execution scope is recorded in [Validation](VALIDATION.md). A mapped case may
|
|
108
|
+
still contain pending assertions, as stated in the Coverage column.
|
|
109
|
+
|
|
110
|
+
Browser fixture names above refer to `apps/math-integrations/tests/`. Unit fixture
|
|
111
|
+
names refer to `packages/math-editor/test/`. A mapping identifies related coverage,
|
|
112
|
+
not an assertion that every step already exists in that file. Extend cases need
|
|
113
|
+
explicit browser assertions before they can receive a full pass.
|
|
114
|
+
|
|
115
|
+
## Test environments
|
|
116
|
+
|
|
117
|
+
Record renderer, adapter, mode and browser separately. An integration using the
|
|
118
|
+
native DOM field does not prove the rich React field, and an iframe can have its
|
|
119
|
+
own focus, event and CSS failures.
|
|
120
|
+
|
|
121
|
+
| Layer | Required scope when that layer changes |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| Shared model / suggestions | Unit checks plus affected editing scenarios on rich React and native DOM. |
|
|
124
|
+
| Framework adapter | The affected adapter: pure JS, Web Component, Vue, Svelte, Solid, or React wrapper. Record the actual renderer used. |
|
|
125
|
+
| Host integration | Every affected host. Shared field changes need the nine-host smoke set: Tiptap, ProseMirror, Lexical, Editor.js, TinyMCE, CKEditor, Quill, Slate, Gutenberg. |
|
|
126
|
+
| Mode / container | Inline and block where supported; TinyMCE classic iframe as well as inline. Editor.js and Gutenberg block-only scenarios are N/A for inline tests. |
|
|
127
|
+
| Browser | Record Chromium, Firefox or WebKit explicitly. Current Chromium evidence does not cover the other engines. |
|
|
128
|
+
| Build source | Workspace source for development; packed artifacts for release checks. Neither implies the other. |
|
|
129
|
+
|
|
130
|
+
## Per-run record
|
|
131
|
+
|
|
132
|
+
Append detailed evidence to [Validation](VALIDATION.md), using this template.
|
|
133
|
+
Record an immutable revision when possible. For an uncommitted workspace, record
|
|
134
|
+
that fact and save the tested patch or a source fingerprint with the run artifacts.
|
|
135
|
+
A date alone does not identify the tested code.
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
Run ID: edit-YYYYMMDD-NN
|
|
139
|
+
Scenario IDs:
|
|
140
|
+
Source: commit / workspace fingerprint / package versions and archive hashes
|
|
141
|
+
Fixture revision:
|
|
142
|
+
Renderer and host:
|
|
143
|
+
Mode and container:
|
|
144
|
+
Browser, OS, locale:
|
|
145
|
+
Input formula and steps:
|
|
146
|
+
Expected result:
|
|
147
|
+
Observed result:
|
|
148
|
+
Outcome: PASS / FAIL / BLOCKED / NOT RUN / N/A
|
|
149
|
+
Evidence: log, screenshot pair, trace or recorded host data
|
|
150
|
+
Remaining steps and excluded environments:
|
|
151
|
+
Issue / follow-up:
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
A scenario passes only when all required assertions pass in the recorded scope.
|
|
155
|
+
For partial coverage, report the passing steps and keep the rest unverified.
|
|
156
|
+
Do not convert historical validation totals into a current release pass.
|
|
157
|
+
|
|
158
|
+
## Change workflow
|
|
159
|
+
|
|
160
|
+
1. Assign a scenario ID to each editing bug before changing its behavior.
|
|
161
|
+
2. Reproduce the smallest failing input sequence. Capture the caret, selection,
|
|
162
|
+
highlighted suggestion, document and host data where relevant.
|
|
163
|
+
3. Add or update a regression fixture with the same ID. Check the final model,
|
|
164
|
+
cursor/focus and history behavior, not only whether an element is visible.
|
|
165
|
+
4. Implement the change. Run its model tests, affected browser scenarios and the
|
|
166
|
+
nearest negative case. Compare editor/KaTeX output when notation changes.
|
|
167
|
+
5. Record the result and its scope. Mark related scenarios for rerun if later
|
|
168
|
+
changes touch their input, selection, suggestions, history or host handling.
|
|
169
|
+
6. Before release, run the applicable P0 cases against the release candidate and
|
|
170
|
+
check packed imports. Any excluded host/browser must be stated explicitly.
|
|
171
|
+
|
|
172
|
+
The Markdown register is the source of truth for scope and acceptance criteria.
|
|
173
|
+
The browser fixtures contain executable assertions. The validation report holds
|
|
174
|
+
run evidence. The documentation site renders this register; it does not execute
|
|
175
|
+
the browser checks. Automated release enforcement is not implemented by this
|
|
176
|
+
register alone.
|
|
177
|
+
|
|
178
|
+
## Next work
|
|
179
|
+
|
|
180
|
+
The [supported-notation milestone](ROADMAP.md#completed-milestone-reliable-editing-of-supported-notation--2026-09-13) is complete for its recorded desktop Chromium scope. Keep the 11 editing suites and full rendering audit as regression checks for subsequent changes.
|
|
181
|
+
|
|
182
|
+
1. Validate Safari, Firefox and Windows Chromium, then real OS IME/clipboard and assistive input.
|
|
183
|
+
2. Verify additional installed-host configurations, including TinyMCE iframe and WordPress admin.
|
|
184
|
+
3. Define JSON migration/recovery and measured document-size/depth/performance budgets.
|
|
185
|
+
4. Expand an editing scenario when a concrete defect or use case requires it. Compare the expected JSON tree and caret with actual edited output and KaTeX. Do not expand notation only to increase a feature count.
|
|
186
|
+
|
|
187
|
+
These are subsequent milestones. No pass is claimed for them by the current reports. Keep geometry reports in the source-only rendering ledger.
|
|
188
|
+
|
|
189
|
+
## Direct selection wrapping — EDIT-033
|
|
190
|
+
|
|
191
|
+
Select math by Shift+arrows, dragging, or native input selection. Press `(`, `[`, `{`, `|`, `/`, `^` or `_` without accepting a suggestion. Check retained content, the new caret slot, continued typing, one-step wrapping Undo and Redo. Include reversed and cross-slot selections, literal text, composition guards and multi-line rejection.
|
|
192
|
+
|
|
193
|
+
Run `pnpm --filter @barocss/math-editor test:editing --suite=shortcuts`.
|
|
194
|
+
The dedicated browser fixture covers React block and native DOM block/inline (63 cases). Core tests cover nested ranges and negative cases. OS IME remains a separate scenario. Geometry fixtures VIS-080–093 compare the resulting notation against KaTeX at 22px and 36px, including active input.
|
|
195
|
+
|
|
196
|
+
## Held arrow navigation — EDIT-034
|
|
197
|
+
|
|
198
|
+
Hold Left or Right through a number, an operator and a variable. Every repeated keydown must use the current input caret. Token and structure boundaries must respond before keyup. Repeat the check through fraction numerator and denominator slots, in both directions. Then hold Shift+Left, collapse the range with Right, type and Undo. Caret movement must preserve the formula and must not emit a document change.
|
|
199
|
+
|
|
200
|
+
Run `pnpm --filter @barocss/math-editor test:editing --suite=arrows`.
|
|
201
|
+
The fixture covers React block and native DOM block/inline. It sends repeated real browser keydown events with one final keyup, and records every focused input and caret offset. Browser-generated key repeat covers the editor event path; physical keyboard repeat timing remains OS-controlled.
|
|
202
|
+
|
|
203
|
+
## Learning and help — EDIT-035
|
|
204
|
+
|
|
205
|
+
Run `pnpm --filter @barocss/math-editor test:editing --suite=learning`.
|
|
206
|
+
|
|
207
|
+
Complete the five practice tasks with keyboard input: correction, selection-to-fraction, power, nearest root conversion and explicit LaTeX insertion. Reject a wrong answer; verify reset/close behavior and an unchanged playground. Pass criteria compare normalized model trees, not merely the rendered string. Test English and Korean help, toolbar access and F1 in React/native block and native inline fields. Closing must restore native selection, permit immediate wrapping/typing and preserve Undo. Destroying a field must remove open help.
|
|
208
|
+
|
|
209
|
+
The continuous host suite also opens/closes help before its existing editing chain. This tests the host draft boundary separately from standalone focus checks. Native OS F1/Fn routing and screen-reader behavior remain separate device checks.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Learn to edit a formula
|
|
2
|
+
|
|
3
|
+
Start with [the five practice exercises](https://math-editor.barocss.com/#tutorial). They use a separate field and leave your playground formula unchanged. Each exercise checks the resulting formula model. You can reset an exercise, go back or close the practice area.
|
|
4
|
+
|
|
5
|
+
## Make editing comfortable
|
|
6
|
+
|
|
7
|
+
If a fraction or nested formula feels small, choose **Math size → 26px** above
|
|
8
|
+
the playground. This enlarges the formula while keeping the relative sizes of
|
|
9
|
+
the base, exponent and radicand. A complex denominator makes the fraction taller;
|
|
10
|
+
it does not automatically enlarge the numerator.
|
|
11
|
+
|
|
12
|
+
편집할 분수나 중첩 수식이 작게 느껴지면 위의 **수식 크기 → 26px**를 선택하세요.
|
|
13
|
+
수식 내부의 크기 비율은 유지됩니다. 분모가 복잡해져도 분자 글자가 자동으로
|
|
14
|
+
커지지는 않습니다. 편집 크기는 저장되는 LaTeX와 미리보기 이미지 크기를 바꾸지 않습니다.
|
|
15
|
+
|
|
16
|
+
Nested editing text has a 14px minimum. In a text-editor visual popup, use
|
|
17
|
+
**125%** or **150%** zoom for a larger editing view. Editing size does not change
|
|
18
|
+
saved LaTeX or the preview/export size. Embedded apps can configure a larger
|
|
19
|
+
minimum and must allow the equation's line height to grow; see [Styling](STYLING.md).
|
|
20
|
+
|
|
21
|
+
## 1. Write, then correct
|
|
22
|
+
|
|
23
|
+
Type `x+1`. Click the number and change it to `2`. Use Left/Right to move the caret. A held arrow key should keep moving. Undo and Redo let you inspect changes without starting again.
|
|
24
|
+
|
|
25
|
+
## 2. Build structure from existing input
|
|
26
|
+
|
|
27
|
+
Type `a+b`, then select it by dragging or using Shift+arrows. Press `/`. The selected expression becomes the numerator, and the denominator receives the caret. Type `2`.
|
|
28
|
+
|
|
29
|
+
You do not have to choose a fraction before writing its contents. Selected math can also be wrapped with `(`, `[`, `{`, `|`, `^` and `_`.
|
|
30
|
+
|
|
31
|
+
## 3. Add a power or subscript
|
|
32
|
+
|
|
33
|
+
Select `x`, press `^`, then type `2`. Use `_` instead when you need a subscript. Use Tab to move between editable slots. The editor preserves the distinction between a base and its scripts.
|
|
34
|
+
|
|
35
|
+
## 4. Change an existing structure
|
|
36
|
+
|
|
37
|
+
Click inside a square root. Press Alt+Down to open suggestions. Choose Change to Indexed root and press Enter. The new index is selected; type `3` to replace it. The radicand stays intact.
|
|
38
|
+
|
|
39
|
+
The same suggestion area offers supported bracket transformations when the caret is inside a bracketed expression. You do not need a toolbar. Escape closes the list; Undo reverses a conversion.
|
|
40
|
+
|
|
41
|
+
## 5. Bring in existing LaTeX
|
|
42
|
+
|
|
43
|
+
Put the caret after a formula. Press Alt+Shift+V, enter `+c^2`, then Ctrl/Cmd+Enter. This adds parsed LaTeX at the caret. Ordinary paste inserts text or preserved editor clipboard data; it does not automatically interpret LaTeX.
|
|
44
|
+
|
|
45
|
+
Read [copy and paste](CLIPBOARD.md) before transferring formulas between applications. The site can also copy/download a PNG from its rendering preview. A PNG cannot be reopened as an editable formula.
|
|
46
|
+
|
|
47
|
+
## Keep these controls nearby
|
|
48
|
+
|
|
49
|
+
- **F1:** keyboard and clipboard help inside the field.
|
|
50
|
+
- **Alt+Down:** suggestions and available transformations.
|
|
51
|
+
- **Tab / Shift+Tab:** move between slots.
|
|
52
|
+
- **Ctrl/Cmd+Z:** undo the last edit.
|
|
53
|
+
|
|
54
|
+
The [keyboard reference](KEYBOARD.md) explains selection, Enter and deletion rules. The [LaTeX guide](LATEX-GUIDE.md) covers more notation. Developers embedding a field can continue with [framework guides](ADAPTERS.md).
|
package/IMPLEMENTATION.md
CHANGED
|
@@ -265,3 +265,108 @@ operations needs a new model version or parser command.
|
|
|
265
265
|
Native text rows are tokenized with the same `tokenizeMathText`/`tokenIndexAt` rules as rich React. Every rendered run retains its model ID and UTF-16 token start/end. Input events replace only that token's slice. Pointer/keyboard offsets are translated to model coordinates; boundary deletion joins neighboring text without discarding it. IME preedit updates the stable input/mirror and is committed before re-tokenizing. Literal text/operator names remain one input.
|
|
266
266
|
|
|
267
267
|
`latex-insertion.ts` parses before applying a range insertion. `preferences.ts` owns validated UI lists independently of formula sessions/history. `presentation.ts` changes only supported metadata while preserving subtree IDs and caret. The nonmodal native panels are reused by React wrappers, so diagnostics and favorites use one implementation. Host clipboard boundaries stay intact and no system clipboard reads are implicit.
|
|
268
|
+
|
|
269
|
+
### Contextual radical conversions
|
|
270
|
+
|
|
271
|
+
`findStateSuggestions(state, locale, caret?)` augments text search with the nearest
|
|
272
|
+
enclosing radical's conversion actions. `transformRootId` binds an action to that
|
|
273
|
+
structure; `acceptSuggestion` validates the current target before conversion and
|
|
274
|
+
does not remove the query. `root-transform.ts` clones the document, preserves the
|
|
275
|
+
radicand tree and structure ID, and updates the slots. Converting to an indexed
|
|
276
|
+
root adds a selected index `2`; converting to a square root rejects any nonempty
|
|
277
|
+
index other than `2`. Both renderers use this shared path and their normal history
|
|
278
|
+
commit mechanism. Context-only actions require pointer acceptance or arrow-key
|
|
279
|
+
selection before Enter can apply them.
|
|
280
|
+
|
|
281
|
+
### Empty-slot deletion and script fractions
|
|
282
|
+
|
|
283
|
+
`unwrapEmptySlot` removes a non-grid wrapper from inside a truly empty slot.
|
|
284
|
+
Both Delete and Backspace call it before boundary-specific deletion. The other
|
|
285
|
+
slots are retained; an empty root index collapses to a square root, and an empty
|
|
286
|
+
paired script preserves the other script. A populated row or ordinary structural
|
|
287
|
+
boundary is not an empty slot. Grid cells keep their shape and their existing
|
|
288
|
+
explicit deletion controls. The edit uses the normal history commit.
|
|
289
|
+
|
|
290
|
+
Fractional script presentation uses compact row heights and term metrics in both
|
|
291
|
+
renderers. See [Rendering checks](RENDERING-TESTS.md) for the bounded geometry
|
|
292
|
+
comparison and remaining layout work.
|
|
293
|
+
|
|
294
|
+
### Query-independent context footer
|
|
295
|
+
|
|
296
|
+
`rootEditingContext(state)` derives the nearest radical, conversion availability
|
|
297
|
+
and index caret from the model. React and DOM render the same actions below the
|
|
298
|
+
surface. The footer does not use suggestion text, dismissal or candidate indices.
|
|
299
|
+
Transformations use `transformRoot` and normal history; Edit index only moves
|
|
300
|
+
and selects the caret. Model/matrix selections and blur hide context actions.
|
|
301
|
+
F6 and Escape are handled within the editor to retain host/iframe focus. Native
|
|
302
|
+
composition disables footer actions without replacing the composing input.
|
|
303
|
+
|
|
304
|
+
### Shared fence transformations
|
|
305
|
+
|
|
306
|
+
`structureEditingContext` selects the nearest supported radical or fence and
|
|
307
|
+
excludes literal text. `findStateSuggestions` adds fence transformations before
|
|
308
|
+
operand-wrapping actions, while retaining explicit symbol/command matches first.
|
|
309
|
+
`transformFenceId` distinguishes metadata changes from new structure insertion.
|
|
310
|
+
Acceptance validates the current target before preserving content, IDs and caret.
|
|
311
|
+
|
|
312
|
+
React and native DOM handle Alt+Down before modifier-key fallthrough. The shortcut
|
|
313
|
+
reopens a dismissed list and arms the first context action. Normal contextual
|
|
314
|
+
menus still require navigation before Enter overrides host commit behavior.
|
|
315
|
+
The footer is optional; suggestions do not depend on its visibility.
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
## Contextual operator layout
|
|
319
|
+
|
|
320
|
+
`src/math-layout.ts` derives display, text, script and scriptscript contexts from
|
|
321
|
+
model slots on each render. It does not mutate or persist presentation metadata.
|
|
322
|
+
Fractions reduce the style of their terms; scripts reduce their labels; indexed
|
|
323
|
+
root indices use scriptscript style. Explicit fraction styles reset that context. Aligned cells enter display style; matrix and cases cells enter text style.
|
|
324
|
+
|
|
325
|
+
Both React and native DOM consume the same row/operator map. Operator attributes
|
|
326
|
+
select the large or small font and side or stacked limits. Explicit limits remain
|
|
327
|
+
authoritative. Scoped row attributes keep a nested operator body at its own size
|
|
328
|
+
while reducing its bounds. This replaces the inline-only CSS decision, which
|
|
329
|
+
could not identify operators inside fractions or nested scripts.
|
|
330
|
+
|
|
331
|
+
The current CSS application is scoped to operators. Other structures still use
|
|
332
|
+
their existing layout rules; this is not a complete TeX layout engine.
|
|
333
|
+
|
|
334
|
+
### Horizontal text spacing
|
|
335
|
+
|
|
336
|
+
`math-spacing.ts` computes spacing between lexical runs without changing the
|
|
337
|
+
saved document, token boundaries or caret offsets. Both renderers use the same
|
|
338
|
+
values. Common binary operators use 4 mu, relations use 5 mu and punctuation
|
|
339
|
+
uses 3 mu before the next atom (18 mu = 1 em). Neighboring atoms distinguish
|
|
340
|
+
unary signs from binary operators. Binary, relation and punctuation gaps are
|
|
341
|
+
suppressed in script and scriptscript rows.
|
|
342
|
+
|
|
343
|
+
Measuring spans use glyph width instead of adding padding to every math token.
|
|
344
|
+
Literal text fields retain their text layout. Named-function fields use unpadded glyph measurement. Inactive model
|
|
345
|
+
boundaries use 1 px; empty expression slots and the active boundary keep their
|
|
346
|
+
existing input hit areas. Other structure interiors and full TeX atom classification are separate work. These rules do not provide a complete
|
|
347
|
+
TeX horizontal layout engine.
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
### Named functions and fraction boundaries
|
|
351
|
+
|
|
352
|
+
Named functions and fractions participate in the same horizontal-spacing pass as
|
|
353
|
+
text runs. A named function uses a thin gap next to an ordinary atom or another
|
|
354
|
+
named function, and no gap before a plain opening parenthesis. These thin gaps
|
|
355
|
+
remain in script styles at the corresponding reduced font size. Binary and
|
|
356
|
+
relation gaps still disappear in scripts. Fractions contribute an ordinary atom
|
|
357
|
+
and receive their external gap once, rather than adding fixed margins on both
|
|
358
|
+
sides. The function name's measuring span adds no glyph padding.
|
|
359
|
+
|
|
360
|
+
The spacing map contains structure IDs for these two families and token-offset
|
|
361
|
+
keys for text. Other structure families keep their existing outer layout. This
|
|
362
|
+
change does not alter LaTeX output, JSON, selection offsets or editing commands.
|
|
363
|
+
|
|
364
|
+
## Editing boundary corrections — 2026-09-13
|
|
365
|
+
|
|
366
|
+
`unwrapNext` reuses the non-grid unwrapping operation, then restores the left-side caret. `joinNextLine` delegates to the existing line merge and keeps the join position. Grid deletion remains a distinct selection/removal operation; it does not pass through wrapper flattening.
|
|
367
|
+
|
|
368
|
+
Both renderers use a view-local preferred column for vertical navigation. The column is not stored in JSON or history. The current row supplies Y while the first vertical movement supplies X; typing, horizontal navigation and pointer placement reset it. Native caret selection is synchronized before keydown so held arrows do not wait for keyup.
|
|
369
|
+
|
|
370
|
+
React and DOM use `mathEnterAction` for Enter decisions. Structured clipboard input is validated before literal fallback. A present but malformed math payload is rejected; missing custom data can still use ordinary text. Single-line mode rejects multiple rows before applying the React paste result.
|
|
371
|
+
|
|
372
|
+
Editing regression runners use the repository-owned `scripts/math-playwright-cli.sh`. Controlled ClipboardEvents test handler behavior, not the OS clipboard. In host tests, permission changes occur without pointer blur: clicking outside an in-place field is a separate, intentional Apply operation. Editor.js cannot save while read-only, so its document equality check runs after editing is re-enabled.
|