@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.
@@ -9,10 +9,10 @@ minified, gzipped:
9
9
 
10
10
  | | minified | gzipped |
11
11
  |---|---|---|
12
- | **Matra** | 92.2 kB | **30 kB** |
12
+ | **Matra** | 94.6 kB | **31 kB** |
13
13
  | Tiptap 3.30 | 370.5 kB | 117.2 kB |
14
14
 
15
- **3.9× smaller.** Matra has no runtime dependencies; Tiptap brings ProseMirror,
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 WebKit. Each cell is
26
- the median of three runs of a median of seven samples. Milliseconds, lower is
27
- better. `bench/browser` builds and runs this.
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 ¶ | — | **8.3** | 15.6 | 77.6 | — |
35
- | `getHTML()`, 2000 ¶ | — | **1.5** | 3.6 | 7.1 | — |
36
- | keystroke, 200 ¶ | — | **0.127** | 0.275 | 0.197 | — |
37
- | keystroke, 2000 ¶ | — | **0.847** | 1.188 | 1.160 | — |
38
- | mount + first render, 200 ¶ | 1.1 | **2.0** | 4.3 | 3.2 | 8.0 |
39
- | mount + first render, 2000 ¶ | 10.9 | **22.1** | 37.7 | 26.0 | 93.0 |
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
@@ -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
@@ -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
- - WebKit, one page, one run · all four editors mounted side by side.
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 | 30 kB | **done** |
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 — **30 kB** for the starter kit as of
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 **30 kB gzipped**, because nothing arrives
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 | **30 kB** | 117 kB | ~35 kB | ~50 kB |
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matrajs/mcp",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "The Matra documentation as a Model Context Protocol server, so any AI tool can read it. Zero dependencies.",
5
5
  "license": "MIT",
6
6
  "author": "Nahim Hossain Shohan",