Implement split block API#141
Conversation
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟢 | Statements | 96.43% | 27/28 |
| 🟢 | Branches | 86.96% | 20/23 |
| 🟢 | Functions | 100% | 5/5 |
| 🟢 | Lines | 96.43% | 27/28 |
Test suite run success
11 tests passing in 2 suites.
Report generated by 🧪jest coverage report action from 0d7d9d8
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟢 | Statements | 100% | 171/171 |
| 🟢 | Branches | 96.97% (-3.03% 🔻) |
64/66 |
| 🟢 | Functions | 100% | 33/33 |
| 🟢 | Lines | 100% | 160/160 |
Show new covered files 🐣
St.❔ |
File | Statements | Branches | Functions | Lines |
|---|---|---|---|---|---|
| 🟢 | api/BlocksAPI.ts | 100% | 100% | 100% | 100% |
Show files with reduced coverage 🔻
St.❔ |
File | Statements | Branches | Functions | Lines |
|---|---|---|---|---|---|
| 🟢 | ... / BlockManager.ts |
100% | 94.44% (-5.56% 🔻) |
100% | 100% |
Test suite run success
103 tests passing in 7 suites.
Report generated by 🧪jest coverage report action from 0d7d9d8
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟢 | Statements | 99.71% (-0.08% 🔻) |
1043/1046 |
| 🟢 | Branches | 98.43% (-0.55% 🔻) |
314/319 |
| 🟢 | Functions | 98.39% (+0.94% 🔼) |
244/248 |
| 🟢 | Lines | 99.7% (-0.09% 🔻) |
1001/1004 |
Show new covered files 🐣
St.❔ |
File | Statements | Branches | Functions | Lines |
|---|---|---|---|---|---|
| 🟢 | utils/textUtils.ts | 100% | 100% | 100% | 100% |
Show files with reduced coverage 🔻
St.❔ |
File | Statements | Branches | Functions | Lines |
|---|---|---|---|---|---|
| 🟢 | ... / index.ts |
99.4% (-0.6% 🔻) |
95.83% (-4.17% 🔻) |
97.37% (+5.7% 🔼) |
99.38% (-0.62% 🔻) |
Test suite run success
562 tests passing in 26 suites.
Report generated by 🧪jest coverage report action from 0d7d9d8
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟡 | Statements | 70.97% | 22/31 |
| 🔴 | Branches | 20% | 1/5 |
| 🟡 | Functions | 75% | 6/8 |
| 🟡 | Lines | 68.97% | 20/29 |
Test suite run success
4 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0d7d9d8
|
⏭️ No files to mutate for |
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🟢 | Statements | 92.51% | 358/387 |
| 🟢 | Branches | 85.51% | 118/138 |
| 🟢 | Functions | 98.15% | 53/54 |
| 🟢 | Lines | 92.41% | 353/382 |
Test suite run success
117 tests passing in 7 suites.
Report generated by 🧪jest coverage report action from 0d7d9d8
|
⏭️ No files to mutate for |
|
⏭️ No files to mutate for |
There was a problem hiding this comment.
Pull request overview
This PR moves block splitting into the core layer and exposes it via the SDK/Core Blocks API, supporting tool-specific splitting (canSplit) and fallback splitting into the default tool via conversionConfig.import. It also extends the document model with helpers for extracting/merging text+fragments and renumbering array-indexed keypaths to support split behavior.
Changes:
- Add
BlocksAPI.split()and implement split logic inBlocksManager.splitBlock()(core), with DOM adapter wiring to call the API. - Introduce model utilities for extracting all block text inputs, slicing fragments, merging text nodes, and renumbering dot-notation array keypaths.
- Extend Block Tool options (
conversionConfig,canSplit) and addimportTextContent()helper for default-tool import during non-splittable splits.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/sdk/src/tools/facades/BlockToolFacade.ts | Adds importTextContent() for building tool data from plain text via conversion config. |
| packages/sdk/src/entities/BlockTool.ts | Extends Block tool options with conversionConfig and canSplit. |
| packages/sdk/src/api/BlocksAPI.ts | Adds split() to the public SDK Blocks API interface. |
| packages/model/src/utils/textUtils.ts | Adds fragment slicing and text-node merge helpers for split/convert flows. |
| packages/model/src/utils/textUtils.spec.ts | Unit tests for sliceFragments() and mergeTextNodes(). |
| packages/model/src/utils/keypath.ts | Adds renumberKeys() to remap array-indexed dot keys starting at 0. |
| packages/model/src/utils/keypath.spec.ts | Unit tests for renumberKeys(). |
| packages/model/src/utils/index.ts | Re-exports keypath namespace and textUtils from model utils. |
| packages/model/src/entities/EditorDocument/index.ts | Exposes resolveBlockIndex() publicly and adds getBlockTextContent(). |
| packages/model/src/entities/EditorDocument/EditorDocument.spec.ts | Tests for resolveBlockIndex() and getBlockTextContent(). |
| packages/model/src/entities/BlockNode/index.ts | Adds getTextContent() to collect all TextNode inputs recursively. |
| packages/model/src/entities/BlockNode/BlockNode.spec.ts | Tests for BlockNode.getTextContent(). |
| packages/model/src/EditorJSModel.ts | Exposes resolveBlockIndex() and getBlockTextContent() wrappers. |
| packages/model/src/EditorJSModel.spec.ts | Updates API surface test to include new model methods. |
| packages/dom-adapters/src/tokens.ts | Adds IoC token for injecting EditorAPI. |
| packages/dom-adapters/src/index.ts | Binds EditorAPI into the adapter IoC container. |
| packages/dom-adapters/src/BlockToolAdapter/index.ts | Replaces direct split implementation with api.blocks.split() call. |
| packages/core/src/tools/internal/block-tools/paragraph/index.ts | Adds paragraph conversionConfig import/export mapping for default conversion. |
| packages/core/src/components/BlockManager.ts | Implements splitBlock() in core using model text extraction, conversion import, and key renumbering. |
| packages/core/src/components/BlockManager.spec.ts | Unit tests for BlocksManager.splitBlock() (mocked model/tools). |
| packages/core/src/api/BlocksAPI.ts | Implements BlocksAPI.split() delegating into BlocksManager.splitBlock(). |
| packages/core/src/api/BlocksAPI.integration.spec.ts | Integration tests for split behavior across canSplit true/false and array-key scenarios. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public importTextContent(value: string, fragments: InlineFragment[]): BlockToolData { | ||
| const conversionConfig = this.options[BlockToolOptionKey.ConversionConfig]; | ||
| const importFnOrProp = conversionConfig?.import; | ||
|
|
||
| if (importFnOrProp === undefined) { | ||
| throw new Error(`Tool ${this.name} does not have import configuration for text content`); | ||
| } | ||
|
|
||
| /** | ||
| * @todo pass fragments to the import function? | ||
| */ | ||
| if (typeof importFnOrProp === 'function') { | ||
| return importFnOrProp(value); | ||
| } | ||
|
|
||
| return { | ||
| [importFnOrProp]: { | ||
| value, | ||
| fragments, | ||
| [NODE_TYPE_HIDDEN_PROP]: BlockChildType.Text as BlockChildType.Text, | ||
| }, | ||
| }; |
There was a problem hiding this comment.
@copilot Fix it using keypath.set, add a tests covering that case
There was a problem hiding this comment.
Fixed in commit 5b33dcc. importTextContent() now uses keypath.set to build the result, so a dot-notation import key like items.0.text produces the correct nested structure { items: [{ text: {...} }] } instead of a flat { 'items.0.text': {...} }. Added four new tests covering: simple string key, dot-notation key, function import, and missing config.
…ests Agent-Logs-Url: https://github.com/editor-js/document-model/sessions/a624a722-89a6-4a89-8816-bbc87fad33ac Co-authored-by: gohabereg <23050529+gohabereg@users.noreply.github.com>
Agent-Logs-Url: https://github.com/editor-js/document-model/sessions/5dd136bd-b230-49cd-9df6-7c3363f1d248 Co-authored-by: gohabereg <23050529+gohabereg@users.noreply.github.com>
Split moved to the core and enhanced. Accessible via Blocks API
Now split follows this algorithm:
If a Tool that is being split has
canSplit: trueoption:a. Core would split the inputs in creation order and insert a new block of the same type with inputs after the split. That means if a Tool provides canSplit = true, it should be able to handle partial data
b. If inputs are contained in the array, array indexes will be renumbered so new block receives array starting from 0
If a Tool doesn't have
canSplitor it equals falsea. New block of the
defaultTooltype insertedb. Content from the inputs after the split is concatenated into a string. Fragments also concatenated into a one array with ranges shifted
c. Default Tool must support
importoption in theconversionConfigd. Content is converted using the conversion config and inserted into the new block