Skip to content

Commit

Permalink
fix: Improve backspace handling (#2284), fix #2281
Browse files Browse the repository at this point in the history
* improve backspace handling

* revert codeblock changes

* revert codeblock changes

* fix tests

Co-authored-by: Philipp Kühn <philippkuehn@MacBook-Pro-von-Philipp.local>
  • Loading branch information
philippkuehn and Philipp Kühn authored Dec 16, 2021
1 parent 10248f2 commit 8ed485b
Showing 1 changed file with 70 additions and 0 deletions.
70 changes: 70 additions & 0 deletions packages/core/src/extensions/keymap.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Plugin, PluginKey, Selection } from 'prosemirror-state'
import { createChainableState } from '../helpers/createChainableState'
import { CommandManager } from '../CommandManager'
import { Extension } from '../Extension'

export const Keymap = Extension.create({
Expand All @@ -6,6 +9,24 @@ export const Keymap = Extension.create({
addKeyboardShortcuts() {
const handleBackspace = () => this.editor.commands.first(({ commands }) => [
() => commands.undoInputRule(),
// maybe convert first text block node to default node
() => commands.command(({ tr }) => {
const { selection, doc } = tr
const { empty, $anchor } = selection
const { pos, parent } = $anchor
const isAtStart = Selection.atStart(doc).from === pos

if (
!empty
|| !isAtStart
|| !parent.type.isTextblock
|| parent.textContent.length
) {
return false
}

return commands.clearNodes()
}),
() => commands.deleteSelection(),
() => commands.joinBackward(),
() => commands.selectNodeBackward(),
Expand Down Expand Up @@ -33,4 +54,53 @@ export const Keymap = Extension.create({
'Mod-a': () => this.editor.commands.selectAll(),
}
},

addProseMirrorPlugins() {
return [
// With this plugin we check if the whole document was selected and deleted.
// In this case we will additionally call `clearNodes()` to convert e.g. a heading
// to a paragraph if necessary.
// This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
// with many other commands.
new Plugin({
key: new PluginKey('clearDocument'),
appendTransaction: (transactions, oldState, newState) => {
const docChanges = transactions.some(transaction => transaction.docChanged)
&& !oldState.doc.eq(newState.doc)

if (!docChanges) {
return
}

const { empty, from, to } = oldState.selection
const allFrom = Selection.atStart(oldState.doc).from
const allEnd = Selection.atEnd(oldState.doc).to
const allWasSelected = from === allFrom && to === allEnd
const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0

if (empty || !allWasSelected || !isEmpty) {
return
}

const tr = newState.tr
const state = createChainableState({
state: newState,
transaction: tr,
})
const { commands } = new CommandManager({
editor: this.editor,
state,
})

commands.clearNodes()

if (!tr.steps.length) {
return
}

return tr
},
}),
]
},
})

0 comments on commit 8ed485b

Please sign in to comment.