@matrajs/mcp 1.0.0 → 1.0.2
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/docs/benchmarks-full.md +12 -11
- package/docs/changelog.md +61 -0
- package/docs/contributing.md +3 -0
- package/docs/docs-benchmarks.md +1 -1
- package/docs/engine.md +19 -2
- package/docs/readme.md +3 -2
- package/package.json +1 -1
package/docs/benchmarks-full.md
CHANGED
|
@@ -9,10 +9,10 @@ minified, gzipped:
|
|
|
9
9
|
|
|
10
10
|
| | minified | gzipped |
|
|
11
11
|
|---|---|---|
|
|
12
|
-
| **Matra** |
|
|
12
|
+
| **Matra** | 94.6 kB | **31 kB** |
|
|
13
13
|
| Tiptap 3.30 | 370.5 kB | 117.2 kB |
|
|
14
14
|
|
|
15
|
-
**3.
|
|
15
|
+
**3.8× smaller.** Matra has no runtime dependencies; Tiptap brings ProseMirror,
|
|
16
16
|
which is 51 packages in `node_modules`. The figure was 25 kB at 0.16; 1.0
|
|
17
17
|
spent 3.6 kB on the engine doing more — attributes one extension adds to
|
|
18
18
|
another's nodes, paste and drop hooks, files and text dropped from outside,
|
|
@@ -22,21 +22,22 @@ every one of those is on the runtime side of this file.
|
|
|
22
22
|
|
|
23
23
|
## Speed, in a browser
|
|
24
24
|
|
|
25
|
-
Four editors mounted in the same page, in the same run, in
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
Four editors mounted in the same page, in the same run, in Chrome 152 on
|
|
26
|
+
2026-09-05 — Matra 1.0.1 against Tiptap 3.31, Lexical 0.50 and Slate 0.126.
|
|
27
|
+
Each cell is the median of three runs of a median of seven samples.
|
|
28
|
+
Milliseconds, lower is better. `bench/browser` builds and runs this.
|
|
28
29
|
|
|
29
30
|
**No editor** is the same paragraphs built by hand into a `contenteditable`
|
|
30
31
|
div, with nothing else in the page — the floor none of these can go under.
|
|
31
32
|
|
|
32
33
|
| operation | No editor | Matra | Tiptap | Lexical | Slate |
|
|
33
34
|
|---|---|---|---|---|---|
|
|
34
|
-
| parse a document, 2000 ¶ | — | **
|
|
35
|
-
| `getHTML()`, 2000 ¶ | — | **
|
|
36
|
-
| keystroke, 200 ¶ | — | **0.
|
|
37
|
-
| keystroke, 2000 ¶ | — | **0.
|
|
38
|
-
| mount + first render, 200 ¶ | 1.
|
|
39
|
-
| mount + first render, 2000 ¶ |
|
|
35
|
+
| parse a document, 2000 ¶ | — | **2.2** | 8.1 | 35.8 | — |
|
|
36
|
+
| `getHTML()`, 2000 ¶ | — | **0.3** | 1.7 | 5.3 | — |
|
|
37
|
+
| keystroke, 200 ¶ | — | **0.073** | 0.158 | 0.102 | — |
|
|
38
|
+
| keystroke, 2000 ¶ | — | **0.480** | 0.622 | 0.547 | — |
|
|
39
|
+
| mount + first render, 200 ¶ | 1.0 | **1.2** | 4.6 | 2.3 | 5.0 |
|
|
40
|
+
| mount + first render, 2000 ¶ | 12.2 | **14.6** | 34.1 | 21.6 | 50.2 |
|
|
40
41
|
|
|
41
42
|
**Absolute milliseconds only mean anything within one run.** Same harness, same
|
|
42
43
|
browser, a different day: Lexical parsed the same document in 34.7 ms one week
|
package/docs/changelog.md
CHANGED
|
@@ -2,6 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
All packages share one version number and are released together.
|
|
4
4
|
|
|
5
|
+
## 1.0.2 — 2026-09-05
|
|
6
|
+
|
|
7
|
+
**Solid mounts.** A Solid ref runs when its element is made, before it is in
|
|
8
|
+
the page — and an element cloned from a template does not even belong to the
|
|
9
|
+
page's document yet. The editor was mounted on it anyway, so the drag handle
|
|
10
|
+
had no body to go in and the mount threw. `createMatra` now mounts once the
|
|
11
|
+
element is in place, and the drag handle is built on the first mouse move
|
|
12
|
+
when there is no body to put it in at mount. Found by running the install
|
|
13
|
+
matrix's Solid app in a real Chrome: happy-dom gives cloned elements a
|
|
14
|
+
document, so the DOM checks had passed.
|
|
15
|
+
|
|
16
|
+
**The browser benchmark, rerun.** Matra 1.0.1 against Tiptap 3.31, Lexical
|
|
17
|
+
0.50 and Slate 0.126 in Chrome 152, all four mounted in one page, the median
|
|
18
|
+
of three runs. Matra leads every row; the tables in `BENCHMARKS.md`, on the
|
|
19
|
+
landing page and on the benchmarks page carry the new figures.
|
|
20
|
+
|
|
21
|
+
## 1.0.1 — 2026-09-05
|
|
22
|
+
|
|
23
|
+
Three bugs a person meets in the first minute, found by driving every
|
|
24
|
+
extension through the built package in every framework, and the harness that
|
|
25
|
+
found them.
|
|
26
|
+
|
|
27
|
+
**The caret stays put through a change of structure.** Select a word, press
|
|
28
|
+
the heading button, press bold: the word is bold. Press Tab in a list item:
|
|
29
|
+
the caret is still in the word it was in. Both failed, because a structural
|
|
30
|
+
change — a paragraph made a heading, blocks wrapped in a list or a quote, an
|
|
31
|
+
item nested or lifted, a block split — was a plain replacement whose position
|
|
32
|
+
map sent every position inside it to the end. A replace step can now carry
|
|
33
|
+
the finer story (`[start, oldSize, newSize]` triples over the tokens that
|
|
34
|
+
actually moved), `Transform.rebuild` writes it from the runs of content an
|
|
35
|
+
operation keeps in place, and every structural operation in the engine uses
|
|
36
|
+
it. Carets, markers, decorations and collaborators' positions all follow.
|
|
37
|
+
The JSON is backwards compatible: a 1.0.0 client applies the same
|
|
38
|
+
replacement and maps the old, coarser way.
|
|
39
|
+
|
|
40
|
+
**The list button works.** Toggling a bullet, ordered or task list off did
|
|
41
|
+
nothing at all: there was no wrapper to lift a paragraph out of, so the
|
|
42
|
+
command was refused. Turning two selected paragraphs into a list made one
|
|
43
|
+
item holding both. The three toggles now share one command: outside a list
|
|
44
|
+
the selected blocks become a list, one item each; in a list of that kind the
|
|
45
|
+
selected items leave it, one level out when nested and out to plain blocks at
|
|
46
|
+
the top; in a list of another kind the list changes kind where it stands.
|
|
47
|
+
Shift-Tab on a top-level item leaves the list the same way.
|
|
48
|
+
|
|
49
|
+
**What is drawn on an element is what the document says.** A node
|
|
50
|
+
decoration — the focus class, a search highlight — whose whole range an edit
|
|
51
|
+
replaced was forgotten by the renderer's comparison, so the element it was
|
|
52
|
+
drawn on was patched and kept its class: after `setContent` two paragraphs
|
|
53
|
+
could both claim the caret. The renderer now remembers what it drew on each
|
|
54
|
+
element and inside it, and compares against that.
|
|
55
|
+
|
|
56
|
+
**`pnpm exercise`.** Every extension the package exports, built into one
|
|
57
|
+
editor and driven the way a person drives it — every command run, every
|
|
58
|
+
input rule typed, paste pasted, menus waited for — against the built package
|
|
59
|
+
in a DOM. The install matrix runs the same file inside each of the five
|
|
60
|
+
framework apps, so a framework proves three things at once: the package
|
|
61
|
+
installs, every extension works in it, and the binding relays what happened.
|
|
62
|
+
CI runs both.
|
|
63
|
+
|
|
64
|
+
**Bundle.** The starter kit is 31 kB gzipped, from 30. The budget is 32.
|
|
65
|
+
|
|
5
66
|
## 1.0.0 — 2026-09-04
|
|
6
67
|
|
|
7
68
|
The engine got faster everywhere it was measured, thirty-six extensions
|
package/docs/contributing.md
CHANGED
|
@@ -25,6 +25,9 @@ pnpm build # tsup, all packages
|
|
|
25
25
|
|
|
26
26
|
CI runs those plus `pnpm size`, `pnpm bench:check`, `pnpm links`,
|
|
27
27
|
`pnpm wiring`, `pnpm packaging`, `pnpm facts --check` and, in its own job,
|
|
28
|
+
`pnpm exercise` — every extension driven through the built package: every
|
|
29
|
+
command run, every input rule typed, paste pasted, in a DOM.
|
|
30
|
+
|
|
28
31
|
`pnpm install:matrix` — every package packed and installed with plain npm
|
|
29
32
|
into a fresh React, Vue, Svelte, Solid and vanilla Vite app, built and run.
|
|
30
33
|
Running the first four locally catches almost everything. Run the benchmark
|
package/docs/docs-benchmarks.md
CHANGED
|
@@ -6,7 +6,7 @@ Every figure on the landing page comes from one run of one harness with all four
|
|
|
6
6
|
|
|
7
7
|
## Method
|
|
8
8
|
|
|
9
|
-
-
|
|
9
|
+
- Chrome 152, one page, one run · all four editors mounted side by side · Matra 1.0.1, Tiptap 3.31, Lexical 0.50, Slate 0.126, on 2026-09-05.
|
|
10
10
|
|
|
11
11
|
- Median of seven samples, after five warm-up rounds.
|
|
12
12
|
|
package/docs/engine.md
CHANGED
|
@@ -49,7 +49,7 @@ honest:
|
|
|
49
49
|
| Phase | Layer | Lines | gz | Status |
|
|
50
50
|
|---|---|---|---|---|
|
|
51
51
|
| 1 | keymap, input rules, history, list commands | ~1,700 | 21 kB | **done** |
|
|
52
|
-
| 2 | model — nodes, marks, fragments, schema, content expressions, DOM parse/serialize | ~3,500 |
|
|
52
|
+
| 2 | model — nodes, marks, fragments, schema, content expressions, DOM parse/serialize | ~3,500 | 31 kB | **done** |
|
|
53
53
|
| 3 | transform — steps, position mapping, rebasing | ~2,200 | 19 kB | **done** |
|
|
54
54
|
| 4 | state — transactions, selection, plugins | ~1,000 | 9 kB | **done** |
|
|
55
55
|
| 5 | view — contenteditable, IME, selection sync | ~6,000 | 59 kB | **done** |
|
|
@@ -177,9 +177,26 @@ user is the last row: an app ships a fraction of what it did, because nothing
|
|
|
177
177
|
is pulled in that the editor does not use.
|
|
178
178
|
|
|
179
179
|
Extensions have landed since, so that last number is not today's. The current
|
|
180
|
-
figure is whatever `pnpm size` prints — **
|
|
180
|
+
figure is whatever `pnpm size` prints — **31 kB** for the starter kit as of
|
|
181
181
|
1.0 — and it is checked in CI rather than quoted from here.
|
|
182
182
|
|
|
183
|
+
## What 1.0.1 changed underneath
|
|
184
|
+
|
|
185
|
+
- **A replace step can say what it kept.** `ReplaceStep` takes optional
|
|
186
|
+
`ranges` — `[start, oldSize, newSize]` triples over the old document — and
|
|
187
|
+
its map tells that story instead of treating the whole range as gone.
|
|
188
|
+
`Transform.rebuild(from, to, content, kept)` derives the triples from the
|
|
189
|
+
runs of content an operation leaves in place. Retyping a block, wrapping,
|
|
190
|
+
lifting, splitting, nesting and un-nesting list items all go through it,
|
|
191
|
+
which is why a caret now survives every one of them.
|
|
192
|
+
- **Lists are one command.** `toggleList` in `list-commands.ts` wraps blocks
|
|
193
|
+
one item each, takes items out of a top-level list, outdents from a nested
|
|
194
|
+
one, and changes a list's kind in place.
|
|
195
|
+
- **The renderer remembers what it drew.** Two weak maps — node decorations
|
|
196
|
+
written onto an element, decorations drawn inside a content element — are
|
|
197
|
+
what a patch is compared against, rather than last render's set mapped
|
|
198
|
+
through the edit, which loses a decoration whose range the edit replaced.
|
|
199
|
+
|
|
183
200
|
## What 1.0 changed underneath
|
|
184
201
|
|
|
185
202
|
Measured first, then changed; the numbers are in BENCHMARKS.md. The shape of
|
package/docs/readme.md
CHANGED
|
@@ -442,6 +442,7 @@ pnpm bench:check # the performance ratchet, against the recorded baseline
|
|
|
442
442
|
pnpm links # no dead internal links on the site
|
|
443
443
|
pnpm packaging # every built package imports and requires (run after build)
|
|
444
444
|
pnpm wiring # every script on the site finds the markup it asks for
|
|
445
|
+
pnpm exercise # drive every extension through the built package in a DOM: every command, rule and paste
|
|
445
446
|
pnpm install:matrix # pack every package, npm-install it into fresh Vite apps for each framework, build and run them
|
|
446
447
|
pnpm facts # the counts the site prints — tests, adversarial tests, extensions
|
|
447
448
|
```
|
|
@@ -454,7 +455,7 @@ mapping, editor state and the editable view are written from scratch, with
|
|
|
454
455
|
package is installed with plain npm into a fresh React, Vue, Svelte, Solid
|
|
455
456
|
and vanilla Vite app and built there before a release (`pnpm install:matrix`).
|
|
456
457
|
|
|
457
|
-
An app on the starter kit bundles **
|
|
458
|
+
An app on the starter kit bundles **31 kB gzipped**, because nothing arrives
|
|
458
459
|
that the editor does not use — seventy-nine extensions ship in the package
|
|
459
460
|
and none of them is in the bundle until it is in the array. The whole ladder,
|
|
460
461
|
from an empty extension array upwards, is measured by `pnpm size` and checked
|
|
@@ -547,7 +548,7 @@ what the numbers are not.
|
|
|
547
548
|
|
|
548
549
|
| | Matra | Tiptap | Lexical | Slate |
|
|
549
550
|
|---|---|---|---|---|
|
|
550
|
-
| Bundle, gzipped | **
|
|
551
|
+
| Bundle, gzipped | **31 kB** | 117 kB | ~35 kB | ~50 kB |
|
|
551
552
|
| Runtime dependencies | **0** | 51 packages | few | several |
|
|
552
553
|
| Engine types in your code | **none** | ProseMirror | Lexical | Slate |
|
|
553
554
|
| Command types | **inferred** | module augmentation | manual | manual |
|
package/package.json
CHANGED