Skip to content

Commit

Permalink
fix(editor): allow empty block to be decorated
Browse files Browse the repository at this point in the history
  • Loading branch information
christianhg committed Sep 9, 2024
1 parent fa76d4b commit d944641
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 59 deletions.
23 changes: 23 additions & 0 deletions packages/editor/e2e-tests/__tests__/decorators.feature
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,26 @@ Feature: Decorators
Then the text is "bar,\n,foo"
And "bar" has marks "strong"
And "foo" has marks "strong"

Scenario: Toggling decorators in empty block
Given an empty editor
When "foo" is typed
And "Backspace" is pressed 3 times
And "strong" is toggled using the keyboard
And editors have settled
Then the text is ""
And "" has marks "strong"

Scenario: Splitting empty decorated block
Given the text "foo"
When "Enter" is pressed
And "strong" is toggled using the keyboard
And "Enter" is pressed
And "ArrowUp" is pressed
And "bar" is typed
And "ArrowDown" is pressed
And "baz" is typed
Then the text is "foo,\n,bar,\n,baz"
And "foo" has no marks
And "bar" has marks "strong"
And "baz" has marks "strong"
Original file line number Diff line number Diff line change
Expand Up @@ -925,44 +925,4 @@ describe('collaborate editing', () => {
const valB = await editorB.getValue()
expect(newValA).toEqual(valB)
})
it('sends the correct patches when toggling marks in a sequence', async () => {
const [editorA, editorB] = await getEditors()
await editorA.toggleDecoratorUsingKeyboard('strong')
await editorA.insertText('Bold')
await editorA.toggleDecoratorUsingKeyboard('strong')
await editorA.toggleDecoratorUsingKeyboard('em')
await editorA.insertText('Italic')
await editorA.toggleDecoratorUsingKeyboard('em')
const valueA = await editorA.getValue()
const valueB = await editorB.getValue()
expect(valueB).toMatchInlineSnapshot(`
Array [
Object {
"_key": "A-4",
"_type": "block",
"children": Array [
Object {
"_key": "A-5",
"_type": "span",
"marks": Array [
"strong",
],
"text": "Bold",
},
Object {
"_key": "A-6",
"_type": "span",
"marks": Array [
"em",
],
"text": "Italic",
},
],
"markDefs": Array [],
"style": "normal",
},
]
`)
expect(valueA).toEqual(valueB)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -441,17 +441,49 @@ export function createWithPortableTextMarkModel(
}
})
} else {
const existingMarks: string[] =
{
const [block, blockPath] = Editor.node(editor, editor.selection, {
depth: 1,
})
const lonelyEmptySpan =
editor.isTextBlock(block) &&
block.children.length === 1 &&
editor.isTextSpan(block.children[0]) &&
block.children[0].text === ''
? block.children[0]
: undefined

if (lonelyEmptySpan) {
const existingMarks = lonelyEmptySpan.marks ?? []
const existingMarksWithoutDecorator = existingMarks.filter(
(existingMark) => existingMark !== mark,
)

Transforms.setNodes(
editor,
{
marks:
existingMarks.length === existingMarksWithoutDecorator.length
? [...existingMarks, mark]
: existingMarksWithoutDecorator,
},
{
at: blockPath,
match: (node) => editor.isTextSpan(node),
},
)
} else {
const existingMarks: string[] =
{
...(Editor.marks(editor) || {}),
}.marks || []
const marks = {
...(Editor.marks(editor) || {}),
}.marks || []
const marks = {
...(Editor.marks(editor) || {}),
marks: [...existingMarks, mark],
marks: [...existingMarks, mark],
}
editor.marks = marks as Text
forceNewSelection()
return editor
}
editor.marks = marks as Text
forceNewSelection()
return editor
}
editor.onChange()
forceNewSelection()
Expand Down Expand Up @@ -494,17 +526,46 @@ export function createWithPortableTextMarkModel(
})
Editor.normalize(editor)
} else {
const existingMarks: string[] =
{
const [block, blockPath] = Editor.node(editor, selection, {
depth: 1,
})
const lonelyEmptySpan =
editor.isTextBlock(block) &&
block.children.length === 1 &&
editor.isTextSpan(block.children[0]) &&
block.children[0].text === ''
? block.children[0]
: undefined

if (lonelyEmptySpan) {
const existingMarks = lonelyEmptySpan.marks ?? []
const existingMarksWithoutDecorator = existingMarks.filter(
(existingMark) => existingMark !== mark,
)

Transforms.setNodes(
editor,
{
marks: existingMarksWithoutDecorator,
},
{
at: blockPath,
match: (node) => editor.isTextSpan(node),
},
)
} else {
const existingMarks: string[] =
{
...(Editor.marks(editor) || {}),
}.marks || []
const marks = {
...(Editor.marks(editor) || {}),
}.marks || []
const marks = {
...(Editor.marks(editor) || {}),
marks: existingMarks.filter((eMark) => eMark !== mark),
} as Text
editor.marks = {marks: marks.marks, _type: 'span'} as Text
forceNewSelection()
return editor
marks: existingMarks.filter((eMark) => eMark !== mark),
} as Text
editor.marks = {marks: marks.marks, _type: 'span'} as Text
forceNewSelection()
return editor
}
}
editor.onChange()
forceNewSelection()
Expand Down

0 comments on commit d944641

Please sign in to comment.