@barocss/math-editor 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/ADAPTERS.md +31 -2
  2. package/API-JAVASCRIPT.md +157 -0
  3. package/API-REACT.md +202 -0
  4. package/API-SESSION.md +163 -0
  5. package/API-SOLID.md +90 -0
  6. package/API-SVELTE.md +83 -0
  7. package/API-VUE.md +104 -0
  8. package/API-WEB-COMPONENT.md +128 -0
  9. package/CHANGELOG.md +21 -0
  10. package/EMBEDDING.md +7 -0
  11. package/IMPLEMENTATION.md +132 -1
  12. package/JSON-MODEL.md +441 -0
  13. package/LATEX-GUIDE.md +254 -0
  14. package/LATEX-MODEL.md +290 -0
  15. package/LATEX-SCOPE.md +260 -4
  16. package/LOCALIZATION.md +7 -1
  17. package/README.md +97 -4
  18. package/RELEASING.md +1 -1
  19. package/ROADMAP.md +111 -16
  20. package/SUPPORT.md +134 -13
  21. package/SYMBOLS.md +33 -1
  22. package/VALIDATION.md +175 -0
  23. package/dist/core.d.ts +2 -0
  24. package/dist/core.d.ts.map +1 -1
  25. package/dist/core.js +2 -0
  26. package/dist/core.js.map +1 -1
  27. package/dist/document-codec.d.ts +4 -0
  28. package/dist/document-codec.d.ts.map +1 -0
  29. package/dist/document-codec.js +37 -0
  30. package/dist/document-codec.js.map +1 -0
  31. package/dist/dom/menu-position.d.ts +3 -0
  32. package/dist/dom/menu-position.d.ts.map +1 -0
  33. package/dist/dom/menu-position.js +44 -0
  34. package/dist/dom/menu-position.js.map +1 -0
  35. package/dist/dom/toolbar.d.ts +2 -0
  36. package/dist/dom/toolbar.d.ts.map +1 -1
  37. package/dist/dom/toolbar.js +16 -1
  38. package/dist/dom/toolbar.js.map +1 -1
  39. package/dist/dom.d.ts +1 -0
  40. package/dist/dom.d.ts.map +1 -1
  41. package/dist/dom.js +153 -24
  42. package/dist/dom.js.map +1 -1
  43. package/dist/editor-labels.d.ts.map +1 -1
  44. package/dist/editor-labels.js +42 -0
  45. package/dist/editor-labels.js.map +1 -1
  46. package/dist/fences.d.ts +11 -0
  47. package/dist/fences.d.ts.map +1 -0
  48. package/dist/fences.js +21 -0
  49. package/dist/fences.js.map +1 -0
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/latex.d.ts +26 -0
  55. package/dist/latex.d.ts.map +1 -0
  56. package/dist/latex.js +689 -0
  57. package/dist/latex.js.map +1 -0
  58. package/dist/locales/en.js +109 -2
  59. package/dist/locales/en.json +109 -2
  60. package/dist/locales/ko.js +121 -3
  61. package/dist/locales/ko.json +121 -3
  62. package/dist/math-editor-toolbar.d.ts +5 -2
  63. package/dist/math-editor-toolbar.d.ts.map +1 -1
  64. package/dist/math-editor-toolbar.js +10 -6
  65. package/dist/math-editor-toolbar.js.map +1 -1
  66. package/dist/math-editor.d.ts +24 -4
  67. package/dist/math-editor.d.ts.map +1 -1
  68. package/dist/math-editor.js +236 -40
  69. package/dist/math-editor.js.map +1 -1
  70. package/dist/model.d.ts +10 -2
  71. package/dist/model.d.ts.map +1 -1
  72. package/dist/model.js +262 -9
  73. package/dist/model.js.map +1 -1
  74. package/dist/range.d.ts +3 -1
  75. package/dist/range.d.ts.map +1 -1
  76. package/dist/range.js +162 -6
  77. package/dist/range.js.map +1 -1
  78. package/dist/react.d.ts +1 -1
  79. package/dist/react.d.ts.map +1 -1
  80. package/dist/session.d.ts +3 -0
  81. package/dist/session.d.ts.map +1 -1
  82. package/dist/session.js +9 -1
  83. package/dist/session.js.map +1 -1
  84. package/dist/suggestions.d.ts +4 -0
  85. package/dist/suggestions.d.ts.map +1 -1
  86. package/dist/suggestions.js +161 -22
  87. package/dist/suggestions.js.map +1 -1
  88. package/dist/symbols.d.ts +1 -1
  89. package/dist/symbols.d.ts.map +1 -1
  90. package/dist/symbols.js +56 -5
  91. package/dist/symbols.js.map +1 -1
  92. package/package.json +3 -2
  93. package/src/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  94. package/src/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  95. package/src/fonts/KaTeX_Main-Bold.woff2 +0 -0
  96. package/src/fonts/KaTeX_Main-Regular.woff2 +0 -0
  97. package/src/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  98. package/src/fonts/LICENSE-KaTeX.txt +21 -0
  99. package/src/style.css +868 -45
package/VALIDATION.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Validation report
2
2
 
3
+ ## Current release status — 0.2.0
4
+
5
+ The dated entries below are historical verification records, not current release availability claims. Note inline editing is resolved according to the user; this release does not change or deploy Note. Math-editor release checks and site validation are recorded separately at the end of this document.
6
+
7
+
3
8
  Updated: 2026-09-07. Scope: independent math editor prototype, Korean/English UI, active-input rendering, model selection, wrapping and editable templates.
4
9
 
5
10
  **Result:** 71 unit tests and 61 Chromium tests passed (132 total, no skipped tests). Package/demo builds and package/demo/browser-test type checks passed.
@@ -83,3 +88,173 @@ Earlier validation entries describe their historical default ordering. Current f
83
88
  79 distinct Chromium scenarios pass across the full suite and the five-case locale-suite rerun. The full run passed 78 cases; the new empty-fraction test initially expected denominator focus instead of the intended numerator-first behavior. The corrected test verifies both localized slots via Tab and converts a decomposed French query to a symbol. An earlier adapter-example variable-name collision was also fixed before this run.
84
89
 
85
90
  Package/demo builds, package and browser-test type checks, formatting, and packed runtime/type/CSS exports pass. Built output is cleaned before compilation so removed modules cannot remain in the package. Language search fixtures are not complete translations or OS IME/RTL validation.
91
+
92
+
93
+ ## Workspace LaTeX / Note trial — 2026-09-08
94
+
95
+ - Math-editor unit suite: 230 tests pass, including 90 symbol entries, templates, all empty structures, six matrix environments, diagnostics/limits and persisted-document validation. One model parity test exercises all 169 pairs of nested structure kinds and compares trees with IDs/typographic minus normalized.
96
+ - Explicit demo import browser test passes: editable fraction, failed import preserves formula, locale switch preserves source.
97
+ - Note LaTeX command tests: 6 pass, including structure/source consistency, persistence/reopen, undo/redo, stale-data clearing and readonly rejection.
98
+ - Note Chromium browser checks: 5 pass across original LaTeX editing, caret/range behavior and new visual draft workflows. Covered cancel/apply, source fallback, save/reload/reopen, multiline matrices/cases and inline top-level line rejection.
99
+ - Package and demo type checks, demo browser-test type checks, Note and demo production builds pass. Full office-editor-ui type checking is still blocked by pre-existing errors in transitive workspace modules; changed math integration files reported no errors in that run.
100
+ - Native OS IME, Safari/Firefox, assistive technology and real product multi-user conflicts were not tested in this trial. No npm package was published.
101
+
102
+
103
+ ## LaTeX compatibility completion pass — 2026-09-08
104
+
105
+ - 233 unit tests pass, including session import failure atomicity, recursive host-policy checks, alternate delimiter/blackboard spellings and comment-hidden wrapper errors.
106
+ - Adapter and LaTeX browser suite: 21 distinct scenarios verified (20 passed in the combined run; the React selector was narrowed and its test rerun). This includes seven session-based adapter import paths, plus rich React undo/redo and editing imported slots.
107
+ - Scope is the existing editable model, not all KaTeX syntax. Composite scripts, named functions, text groups, indexed roots and macros remain explicitly excluded.
108
+ - Note integration fixes are paused until this package contract is accepted; the reported Note inline-editing and popup-suggestion issues have not been fixed by this compatibility pass.
109
+
110
+ ## Imported LaTeX editing regression — 2026-09-08
111
+
112
+ - All 42 Chromium scenarios in `latex-editing.spec.ts` and `latex-import.spec.ts` pass in one run. Browser-test TypeScript checking also passes.
113
+ - Added 33 cases: rich React and native DOM editing of nested fractions/roots/scripts, three delimiter structures, sum/product/integral bounds and bodies, all six matrix environments, aligned/cases cells, gathered lines, and normalized command aliases. Each marked slot is changed through the real input, then undone, redone and undone again with LaTeX output assertions.
114
+ - Both renderers show suggestions inside an imported root and allow inserting and filling a nested fraction. Imported matrix row/column deletion shortcuts restore original contents with Undo.
115
+ - Existing import tests cover the seven session-based adapters, atomic failure, inline multiline rejection, and import history.
116
+ - Initial failures were test selectors: a focused React token has an input instead of a preview, and native text runs encompass multiple lexical tokens. Selectors now follow each renderer's actual representation. No editor implementation changes were needed for these scenarios.
117
+ - This is Chromium coverage of the supported import subset. It does not establish arbitrary LaTeX support, OS IME behavior, other browser engines, or resolve the paused Note integration issues.
118
+
119
+ ## Combined scripts and contextual selection — 2026-09-08
120
+
121
+ - 236 unit tests pass. Added both script-order imports, shared-node export, duplicate-script rejection and completion/removal of the opposite script.
122
+ - All 56 Chromium cases across LaTeX editing, import and wrapping pass in one final run. Both renderers edit imported combined scripts and complete existing scripts using mouse-selected suggestions; geometry assertions verify a shared script column. Empty-side deletion and Undo preserve the other script.
123
+ - Drag selection wraps formulas through the contextual popup; the native toolbar-free inline surface also offers and applies these actions. Multi-line wrapping stays disabled.
124
+ - Package build, demo type checking and browser-test type checking pass. Tests place the caret through input editing rather than OS-dependent End behavior, which scrolled the page in the initial runs.
125
+ - JSON model, mapping and support docs describe the workspace addition. No package publish or Note integration fixes were performed.
126
+
127
+ ## Selection suggestions — 2026-09-08
128
+
129
+ The contextual wrapping UI now uses the existing suggestion panel/list styling and listbox/option semantics instead of a separate toolbar. Mouse application, arrow-key selection and Enter application are covered; 48 Chromium cases in wrapping and LaTeX editing pass, along with package build and browser-test type checking. Native inline selection remains available without a toolbar. The previous standalone wrapping-panel styles were removed.
130
+
131
+ ## Literal text and functions — 2026-09-08
132
+
133
+ - 239 unit tests pass, including all 19 named-function round trips, literal text escaping, mixed-math rejection, and function-script insertion with literal-slot protection.
134
+ - 54 Chromium scenarios in LaTeX editing and wrapping pass. The two suggestion tests were then extended and rerun successfully to cover adding an exponent after a function suggestion in both renderers.
135
+ - Package build, demo and browser-test type checking pass. New English/Korean message keys and locale aliases use the existing registration mechanism. Matrix-prefix recommendation regression tests remain green.
136
+ - Literal text is not mixed TeX text/math or a text-styling engine. The published npm version remains unchanged.
137
+
138
+ ## Sequential typing regression — 2026-09-08
139
+
140
+ - Added real per-character keyboard tests for literal text, custom function names, ordinary math, suggestion acceptance, continued typing, middle insertion/deletion, and returning from text to math with Tab.
141
+ - Reproduced dropped typing after a model range selection in both renderers. Printable keys now replace the range and focus the resulting input. The sequential typing and wrapping suites pass all 21 cases after the fix; the replacement tests also check Undo restoration.
142
+ - Package build and browser-test type checking pass. This does not cover native OS IME composition.
143
+
144
+ ## Indexed roots — 2026-09-08
145
+
146
+ - All 241 unit tests pass, including indexed-root round trips, empty/nested indices, host exclusions and preserving the radicand when removing an empty index. The catalog-driven nested-pair test now includes indexed roots.
147
+ - The broad browser run passed 65 cases. Two new deletion tests incorrectly moved the caret out of the index with ArrowRight; after selecting the index character directly, both pass. The targeted five-case suite also verifies imported-slot edits in both renderers and drag wrapping with Undo.
148
+ - Package and demo builds and browser-test type checking pass. Scope, model mapping, JSON slot order, usage guide and roadmap are updated. No npm release was made.
149
+
150
+ ## Accents and reported inequality — 2026-09-08
151
+
152
+ - 248 unit tests pass, including accent bodies, nested wrappers, slanted relation symbols, the reported Cauchy–Schwarz expression, and comment/nesting handling for scripted parentheses.
153
+ - 74 Chromium scenarios in LaTeX editing and wrapping pass. An additional regression loads the reported full inequality and edits its first lower script and the exponent of the complete final parenthesis.
154
+ - Package/demo builds and browser-test type checking pass. Updated the guide, scope, JSON/mapping tables, symbol reference and roadmap. No npm publish was performed.
155
+
156
+ ### Binomial, operand wrapping and function spacing (workspace)
157
+
158
+ - 253 unit tests pass, including nested binomial import/export, malformed arguments, exclusions, operand preservation and undo.
159
+ - React and native browser checks cover binomial slot editing, command typing, operand wrapping, continuation, deletion/undo and normal Enter behavior.
160
+ - Function-spacing regression types `ln`, attaches a subscript and edits the name to `log`. Passive boundary targets measure at most 4.5px; the name-to-subscript gap stays below 14px. Screenshots were inspected for both renderers.
161
+ - The final spacing regression run passed 33 browser tests covering functions, operand wrapping, sequential typing and existing range wrapping. Package build, browser-test type checking and demo build pass.
162
+
163
+ ### Limits and function colors (workspace)
164
+
165
+ 261 unit tests pass. Browser validation covers LaTeX limit slot editing, per-character suggestion input, condition arrows, Tab navigation, wrapper deletion and Undo in both renderers. Function color checks cover the active name input and passive preview, including a subscripted operator. The combined browser run passed 69 tests. Package/demo builds and browser-test TypeScript checks pass.
166
+
167
+ ### Imported notation and scalable delimiter regression (workspace)
168
+
169
+ The three reported equations are regression fixtures: a quotient limit with `\quad` and Chinese text; a three-sum inequality with `\limits`; and the chain rule with `\rm`. Unit coverage includes command preservation, scoped roman normalization, rejected placement directives and zero-slot spacing insertion. Browser tests import and edit each equation in React/native, measure spacing widths, and exercise deletion/Undo. Structured parentheses are measured against the enclosed fraction height; matching editor screenshots are inspected.
170
+
171
+ ### Fences, annotations and indexed-root geometry (workspace)
172
+
173
+ 291 unit tests pass. Browser coverage verifies both renderers importing and editing braces, angles, mixed/invisible fences, overset and underset; annotation typing/navigation/deletion/Undo; and the indexed radical meeting the overbar at the same coordinate. The 105-case regression run had one incorrect expected test string for a multiline separator; after correcting the fixture, all 20 wrapping cases passed. The brace/angle symbol-query browser test also passes. The indexed-root screenshot was inspected.
174
+
175
+ ## Latest workspace typography and discovery checks — 2026-09-08
176
+
177
+ - The last recorded unit run passed 327 tests, including catalog parsing/export and arrow suggestions. This documentation update does not constitute a new unit run.
178
+ - Chromium: chemical-layout (2), function-spacing (2), root-geometry (6) and similarity-glyph (2) passed across React/native. The glyph test was updated to the renamed font and rerun separately. Chemical geometry checks cover base/coefficient alignment, subscript gap/offset and editing the subscript.
179
+ - Absolute-focus (2) passed again after removing the focus halo, including visible delimiters and operand replacement. Screenshots were inspected for chemistry and borderless focus.
180
+ - Earlier focused runs covered arrow triggers (4), arrow search/typing/wrapping (22), integral bounds (4), double integrals (4), equation-only cases (2) and down-arrow chemistry (4). These are separate targeted runs, not one full-suite total.
181
+ - Package build passed after the typography changes. Safari, Firefox, Windows, native OS IME, screen-reader behavior and Note's reported inline/dialog issues remain unverified or open. No npm release was made.
182
+
183
+ ## Editor versus KaTeX spacing audit — 2026-09-08
184
+
185
+ The `spacing-audit.spec.ts` Chromium audit imported seven expressions in the rich React demo, verified a KaTeX preview for each exported expression, and captured passive editor DOM beside that preview. The comparison board uses the existing editor styles and an 18px KaTeX container; font metrics differ, so it is a qualitative layout reference, not a pixel-equality test. The board and width measurements are saved in `apps/math-demo/artifacts/spacing-audit/`. Native rendering, inner-slot focus, long conditions and touch hit targets still need their own audit. No production spacing rules were changed in this audit.
186
+
187
+ | Priority | Observed difference | Recommended adjustment |
188
+ | --- | --- | --- |
189
+ | 1 | `pmatrix` sides look bracket-like; the cases brace lacks a clear central cusp | Reuse the scalable physical fence shapes for grid delimiters before tuning whitespace |
190
+ | 1 | A nested fraction retains full-size inner text and becomes disproportionately tall | Introduce a shared, bounded math-size scale for nested fractions/scripts; keep the input and its measuring twin identical |
191
+ | 2 | Combined scripts have more upper/lower separation than the reference | Tighten the script stack and remove slot line-box overhead; test nested scripts and active slots |
192
+ | 2 | Matrix and cases rows have much more vertical space | Reduce row gap/padding while retaining a usable empty-cell target; test tall cells separately |
193
+ | 2 | Vector/hat/overline marks float above the letters | Position each accent against its body rather than retaining one generous top gap |
194
+ | 3 | Sum/product placement is reasonably close but bounds/body gaps remain generous | Tune after script sizing; preserve separate integral and explicit-limits placement rules |
195
+ | 3 | The tall nested fence is largely driven by the fraction/root contents | Fix interior sizing first, then reassess delimiter width and body clearance |
196
+
197
+ For all seven samples, focusing the first empty boundary increased the expression width by exactly 20px (4px passive to 24px active). This measures that boundary only, not arbitrary cursor positions. Evaluate an overlay hit area or a smaller active minimum so focusing does not push the entire formula sideways; do not reduce all empty slots globally.
198
+
199
+ Suggested sequence: grid delimiter shapes → nested-size policy → combined scripts/fraction gaps → matrix rows and accents → boundary focus stability. Acceptance should include passive/active screenshots, empty and populated slots, nested content, pointer access, Tab navigation, typing and Undo in both renderers. KaTeX is a notation/layout reference, while editing still requires visible caret targets.
200
+
201
+ ### Spacing implementation follow-up
202
+
203
+ Shared CSS refinements now address grid fence shapes, grid gaps, fraction/script line boxes, bounded nested fraction sizes, accent offsets and large-operator body gaps. The final import/edit and comparison run passed 80 Chromium cases across React/native; an earlier 11-case run covered chemistry, limits and root geometry. Demo build passed. The refreshed comparison is `comparison-after.png`. First-boundary focus expansion is now 8px instead of 20px in all seven samples. These checks do not establish complete TeX style parity or native OS IME/accessibility coverage.
204
+
205
+ ### Norm fences — 2026-09-08
206
+
207
+ 337 unit tests pass, including norm aliases/canonical round trips, failed-import state preservation, localized/punctuation discovery and range wrapping/Undo. Four Chromium tests pass across rich React/native: nested-fraction norm import, scalable bars, active-slot replacement/Undo, empty-body suggestion insertion and Tab continuation. Active/passive screenshots were compared with the KaTeX preview of the same exported nested fraction. Editing retains extra body clearance for caret targets. Package and demo builds pass; no npm publication was performed.
208
+
209
+ ### Triple and contour integrals — workspace
210
+
211
+ 341 unit tests pass, including nested bodies, explicit limits preservation, localized discovery and failed-placement atomicity. The 95-case Chromium run covers rich React/native imported-slot editing, suggestion insertion, traversal, deletion/Undo and integral geometry. After KaTeX comparison, contour glyphs were changed from system U+222E to an integral stroke plus ring; the final eight-case bounds/edit run passed again. Package/demo builds pass. Broader browser and OS input coverage remains open; no npm release was made.
212
+
213
+ ### Over/under braces — workspace
214
+
215
+ 345 unit tests pass, including bare/annotated import, nested bodies, duplicate annotation rejection, discovery and range wrapping/Undo. In the broad Chromium run, 90 cases passed and an existing overline test encountered a page navigation during a concurrent package rebuild. After the build completed, all ten targeted brace/overline checks passed. Four nested brace import/edit checks also passed separately. Simple and nested brace screenshots were compared with KaTeX, including rich React/native active and passive states. Package/demo builds pass. This is workspace support, not a new npm release.
216
+
217
+ Contour correction: the earlier synthetic-glyph approach was visually incorrect. Ten Chromium regressions now pass, including the reported `\oint_{20}^{20}{x}` in React/native, single-glyph count, absence of pseudo-element drawings, native font slant, side bounds and explicit limits. Screenshots were rechecked against KaTeX.
218
+
219
+ Compact toolbar: two Chromium checks pass for rich React expand/collapse with preserved content/history and hidden-command typing, and native independent toolbar filtering with expansion preserved after insertion. A compact demo screenshot was inspected.
220
+
221
+ ### Six additional accents — workspace
222
+
223
+ 351 unit tests pass. A 25-case Chromium run passes for rich React/native import/edit, suggestion insertion, content-preserving unwrapping/Undo and the KaTeX comparison board. The initial dot typing test selected the existing multiplication-symbol candidate; the corrected test explicitly chooses Dot accent, preserving symbol-first ranking. After final accent clearance tuning, the comparison board passed again and was visually inspected for simple and nested expressions. The image is saved as `apps/math-demo/artifacts/spacing-audit/accents-comparison.png`. Package/demo builds pass; no npm release was made.
224
+
225
+ ### Limit variants and explicit side placement — workspace
226
+
227
+ 362 unit tests pass, including all supported operators with `limits: false`, JSON validation, canonical round trips and localized limit-name discovery. Eleven Chromium cases pass for both renderers: condition/body editing, insertion, deletion/Undo and the KaTeX comparison board. Package/demo builds pass. The comparison is a visual reference rather than pixel parity: KaTeX 0.16.28's operatorname-based liminf preview showed a below-name condition for the explicit nolimits example, while the editor deliberately honors the stored side-placement directive. No placement metadata is discarded to match that preview. Broader browser checks and a direct placement toolbar switch remain open.
228
+
229
+ Fine spacing: 366 unit tests pass. Nine Chromium checks pass across rich React/native for measured spacer widths, insertion, deletion/Undo, continued typing and a KaTeX comparison board. The negative gap preserves adjacent input access and has no painted hit box. Broader TeX glue/style semantics remain out of scope.
230
+
231
+ Limit preview correction: the earlier liminf display mismatch is now resolved in the demo through rendering-only KaTeX macro definitions. Seven Chromium checks pass: both limit names with default/limits/nolimits MathML placement and a refreshed visual comparison. Saved JSON and canonical LaTeX remain unchanged. Hosts using KaTeX 0.16.28 can use the documented macro configuration.
232
+
233
+ ## Explicit size validation — 2026-09-08
234
+
235
+ - Package build and 371 unit tests passed, including four size-command round trips, suggestion insertion and nested explicit styles.
236
+ - Chromium: 8 React/native imported-slot editing cases, 8 typed-preset cases and one KaTeX comparison audit passed. Typed cases assert active input size and final exported source.
237
+ - Compared explicit display/text sizes and nested sizes against KaTeX. The editor keeps its interaction spacing; it does not claim pixel-identical TeX layout. General style declarations remain unsupported.
238
+ - Reference image: `apps/math-demo/artifacts/spacing-audit/explicit-sizes.png`. Publication and wider browser/platform validation remain open.
239
+
240
+ ## Math alphabets — 2026-09-08
241
+
242
+ Package build and 376 unit tests passed. Thirteen Chromium checks passed: six typed-suggestion cases, six imported-slot editing/undo cases across React/native, and one KaTeX comparison audit including nested alphabets and a fraction with a script. Decorative alphabet claims are limited to Latin capitals. The comparison is in `apps/math-demo/artifacts/spacing-audit/math-alphabets.png`. Broader glyph coverage and cross-browser validation remain open.
243
+
244
+ ## Labeled arrows — 2026-09-08
245
+
246
+ Package build and 381 unit tests passed, including label round trips, JSON validation and malformed optional-argument rejection. Nine Chromium checks passed: four typed/width-growth cases, four imported-label edit/undo cases across React/native, and one KaTeX comparison audit. The audit was repeated after fixing arrowhead width. See `apps/math-demo/artifacts/spacing-audit/labeled-arrows.png`. Other extensible arrows and wider browser testing remain open.
247
+
248
+ ## Locale correction and equation* — 2026-09-08
249
+
250
+ Package build and 388 unit tests passed. Built-in locale tests reject misplaced fields, check en/ko parity and verify referenced literal message keys. Four Chromium cases passed: both locales' nine recent suggestion labels and arrow slot labels, plus React/native equation* import/edit/undo. The native fixture uses separate structural slots to match its whole-run text editing model. A KaTeX audit also compared the imported fraction/root equation. Demo build passed. Numbered equations remain unsupported.
251
+
252
+ ## 0.2.0 release verification
253
+
254
+ - Formatting, package type checking, 388 unit tests and all eight packed JavaScript entry points pass. Packed CSS, locale JSON and licensed math fonts are present.
255
+ - The 379-case Chromium suite was reviewed against the current UI. Stale assumptions about expanded toolbars, symbol counts, broad candidate-name matching, focus outlines and suggestion-versus-line shortcuts were updated. Corrected cases were rerun, including the full 20-case wrapping file.
256
+ - Production demo build and generated documentation page/anchor checks pass. This release covers math-editor only. Note inline editing is resolved per the user and other product deployment is outside scope.
257
+
258
+ ## 0.2.1 release verification
259
+
260
+ Formatting, types, 390 unit tests and all eight packed entry points passed. Thirty-nine related Chromium cases passed for keyboard and drag selection, clipboard, wrapping, tokens, brace/cases discovery, preview and bundled locales. Website PNG download/copy checks validate dimensions and nonblank raster pixels. Long-formula fitting and transparent alpha were checked separately. Image generation is a demo dependency, not a library API.
package/dist/core.d.ts CHANGED
@@ -8,4 +8,6 @@ export * from './suggestions.js';
8
8
  export * from './templates.js';
9
9
  export * from './session.js';
10
10
  export * from './i18n.js';
11
+ export * from './latex.js';
12
+ export * from './document-codec.js';
11
13
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAE1B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
package/dist/core.js CHANGED
@@ -8,4 +8,6 @@ export * from './suggestions.js';
8
8
  export * from './templates.js';
9
9
  export * from './session.js';
10
10
  export * from './i18n.js';
11
+ export * from './latex.js';
12
+ export * from './document-codec.js';
11
13
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAE1B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type MathDocument } from './model.js';
2
+ /** Validate persisted JSON before passing it to a renderer. Reject duplicate caret addresses. */
3
+ export declare function parseMathDocument(source: string): MathDocument | undefined;
4
+ //# sourceMappingURL=document-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-codec.d.ts","sourceRoot":"","sources":["../src/document-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAgB,MAAM,YAAY,CAAC;AAG3E,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAgC1E"}
@@ -0,0 +1,37 @@
1
+ import { documentRows } from './model.js';
2
+ import { parseFragment } from './range.js';
3
+ /** Validate persisted JSON before passing it to a renderer. Reject duplicate caret addresses. */
4
+ export function parseMathDocument(source) {
5
+ if (source.length > 200000)
6
+ return;
7
+ try {
8
+ const value = JSON.parse(source);
9
+ if (value?.version !== 1 ||
10
+ !value.root ||
11
+ (value.additionalLines !== undefined && !Array.isArray(value.additionalLines)))
12
+ return;
13
+ const rows = documentRows(value);
14
+ if (!parseFragment(JSON.stringify({ version: 1, rows })))
15
+ return;
16
+ const ids = new Set();
17
+ const unique = (id) => {
18
+ if (ids.has(id))
19
+ return false;
20
+ ids.add(id);
21
+ return true;
22
+ };
23
+ const visit = (row) => unique(row.id) &&
24
+ row.children.every((node) => unique(node.id) && (node.type === 'text' || node.slots.every(visit)));
25
+ if (!rows.every(visit))
26
+ return;
27
+ return {
28
+ version: 1,
29
+ root: value.root,
30
+ ...(value.additionalLines?.length ? { additionalLines: value.additionalLines } : {}),
31
+ };
32
+ }
33
+ catch {
34
+ return;
35
+ }
36
+ }
37
+ //# sourceMappingURL=document-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-codec.js","sourceRoot":"","sources":["../src/document-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmC,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,iGAAiG;AACjG,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM;QAAE,OAAO;IACnC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,IACE,KAAK,EAAE,OAAO,KAAK,CAAC;YACpB,CAAC,KAAK,CAAC,IAAI;YACX,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAE9E,OAAO;QACT,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAAE,OAAO;QACjE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAE;YAC5B,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC9B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,GAAY,EAAW,EAAE,CACtC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACd,GAAG,CAAC,QAAQ,CAAC,KAAK,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAC/E,CAAC;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO;QAC/B,OAAO;YACL,OAAO,EAAE,CAAC;YACV,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Position a fixed portal in viewport coordinates, including transformed modal hosts. */
2
+ export declare function positionMathMenu(menu: HTMLElement, anchor: DOMRect, maxHeight: number): void;
3
+ //# sourceMappingURL=menu-position.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-position.d.ts","sourceRoot":"","sources":["../../src/dom/menu-position.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,QA+CrF"}
@@ -0,0 +1,44 @@
1
+ /** Position a fixed portal in viewport coordinates, including transformed modal hosts. */
2
+ export function positionMathMenu(menu, anchor, maxHeight) {
3
+ const win = menu.ownerDocument.defaultView;
4
+ const bounds = { left: 8, top: 8, right: win.innerWidth - 8, bottom: win.innerHeight - 8 };
5
+ for (let parent = menu.parentElement; parent; parent = parent.parentElement) {
6
+ const style = win.getComputedStyle(parent);
7
+ const dialog = parent.matches('dialog, [role="dialog"]');
8
+ const clipX = dialog || /auto|scroll|hidden|clip/.test(style.overflowX);
9
+ const clipY = dialog || /auto|scroll|hidden|clip/.test(style.overflowY);
10
+ if (!clipX && !clipY)
11
+ continue;
12
+ const rect = parent.getBoundingClientRect();
13
+ if (clipX) {
14
+ bounds.left = Math.max(bounds.left, rect.left + 8);
15
+ bounds.right = Math.min(bounds.right, rect.right - 8);
16
+ }
17
+ if (clipY) {
18
+ bounds.top = Math.max(bounds.top, rect.top + 8);
19
+ bounds.bottom = Math.min(bounds.bottom, rect.bottom - 8);
20
+ }
21
+ }
22
+ // Measure the fixed containing block instead of assuming it is the viewport.
23
+ // A dialog's transform/translate establishes a local origin and may also scale it.
24
+ menu.style.left = '0px';
25
+ menu.style.top = '0px';
26
+ menu.style.maxWidth = '';
27
+ menu.style.maxHeight = `${maxHeight}px`;
28
+ const origin = menu.getBoundingClientRect();
29
+ const scaleX = origin.width / menu.offsetWidth || 1;
30
+ const scaleY = origin.height / menu.offsetHeight || 1;
31
+ menu.style.maxWidth = `${Math.max(0, bounds.right - bounds.left) / scaleX}px`;
32
+ const desiredHeight = Math.min(menu.scrollHeight * scaleY, maxHeight * scaleY);
33
+ const below = Math.max(0, bounds.bottom - anchor.bottom - 4);
34
+ const above = Math.max(0, anchor.top - bounds.top - 4);
35
+ // Choose direction by available space, not candidate count, so typing does not flip the list.
36
+ const placeBelow = below >= Math.min(maxHeight * scaleY, 160) || below >= above;
37
+ menu.style.maxHeight = `${Math.min(desiredHeight, placeBelow ? below : above) / scaleY}px`;
38
+ const size = menu.getBoundingClientRect();
39
+ const left = Math.max(bounds.left, Math.min(anchor.left, bounds.right - size.width));
40
+ const top = Math.max(bounds.top, Math.min(placeBelow ? anchor.bottom + 4 : anchor.top - size.height - 4, bounds.bottom - size.height));
41
+ menu.style.left = `${(left - origin.left) / scaleX}px`;
42
+ menu.style.top = `${(top - origin.top) / scaleY}px`;
43
+ }
44
+ //# sourceMappingURL=menu-position.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-position.js","sourceRoot":"","sources":["../../src/dom/menu-position.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,8 @@ import type { MathSession } from '../session.js';
2
2
  import type { StructureKind } from '../model.js';
3
3
  export interface MathToolbarOptions {
4
4
  kinds?: readonly StructureKind[];
5
+ /** Visible structure buttons before More; defaults to 8. */
6
+ maxItems?: number;
5
7
  onExecute?: () => void;
6
8
  }
7
9
  /** Independently mounted toolbar; the host may instead build any UI around session.execute(). */
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../../src/dom/toolbar.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AACD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,kBAAuB;;EA4CjC"}
1
+ {"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../../src/dom/toolbar.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AACD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,kBAAuB;;EAkEjC"}
@@ -3,6 +3,8 @@ import { translate, mathLocaleDirection } from '../i18n.js';
3
3
  import { mathStructures } from '../suggestions.js';
4
4
  /** Independently mounted toolbar; the host may instead build any UI around session.execute(). */
5
5
  export function mountMathToolbar(host, session, options = {}) {
6
+ let expanded = false;
7
+ const maxItems = Math.max(0, Math.floor(Number.isFinite(options.maxItems) ? options.maxItems : 8));
6
8
  const toolbar = element('div', 'me-tools');
7
9
  host.append(toolbar);
8
10
  const draw = () => {
@@ -11,7 +13,8 @@ export function mountMathToolbar(host, session, options = {}) {
11
13
  toolbar.setAttribute('role', 'toolbar');
12
14
  toolbar.setAttribute('aria-label', t('toolbar.label'));
13
15
  toolbar.dir = mathLocaleDirection(snapshot.locale);
14
- for (const item of mathStructures.filter((item) => !options.kinds || options.kinds.includes(item.kind))) {
16
+ const items = mathStructures.filter((item) => !options.kinds || options.kinds.includes(item.kind));
17
+ for (const item of expanded ? items : items.slice(0, maxItems)) {
15
18
  const button = element('button', '', `${item.glyph} ${t(item.label)}`);
16
19
  button.type = 'button';
17
20
  button.setAttribute('aria-label', t(item.label));
@@ -22,6 +25,18 @@ export function mountMathToolbar(host, session, options = {}) {
22
25
  };
23
26
  toolbar.append(button);
24
27
  }
28
+ if (items.length > maxItems) {
29
+ const toggle = element('button', 'me-toolbar-toggle', t(expanded ? 'toolbar.less' : 'toolbar.more'));
30
+ toggle.type = 'button';
31
+ toggle.setAttribute('aria-expanded', String(expanded));
32
+ toggle.onmousedown = (event) => event.preventDefault();
33
+ toggle.onclick = () => {
34
+ expanded = !expanded;
35
+ draw();
36
+ toolbar.querySelector('[aria-expanded]')?.focus();
37
+ };
38
+ toolbar.append(toggle);
39
+ }
25
40
  for (const type of ['undo', 'redo']) {
26
41
  const button = element('button', '', t(type === 'undo' ? 'history.undo' : 'history.redo'));
27
42
  button.type = 'button';
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/dom/toolbar.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/dom/toolbar.ts"],"names":[],"mappings":"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"}
package/dist/dom.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface DOMMathEditorOptions {
11
11
  locale?: MathLocale;
12
12
  mode?: MathEditorMode;
13
13
  toolbar?: boolean | readonly StructureKind[];
14
+ toolbarMaxItems?: number;
14
15
  showLineNumbers?: boolean;
15
16
  onChange?: (document: MathDocument, latex: string) => void;
16
17
  onExit?: (direction: -1 | 1) => void;
package/dist/dom.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAUL,KAAK,YAAY,EAEjB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAapB,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,aAAa,EAAE,CAAC;IAC7C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACrC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACrC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,KAAK,IAAI,CAAC;IACtE,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,CACJ,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,cAAc,GAAG,UAAU,CAAC,CAAC,GACpF,IAAI,CAAC;IACR,OAAO,IAAI,IAAI,CAAC;CACjB;AACD,qFAAqF;AACrF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CA4kBf"}
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAWL,KAAK,YAAY,EAEjB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAgBpB,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,aAAa,EAAE,CAAC;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACrC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACrC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,KAAK,IAAI,CAAC;IACtE,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,CACJ,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,cAAc,GAAG,UAAU,CAAC,CAAC,GACpF,IAAI,CAAC;IACR,OAAO,IAAI,IAAI,CAAC;CACjB;AACD,qFAAqF;AACrF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAmuBf"}