feat: add BlockPathMap with incremental updates#2336
Draft
christianhg wants to merge 3 commits intomainfrom
Draft
feat: add BlockPathMap with incremental updates#2336christianhg wants to merge 3 commits intomainfrom
christianhg wants to merge 3 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: b83aa6f The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📦 Bundle Stats —
|
| Metric | Value | vs main (be4d3b8) |
|---|---|---|
| Internal (raw) | 820.5 KB | +9.9 KB, +1.2% |
| Internal (gzip) | 154.1 KB | +2.6 KB, +1.7% |
| Bundled (raw) | 1.43 MB | +10.1 KB, +0.7% |
| Bundled (gzip) | 317.0 KB | +2.7 KB, +0.8% |
| Import time | 104ms | -0ms, -0.5% |
@portabletext/editor/behaviors
| Metric | Value | vs main (be4d3b8) |
|---|---|---|
| Internal (raw) | 467 B | - |
| Internal (gzip) | 207 B | - |
| Bundled (raw) | 424 B | - |
| Bundled (gzip) | 171 B | - |
| Import time | 6ms | -0ms, -1.4% |
@portabletext/editor/plugins
| Metric | Value | vs main (be4d3b8) |
|---|---|---|
| Internal (raw) | 2.5 KB | - |
| Internal (gzip) | 910 B | - |
| Bundled (raw) | 2.3 KB | - |
| Bundled (gzip) | 839 B | - |
| Import time | 12ms | -0ms, -2.1% |
@portabletext/editor/selectors
| Metric | Value | vs main (be4d3b8) |
|---|---|---|
| Internal (raw) | 60.2 KB | - |
| Internal (gzip) | 9.4 KB | - |
| Bundled (raw) | 56.7 KB | - |
| Bundled (gzip) | 8.6 KB | - |
| Import time | 10ms | -0ms, -4.5% |
@portabletext/editor/utils
| Metric | Value | vs main (be4d3b8) |
|---|---|---|
| Internal (raw) | 24.2 KB | - |
| Internal (gzip) | 4.7 KB | - |
| Bundled (raw) | 22.2 KB | - |
| Bundled (gzip) | 4.4 KB | - |
| Import time | 10ms | +0ms, +1.6% |
Details
- Import time regressions over 10% are flagged with
⚠️ - Treemap artifacts are attached to the CI run for detailed size analysis
- Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
96b4f53 to
e7fd100
Compare
e7fd100 to
a2509cb
Compare
…d discovery Rewrite traversal internals to use BlockPathMap for O(1) position resolution instead of findIndex scans. Replace duck-typing container field discovery with schema-driven lookup via schema.containers. Four-layer navigation stack: - Map: O(1) position via blockPathMap.get(keyPath) - Arithmetic: O(1) sibling access via index increment/decrement - Index walk: O(depth) tree walk using field names + positional indices - Schema: O(1) field names via schema.containers.find() Extend BlockPathMap.rebuild() to accept an optional schema parameter for recursive container indexing. Pass schema through createTestSnapshot. Add containers to test schema definitions (table, row, cell). All 83 traversal tests pass unchanged - same inputs, same outputs, map-connected internals.
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.
Adds
BlockPathMap- a data structure that maps key-based paths to positional paths with O(1) lookup and incremental updates on structural operations. Text edits and selection changes are zero-cost (early return).On top of the map, 12 traversal utility functions give behavior authors efficient navigation of nested document structures. The traversal utils use the map for O(1) position resolution, then walk the value tree by positional index - O(depth) per navigation, where depth is 2-5 for realistic documents.
Container field discovery is schema-driven:
schema.containerstells us which fields hold child blocks, replacing the duck-typing approach of scanningObject.entries. This cherry-picks the container schema type fromfeat/containersto make it available here.Navigation stack
Each traversal operation uses four layers:
blockPathMap.get(keyPath)schema.containers.find()BlockPathMap
get(keyPath)/has(keyPath)/getIndex(keyPath)- O(1) lookupsrebuild(value, schema?)- full rebuild, recurses into containers when schema providedapplyOperation(op)- incremental updates for insert, remove, split, merge, move, set_nodetoBlockIndexMap()- backward-compatibleMap<string, number>for existing consumersTraversal utils
Structural navigation:
getNode,getParent,getChildren,getNextSibling,getPrevSibling,getAncestorsCursor-order navigation:
getNextBlock,getPrevBlock(depth-first pre-order, skips containers, returns only leaf blocks)Convenience:
isNested,getDepth,isDescendantOf,getContainingContainerTests
129 tests total: 46 for BlockPathMap (including deep structure performance tests on 5,100 entries) and 83 for traversal utils on a 4-level deep document (table, row, cell, text/image). All 8 cross-boundary scenarios tested in both directions.
Performance verified: build 5,100 entries in 42ms, lookup 0.003ms, insert 0.008ms, getNextSibling 0.004ms.