research: PT tree as single source of truth#2221
Draft
christianhg wants to merge 6 commits intomainfrom
Draft
Conversation
Vendor `slate@0.120.0`, `slate-dom@0.119.0`, and `slate-react@0.120.0` source from github.com/ianstormtaylor/slate (tag: slate@0.120.0). Pure copy of src/ directories — no modifications, no git history. packages/editor/src/slate/ — 118 files (slate core) packages/editor/src/slate-dom/ — 14 files (DOM integration) packages/editor/src/slate-react/ — 40 files (React bindings)
Rewire all bare 'slate', 'slate-dom', 'slate-react' imports to relative paths. Fix module augmentation (declare module '../slate/index' instead of 'slate'). Remove slate/slate-dom/slate-react npm dependencies, add their transitive deps (direction, is-hotkey, lodash, etc.). Fix 583 TypeScript errors from vendored source hitting PTE's strict tsconfig (@sanity/tsconfig strictest): Structural fixes: - Widen DOMEditor/ReactEditor params to Editor (resolves CustomTypes) - withDOM/withReact generic: <T extends BaseEditor> → <T extends Editor> - Remove vendored CustomTypes augmentation (PTE's types/slate.ts is source) - Convert enum to const object (erasableSyntaxOnly) - Cast create-editor.ts delegates through any (incremental object build) Mechanical fixes: - verbatimModuleSyntax: type-only re-exports (biome --fix) - erasableSyntaxOnly: angle bracket → as assertions, import aliases - noUncheckedIndexedAccess: non-null assertions on bounded array access - Unused variables prefixed with _ - override keyword on React lifecycle methods - JSX namespace imports for React 19 - React 19 ref types (RefObject<T | null>, useRef(undefined)) Lint fixes: - Rename String component to SlateString (no shadow global) - Block statements for single-line ifs - Explicit types for uninitialized let declarations - biome-ignore for Slate upstream patterns (hooks in conditionals, assignment in expressions, non-null after optional chain) All 317 unit tests pass. Zero type errors. Zero lint errors.
The vendored Slate source files are now raw TypeScript compiled alongside PTE, which means the React Compiler babel plugin transforms them. Slate's components use manual React.memo with custom equality functions that the React Compiler interferes with, causing incorrect re-render optimization (skipping renders that should happen). Exclude src/slate/, src/slate-dom/, and src/slate-react/ from @vitejs/plugin-react so the React Compiler doesn't process them. esbuild still handles JSX transformation for these files.
lodash is CJS-only and doesn't resolve under Node's ESM module resolution. Since the editor package is "type": "module", downstream consumers running tests in Node (e.g. Vitest) fail with "Cannot find module 'lodash/debounce'". Replaces the two lodash imports from vendored Slate with minimal inline implementations and removes lodash from dependencies.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
ef2f7b9 to
5b7ee00
Compare
5651173 to
5b8d72a
Compare
5b8d72a to
55b7c12
Compare
55b7c12 to
c863b05
Compare
74b662a to
ebdccf1
Compare
ebdccf1 to
4dd271a
Compare
4dd271a to
126a26e
Compare
126a26e to
704965b
Compare
704965b to
a133c68
Compare
a133c68 to
05cee0b
Compare
Remove the Slate translation layer for void elements (block objects and
inline objects). Previously, toSlateBlock wrapped void element properties
in a 'value' object, added '__inline' markers, and inserted synthetic
'children' arrays with void-child text nodes. fromSlateBlock reversed
this on the way out.
Now void elements are stored directly as PT-shaped data in the Slate
tree. A block object like {_type: 'image', _key: 'abc', src: '...'}
exists in editor.children exactly as-is, with no children property.
Changes across three layers:
Vendored Slate (20 files):
- Element.isElement() uses _type string check instead of children array
- BaseElement.children is optional
- Node.first/last/nodes/string/child/children guard against missing children
- Editor.point() synthesizes {path, offset: 0} for childless voids
- normalizeNode skips void elements entirely
- Transforms handle optional children defensively
- Void rendering synthesizes a virtual text node at render time only
PTE translation layer (12 files):
- toSlateBlock no longer adds children/value/__inline to voids
- fromSlateBlock no longer strips children/value from voids
- apply-operation-to-portable-text strips children from Elements directly
- operation-to-patches generates patches from node properties directly
- applyPatch applies patches to nodes directly (no value wrapper)
- operation.insert.child creates inline objects without children
- Removed VOID_CHILD_KEY usage from sync-machine
- Fixed set_node handler to guard children in text block property deletion
Rendering (3 files):
- element.tsx synthesizes virtual {text: ''} for void spacer rendering
- use-children.tsx uses editor.isTextSpan() for render branching
- schema plugin uses schema-only isInline check (no __inline marker)
05cee0b to
a6b5e93
Compare
3a640a2 to
2907698
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Research: Making the PT tree the single source of truth
Exploration branch for understanding what it takes to make
editor.childrenhold PT-shaped data directly, eliminating the dual-tree architecture.Findings so far
See
research/00-structural-gaps.mdfor the full analysis.10 structural gaps identified. Two genuinely hard problems:
Status
Active research - commits represent exploration, not production code.