Skip to content

Commit

Permalink
fix(portable-text-editor): fix and test issue with merge block operat…
Browse files Browse the repository at this point in the history
…ion (#5996)

* test(portable-text-editor): fix wrong path used in package script (dev)

* test(portable-text-editor): fix debug statement and remove redundant var

* test(portable-text-editr): add collab test for merge empty block
  • Loading branch information
skogsmaskin authored Mar 14, 2024
1 parent 51d3bbd commit 96bc72b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,67 @@ describe('collaborate editing', () => {
})
})

it('should not remove content for both users if one user backspaces into a block that starts with a mark.', async () => {
const exampleValue = [
{
_key: 'randomKey0',
_type: 'block',
children: [
{
_key: 'randomKey1',
_type: 'span',
marks: ['strong'],
text: 'Example Text: ',
},
{
_type: 'span',
marks: [],
text: "This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent. This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent. This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent.",
_key: 'randomKey2',
},
],
markDefs: [],
style: 'normal',
},
]
await setDocumentValue(exampleValue)
const [editorA, editorB] = await getEditors()
await editorA.setSelection({
anchor: {path: [{_key: 'randomKey0'}, 'children', {_key: 'randomKey2'}], offset: 542},
focus: {path: [{_key: 'randomKey0'}, 'children', {_key: 'randomKey2'}], offset: 542},
})
await editorA.pressKey('Enter')
await editorA.pressKey('Backspace')

await new Promise((resolve) => setTimeout(resolve, 1000))

const valA = await editorA.getValue()
const valB = await editorB.getValue()
expect(valA).toEqual(valB)
expect(valB).toEqual([
{
_key: 'randomKey0',
_type: 'block',
children: [
{
_key: 'randomKey1',
_type: 'span',
marks: ['strong'],
text: 'Example Text: ',
},
{
_type: 'span',
marks: [],
text: "This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent. This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent. This is a very long example text that will completely disappear later on. It's kind of a bad magic trick, really. Just writing more text so the disappearance becomes more apparent.",
_key: 'randomKey2',
},
],
markDefs: [],
style: 'normal',
},
])
})

it('will reset the value when someone deletes everything, and when they start to type again, they will produce their own respective blocks.', async () => {
await setDocumentValue(initialValue)
const [editorA, editorB] = await getEditors()
Expand Down
2 changes: 1 addition & 1 deletion packages/@sanity/portable-text-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"clean": "rimraf lib",
"lint": "eslint .",
"prettier": "prettier --write './**/*.{ts,tsx,js,css,html}'",
"dev": "cd ./test/ && ts-node serve",
"dev": "cd ./e2e-tests/ && ts-node serve",
"test": "jest",
"test:e2e": "jest --config=e2e-tests/e2e.config.cjs",
"test:watch": "jest --watch",
Expand Down
12 changes: 8 additions & 4 deletions packages/@sanity/portable-text-editor/src/utils/applyPatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,18 +250,22 @@ function setPatch(editor: PortableTextSlateEditor, patch: SetPatch) {
} else if (Element.isElement(block) && patch.path.length === 1 && blockPath) {
debug('Setting block property')
const {children, ...nextRest} = value as unknown as PortableTextBlock
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
const {children: prevChildren, ...prevRest} = block || {children: undefined}
// Set any block properties
editor.apply({
type: 'set_node',
path: blockPath,
properties: {...prevRest},
newProperties: nextRest,
})
// Replace the children in the block
// Note that children must be explicitly inserted, and can't be set with set_node
debug('Setting children')
block.children.forEach((c, cIndex) => {
editor.apply({
type: 'remove_node',
path: blockPath.concat(cIndex),
path: blockPath.concat(block.children.length - 1 - cIndex),
node: c,
})
})
Expand Down Expand Up @@ -306,6 +310,7 @@ function unsetPatch(editor: PortableTextSlateEditor, patch: UnsetPatch, previous
return true
}
const {block, blockPath, child, childPath} = findBlockAndChildFromPath(editor, patch.path)

// Single blocks
if (patch.path.length === 1) {
if (!block || !blockPath) {
Expand All @@ -327,11 +332,10 @@ function unsetPatch(editor: PortableTextSlateEditor, patch: UnsetPatch, previous
debug('Child not found')
return false
}
const childIndex = childPath[1]
debug(`Unsetting child at path ${JSON.stringify(childPath)}`)
debugState(editor, 'before')
if (debugVerbose) {
debug(`Removing child at path ${JSON.stringify([childPath, childIndex])}`)
debug(`Removing child at path ${JSON.stringify(childPath)}`)
}
Transforms.removeNodes(editor, {at: childPath})
debugState(editor, 'after')
Expand Down

0 comments on commit 96bc72b

Please sign in to comment.