Repository navigation
[lexical-mark][lexical-website] Documentation Update: Bring the collaboration docs up to date with merged @lexical/y - #9536
Conversation
…boration docs up to date with merged @lexical/y ## Description An audit of the collaboration docs against `main` after the `@lexical/y` stack merged. Every page was already close; what was stale, missing or did not compile: - `y.md`: a Limits subsection, **Open issues**, lists the open `@lexical/y` bugs (#9511 to #9526) with what each one does, so readers know which behaviors are bugs rather than design. The warnings table now lists every `NESTED_FALLBACK_WARNING` reason (it named 2 of 10). The read-only banner example imports `defineExtension` and names its extension, so it compiles. - `y-server.md`: the `'read-only'` `YHeadlessError` cases now include a newer `schemaVersion` and content without a layout record, as the error's own type says. - `comments.md`: the store example (`Y.Map` from `yjs`) only works on Yjs 13; a Yjs 14 version for `@lexical/y` (a shared type's attributes, `getAttr`/`setAttr`/`deleteAttr`) follows it. The limitations list the two open `MarkStateExtension` bugs (#9519, #9491). - `faq.md`: "Initializing EditorState from Yjs Document" points `@lexical/y` users at `readYState`. - `extensions/block-ids.md`: `repairTransforms` says that `YCollabExtension` sets it to `false` and the binding goes read only with `true`. - `@lexical/mark` README: describes `MarkStateExtension` (`isMarkIDShown`, `registerMarkIDsListener`), mark flavors (`defineMarkExtension`) and `MarkNode`, and links the comments guide. ## Changeset `.changeset/mark-readme.md` (`[docs]`, the `@lexical/mark` README ships in the package). The website changes need none. ## Test plan Every TypeScript snippet on the collaboration pages, `extensions/block-ids.md` and the two READMEs was extracted and type-checked against the workspace sources (`tsc`, the website's `tsconfig.json`, with declarations for the names a snippet leaves to the reader such as `config` or `stored`). The Yjs 14 store example was also run against `@y/y` 14.0.0-rc.29 across two documents. ### Before ``` y_md_L284.ts(24,1): error TS2304: Cannot find name 'defineExtension'. comments_md_L283.ts(5,22): error TS2339: Property 'getMap' does not exist on type 'Doc'. (with a @y/y document) ``` ### After ``` $ tsc -p .snip/tsconfig.json --noEmit # only fragments' reader-supplied names remain $ node y14map.mjs true hi true undefined {"attrs":{"c1":{"attrs":{"body":"hi"}}}} $ pnpm -C packages/lexical-website run build # onBrokenAnchors: 'throw' [SUCCESS] Generated static files in "build". ```
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
lexical
@lexical/a11y
@lexical/clipboard
@lexical/code
@lexical/code-core
@lexical/code-prism
@lexical/code-shiki
@lexical/compiler
@lexical/devtools-core
@lexical/dragon
@lexical/eslint-plugin
@lexical/extension
@lexical/fast-check
@lexical/file
@lexical/hashtag
@lexical/headless
@lexical/history
@lexical/html
@lexical/internal
@lexical/link
@lexical/list
@lexical/mark
@lexical/markdown
@lexical/mdast
@lexical/offset
@lexical/overflow
@lexical/plain-text
@lexical/react
@lexical/rich-text
@lexical/selection
@lexical/table
@lexical/tailwind
@lexical/text
@lexical/utils
@lexical/y
@lexical/yjs
commit: |
…es to concurrent typing, drop fixed open issues, leave faq.md to #9547 ## Description Follow-up to the collaboration docs audit, from the integration review of the open `@lexical/y` PRs: - `y.md`, "Edits made by code": the first bullet said a replaced block loses what collaborators type in it at the same time. Tests show that in a line (a paragraph, also one inside a table cell) the typing survives, before the new text and with its own formatting; formatting of the replaced characters does not carry over; only a block stored as a node of its own (a table, a container) loses what was typed in it. The bullet now says so, in the same sentence as the server and block id pages. - `y.md`, "Open issues": drops the lines for the issues that other open PRs fix (#9513, #9515, #9516 and #9526, #9517, #9520, and #9525 from the markerless-line line, which keeps #9524). This PR lands after them. - `comments.md`: the open issues line keeps only #9491. Another open PR fixes #9519 where the composition starts in an update of its own, as a browser's `compositionstart` does; the limitations now say so, and that a composition code starts and writes in one update is still compared as text, which can leave letters added at the end of a mark without its ids. - `faq.md`: this PR no longer changes it. #9547 rewrites the same section with a working `readYState` example. ## Changeset None: website only. ## Test plan ### Before ``` $ grep -n "is lost (see \[Limits\]" packages/lexical-website/docs/collaboration/y.md 660: is lost (see [Limits](#limits)). Lexical records the text edits of an ``` ### After ``` $ npx prettier --check packages/lexical-website/docs/collaboration/*.md All matched files use Prettier code style! $ git diff --stat 0823b74 -- packages/lexical-website/docs/collaboration/faq.md (no changes) $ pnpm -C packages/lexical-website run build # onBrokenAnchors: 'throw' [SUCCESS] Generated static files in "build". ```
…highlighting opens unhighlighted, and list two open issues ## Description The `@lexical/y` Limits named the table plugin as a transform whose pass over an open document writes nothing. A code highlighter behaves the same: code stored without highlighting (a headless seed or `editYState` whose extensions lack `CodePrismExtension` or `CodeShikiExtension`) shows unhighlighted on every client, also on clients that run the highlighter, until a local edit in that code block highlights the whole block and writes it. The "Shapes ... shown as stored" bullet now says so, why (a transform never rewrites what a client read), and the workaround (seed and edit with the clients' extensions). The "Open issues" list also gains #9560 and #9564, two open `@lexical/y` bugs it did not name. ## Test plan ### Before A document seeded with `seedYState` and `CodeExtension` only, bound to an editor with `CodePrismExtension` (either extension order), then one character typed at the end of the code block, compared with a fresh `readYState`: ``` seeded without the highlighter opened: code(text:"const x = 1;") edited: code(code-highlight:"const",code-highlight:" x ",code-highlight:"=",code-highlight:" ",code-highlight:"1",code-highlight:";",code-highlight:" ") fresh: code(code-highlight:"const",code-highlight:" x ",code-highlight:"=",code-highlight:" ",code-highlight:"1",code-highlight:";",code-highlight:" ") seeded with the highlighter opened: code(code-highlight:"const",code-highlight:" x ",code-highlight:"=",code-highlight:" ",code-highlight:"1",code-highlight:";") ``` An editor without collaboration given the same content as JSON shows the highlighted tokens at once. ### After Documentation only. ``` $ prettier --check packages/lexical-website/docs/collaboration/y.md Checking formatting... All matched files use Prettier code style! ```
…t conversion issue among the open @lexical/y issues ## Description Every `@lexical/y` editor runs `NodeStructureExtension`. In such an editor, turning a paragraph inside a container that is itself inside a container (both not shadow roots) into a list removes the outer container and makes no list (#9570). The "Open issues" list now names it. ## Test plan ### Before The repro on main (a box inside a box holding a paragraph, `$insertList('bullet')` at the paragraph, two bound peers and a fresh reader): ``` A test_box[i](paragraph("abc")) | B test_box[i](paragraph("abc")) | fresh test_box[i](paragraph("abc")) ``` ### After Documentation only. ``` $ prettier --check packages/lexical-website/docs/collaboration/y.md Checking formatting... All matched files use Prettier code style! ```
There was a problem hiding this comment.
Thanks for this pass over the @lexical/y and comments docs. I checked each claim against this head, and nearly all of them hold. Three places, though, describe main as it will be once other open PRs merge, so the order in which things land matters.
1. comments.md lines 401-407: IME limitation. The new text says the replaced selection is known when an insertion "starts an input method composition in an update of its own, as the browser's compositionstart does". On this head that isn't the case yet. $applyInsertedTextMarkIDs uses the replaced selection only when the text in its place is in new TextNodes (MarkStateExtension.ts:2007-2012), and an input method writes into the existing node. Retyping the commented cd of abcd as cde:
How cde replaces cd |
Comment id on e |
|---|---|
CONTROLLED_TEXT_INSERTION_COMMAND |
c1 |
| Composition started and written in one update | none |
Composition started in an update of its own (as compositionstart) |
none |
This is #9519, which is still open; #9540 adds the behaviour the new text describes. This PR also removes the #9519 line, so merging it before #9540 would leave the limits promising the opposite of what happens, with the bug listed nowhere. Can this wait for #9540, or keep the previous wording and the #9519 line until #9540 lands?
2. y.md lines 1043-1074: Open issues. #9513, #9515, #9516, #9517, #9520, #9525 and #9526 are still open; their fixes are in #9557, #9559, #9535, #9549, #9539 and #9544. The description says this PR lands after "those fixes". Naming those PRs there would make the merge order explicit.
3. y.md lines 657-663 against y-server.md lines 316-319. The new sentence matches this head: a collaborator's concurrent typing in a replaced paragraph survives before the new text with its own formatting, and in a replaced table it is lost. But the "Edit text in place" bullet in y-server.md still says that the typing "is lost". #9545 updates that bullet. Either carry the sentence over here, or merge the two PRs together.
Nit, y-server.md lines 154-161: the 'read-only' list could also name a node type stored differently from how its class declares it. STORAGE_MISMATCH_WARNING makes the binding read only too.
Also checked on this head:
- The ten
NESTED_FALLBACK_WARNINGreasons matchWarnings.ts. - The banner snippet now compiles.
- The Yjs 14 thread-store snippet type-checks and round-trips between two documents.
- The code-highlighting limit reproduces.
YCollabExtensiondoes setrepairTransforms: false.- The
[docs]changeset passescheck-changesets. - Every API the
@lexical/markREADME names is exported.
| or starts an input method composition in an update of its own, as the | ||
| browser's `compositionstart` does. A composition that code starts and | ||
| writes in one update is compared as text instead, so letters it adds at | ||
| the end of a mark can be left without the mark's ids. Code that replaces a |
There was a problem hiding this comment.
On this head, a composition started in its own update still leaves the added letters without the replaced selection's ids. $applyInsertedTextMarkIDs uses the replaced selection only when the text is in new TextNodes (MarkStateExtension.ts:2007-2012), and an input method writes into the existing node. So retyping the commented cd of abcd as cde leaves e without c1 (#9519). This sentence describes #9540, which is still open. Could this merge after #9540, or keep the previous wording and the #9519 line until it lands?
| ### Open issues | ||
|
|
||
| These are bugs, not intended behavior; each issue has a test that | ||
| reproduces it: |
| delete and an insert. In a line such as a paragraph, what a collaborator | ||
| types at the same time survives but lands before the new text, with its | ||
| own formatting; formatting of the replaced characters does not carry | ||
| over. Replacing a block stored as a node of its own, such as a table, | ||
| deletes what was typed in it (see [Limits](#limits)). Lexical records the text edits of an |
There was a problem hiding this comment.
This matches this head: concurrent typing in a replaced paragraph survives before the new text with its own formatting, and in a replaced table it is lost. But y-server.md:316-319 ("Edit text in place") still says the typing "is lost". #9545 updates that bullet, so either carry this sentence there in this PR or merge the two together.
| record yet: seed the document first), `'read-only'` (a newer version of | ||
| the app's schema wrote to the document, a newer layout, content without a | ||
| layout record, a node type the config does not register, content its | ||
| classes throw on, or a named slot the document cannot store, which the | ||
| binding refuses to write; the error's `warnings` are the |
There was a problem hiding this comment.
Nit: a node type stored differently from how its class declares it (STORAGE_MISMATCH_WARNING) also makes the binding read only, so editYState/readYState throw 'read-only' for it too. It is worth naming here.
There was a problem hiding this comment.
Added in 5913777: a node type stored in a way its class cannot be (STORAGE_MISMATCH_WARNING) is now in the list (the binding sets its status to read only after that warning, and the headless functions refuse a read-only binding).
…ng the server page's read-only causes ## Description The server page lists what makes `editYState` and `readYState` throw a `'read-only'` `YHeadlessError`. A node type stored in a way its class cannot be (`STORAGE_MISMATCH_WARNING`: its declaration changed, or its storage record is malformed) also makes the binding read only (`YBinding` sets its status to `readonly` after warning it), so the headless functions refuse it the same way. It is now in the list. ## Test plan ### Before The list named a newer schema version or layout, content without a layout record, an unregistered node type, content its classes throw on and an unstorable named slot, but not a storage mismatch. ### After ``` $ prettier --check packages/lexical-website/docs/collaboration/y-server.md All matched files use Prettier code style! ```
There was a problem hiding this comment.
Thanks for keeping the @lexical/y and comments docs in step with main, and for the new Merge order section and the storage-mismatch cause in y-server.md.
Every statement checks out against this head except three passages that describe main as it will be once the open PRs in the Merge order section land, so what is left is landing order:
packages/lexical-website/docs/collaboration/comments.mdlines 404-407 (IME limitation) describe #9540. Onmain, a composition started in an update of its own, ascompositionstartdoes, still leaves the added letters without the comment id: retyping the commentedcdofabcdascdeleavesewithout the comment (#9519). The base wording promised this for every composition, so the new wording is narrower, not worse.packages/lexical-website/docs/collaboration/y.mdlines 1043-1074 (Open issues) leave out #9513, #9515, #9516, #9517, #9520, #9525 and #9526, which stay open until #9557, #9559, #9535, #9549, #9539 and #9544 merge.y.mdlines 657-663 matchmain(typing into a replaced paragraph survives before the new text; typing into a replaced table is lost), buty-server.mdlines 317-320 still say the typing is lost until #9545 brings the same sentence there.
Question for maintainers: will this PR be held until #9540, #9545, #9535, #9539, #9544, #9549, #9557 and #9559 have merged? If it may land earlier, a #9519 line in the comments.md limitations, the seven issue lines in y.md, and #9545's sentence in the y-server.md bullet would keep each page accurate in the meantime.
Also checked on this head:
- The new
'read-only'cause holds: a storage record that differs from the class, or is malformed, makesreadYStateandeditYStatethrow'read-only'with aSTORAGE_MISMATCH_WARNING. - The ten
NESTED_FALLBACK_WARNINGreasons matchWarnings.ts. - The banner snippet and the Yjs 14 store example type-check, and the store example syncs between two documents.
- The code-highlighting limit reproduces.
YCollabExtensionsetsrepairTransforms: false.- The
[docs]changeset follows.changeset/README.mdand passescheck-changesets. - Every API the
@lexical/markREADME names is exported. - The website build, with broken-link and broken-anchor checks, passed.
|
Answering the review's question: yes, this PR is held until #9535, #9539, #9544, #9549, #9557 and #9559 have merged (#9540 and #9545 already have), as the description's "Merge order" section says, so each passage you flagged describes |
## Description Brings in main at d61302b. One conflict, in `docs/collaboration/y.md`'s "Edit text in place" bullet: main (#9598) now says what collaborators type into a replaced line survives at the start of the new text (or at its end when typed at the end of the line); this branch still had the older wording that it lands before the new text. The resolution keeps main's wording, which describes main. ## Test plan ``` $ pnpm exec prettier --check <the six changed files> All matched files use Prettier code style! $ pnpm run check-changesets Changeset check passed: 53 pending changeset(s) valid. ```
There was a problem hiding this comment.
Thanks, this looks good. I checked the new statements against the code at this head: both changed TypeScript examples compile (the read-only banner fails on the base with TS2304: Cannot find name 'defineExtension'), the Yjs 14 thread-store example sets and clears orphaned across two @y/y 14.0.0-rc.29 documents, and the new "Code stored without highlighting" limit behaves as written. The suggestions below are optional and non-blocking.
Optional suggestions
-
packages/lexical-website/docs/collaboration/y.md, Open issues (lines 1230-1261).mainhas moved since this branch last merged it:- #9570 was fixed and closed by #9590, which also rewrote the Moves limit in
y.mdto describe the in-place list conversion. The branch merges cleanly, but the merged page would still list #9570 as an open bug; dropping that entry when you mergemainin again keeps the two passages consistent. - Several open
@lexical/ybugs are not listed, thoughmainpins them as expected failures or tracks them inpackages/lexical-y/DECISIONS.md: #9579 (BatchedWrites.test.ts), #9591 (Races.test.ts), #9608 (RemadeTextEnds.test.ts, D76), #9609 (OwnRunRestoreEnd.test.ts, D65), #9599 (D78) and #9603 (D65).
Since the intro tells readers these are the bugs rather than design, consider introducing the list as a selection and linking one that stays current (an issue search for open
[lexical-y]bugs, or the Open table inDECISIONS.md), so it does not need an edit for every new issue. - #9570 was fixed and closed by #9590, which also rewrote the Moves limit in
-
Same subsection, #9511. The intro calls every entry "not intended behavior", while Other races (lines 1225-1228) documents the same race as how the layout behaves, and
DECISIONS.md(D61) keeps it open as "a real trade-off". Dropping "not intended behavior" from the intro, or leaving #9511 to Limits, would remove the contradiction.
The Merge order hold in the description is satisfied: all eight listed pull requests have merged, #9535 last. The description's "Edits made by code" bullet now describes a change that reached main through #9545 rather than this diff, if you want to trim it.
| - Turning a paragraph inside a container that is itself inside a | ||
| container (both not shadow roots) into a list removes the outer | ||
| container and makes no list, in every `@lexical/y` editor (it runs | ||
| `NodeStructureExtension`): | ||
| [#9570](https://github.com/meta/lexical/issues/9570). |
There was a problem hiding this comment.
| These are bugs, not intended behavior; each issue has a test that | ||
| reproduces it: |
There was a problem hiding this comment.
Optional: this list misses open @lexical/y bugs that main pins as expected failures or tracks in packages/lexical-y/DECISIONS.md: #9579, #9591, #9608, #9609, #9599 and #9603. Since the intro presents these as the bugs rather than design, consider introducing the list as a selection and linking one that stays current (an issue search for open [lexical-y] bugs, or the Open table in DECISIONS.md). The intro's "not intended behavior" also covers #9511, which Other races documents as how the layout behaves and DECISIONS.md (D61) keeps open as a trade-off.
Description
An audit of the collaboration docs against
mainafter the@lexical/ystack merged. Every page was already close; what was stale, missing or did not compile:y.md: a Limits subsection, Open issues, lists the@lexical/ybugs still open once the fixes in flight land (Bug: [lexical-y] Two concurrent joins into a code block or heading change its block type #9511, Bug: [lexical-y] Two app versions that store a node type differently and insert its first node at once: one node becomes a paragraph and the room opens read only #9512, Bug: [lexical][lexical-y] An update listener that throws stops the later listeners, so @lexical/y never writes that commit #9514, Bug: [lexical-y] Undoing a link while a collaborator formats part of it keeps the link on its text #9521, Bug: [lexical-y] A line without a marker joins the start of a paragraph a collaborator appends at the same time #9524, Bug: [lexical-y] Undoing a format while a collaborator moves a word into its range leaves it on text typed next to the range #9560, Bug: [lexical-y] A comment spreads onto later words when a client types plain text into it offline and a collaborator's delete drops the null that ended it #9564, and the list conversion issue Bug: [lexical-list] $insertList on a paragraph inside a nested container drops the outer container and makes no list when NodeStructureExtension runs #9570 that every@lexical/yeditor has throughNodeStructureExtension) with what each one does, so readers know which behaviors are bugs rather than design. This PR lands after those fixes. The "Shapes ... shown as stored" limit also says that code stored without highlighting (a headless seed without the highlighter) opens unhighlighted until a local edit in that code block, and to seed with the clients' extensions. The warnings table now lists everyNESTED_FALLBACK_WARNINGreason (it named 2 of 10). The read-only banner example importsdefineExtensionand names its extension, so it compiles.y-server.md: the'read-only'YHeadlessErrorcases now include a newerschemaVersion, content without a layout record and a node type stored in a way its class cannot be (STORAGE_MISMATCH_WARNING), as the error's own type and the binding say.comments.md: the store example (Y.Mapfromyjs) only works on Yjs 13; a Yjs 14 version for@lexical/y(a shared type's attributes,getAttr/setAttr/deleteAttr) follows it. The limitations list the openMarkStateExtensionbug Bug: [lexical-mark] $addMarkID over part of a code highlight token marks nothing, or only part of the range #9491, and say that the selection an input method composition replaces is known only when the composition starts in an update of its own, as a browser'scompositionstartdoes.y.md, "Edits made by code": replacing a block in a line keeps what a collaborator types at the same time (before the new text, with its own formatting; formatting of the replaced characters does not carry over); only a block stored as a node of its own loses it. The same sentence is on the server and block id pages ([lexical-website] Documentation Update: Show agent edits by block id on a server that check their targets and edit text in place #9545).faq.mdis not changed here: [lexical-website] Documentation Update: Say which collaboration pages are about @lexical/yjs, and point to the @lexical/y equivalents #9547 rewrites the same section with a workingreadYStateexample, which replaces this PR's earlier hunk.extensions/block-ids.md:repairTransformssays thatYCollabExtensionsets it tofalseand the binding goes read only withtrue.@lexical/markREADME: describesMarkStateExtension(isMarkIDShown,registerMarkIDsListener), mark flavors (defineMarkExtension) andMarkNode, and links the comments guide.Merge order
These pages describe
mainonce the following open pull requests have landed, so merge this one after them:comments.mdlimitation about the selection an input method composition replaces describes [lexical-mark] Bug Fix: Give text an input method composes over a selection the ids all of the replaced text had #9540's behavior, and this PR drops the Bug: [lexical-mark] An IME replacement of a commented suffix leaves the new letters without the comment #9519 line. Merged before [lexical-mark] Bug Fix: Give text an input method composes over a selection the ids all of the replaced text had #9540, the page would promise what does not happen yet.y.mdsentence on replacing a block pairs with [lexical-website] Documentation Update: Show agent edits by block id on a server that check their targets and edit text in place #9545's server-page bullet ("Edit text in place"), which still says the typing is lost until [lexical-website] Documentation Update: Show agent edits by block id on a server that check their targets and edit text in place #9545 lands. Merge the two together, or [lexical-website] Documentation Update: Show agent edits by block id on a server that check their targets and edit text in place #9545 first.Changeset
.changeset/mark-readme.md([docs], the@lexical/markREADME ships in the package). The website changes need none.Test plan
Every TypeScript snippet on the collaboration pages,
extensions/block-ids.mdand the two READMEs was extracted and type-checked against the workspace sources (tsc, the website'stsconfig.json, with declarations for the names a snippet leaves to the reader such asconfigorstored). The Yjs 14 store example was also run against@y/y14.0.0-rc.29 across two documents.Before
After