Closed andreasvirkus closed 3 years ago
Since the gapcursor extension is basically a wrapper around prosemirror-gapcursor and marijn don't want to change that behavior I’m not sure how we should handle that right now.
You could get the expected behavior by setting isolating = true
in the NodeSpec of codeblock because the gapcursor uses:
(before.childCount == 0 && !before.inlineContent) || before.isAtom || before.type.spec.isolating
If you do that, you'll lose some behaviors like "if two codeblocks are adjacent, pressing backspace on the second codeblock will not merge it with the first one".
isolating
has some other weird side effects (up and down cursor navigation within cursor navigation isn't working as expected) so this is not an option I think.
I think we'll just live with the current situation then. Thanks for explaining! We've added some arrow shortcuts to our editor as a compromise. @techstonia is hopefully planning on proposing these changes in a PR for you soon, if that's fine. Slack's inline code also works the same way (right arrow to escape)
export const CustomCode = Code.extend({
addKeyboardShortcuts() {
return {
'Mod-e': () => this.editor.commands.toggleCode(),
ArrowRight: () => {
const state = this.editor.state
const { from, to } = state.selection
if (from > 1 && from === to) {
let codeOnLeft = false
state.doc.nodesBetween(from - 1, to - 1, (node) => {
const code = node.marks.find((markItem) => markItem.type.name === 'code')
if (code) codeOnLeft = true
})
let noCodeUnderCursor = true
state.doc.nodesBetween(from, to, (node) => {
const code = node.marks.find((markItem) => markItem.type.name === 'code')
if (code) noCodeUnderCursor = false
})
let nothingOnRight = true
state.doc.nodesBetween(from + 1, to + 1, (node) => {
if (node) nothingOnRight = false
})
if (codeOnLeft && noCodeUnderCursor && nothingOnRight) {
return this.editor.chain().unsetCode().insertContent(' ').run()
}
}
return false
},
Backspace: () => {
const { state } = this.editor
const { $anchor } = state.selection
const { from, to } = state.selection
let commentStartsWithCode = false
state.doc.nodesBetween(1, 2, (node) => {
const code = node.marks.find((markItem) => markItem.type.name === 'code')
if (code) commentStartsWithCode = true
})
if (!commentStartsWithCode) return false
const noCodeOnRight = !$anchor.nodeAfter?.marks.find((markItem) => markItem.type.name === 'code')
if (this.editor.isActive('code') && from === 2 && noCodeOnRight) {
return this.editor.chain().deleteRange({ from: 1, to: 2 }).unsetCode().run()
}
// Remove code formatting when deleting everything in editor
if (from === 1 && to === state.doc.content.size - 1) {
return this.editor.commands.clearContent()
}
return false
},
}
},
})
export const CustomCodeBlock = CodeBlock.extend({
addKeyboardShortcuts() {
return {
'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),
// remove code block when at start of document or code block is empty
Backspace: () => {
const { state } = this.editor
const { empty, $anchor } = state.selection
const isAtStart = $anchor.pos === 1
if (!empty || $anchor.parent.type.name !== 'codeBlock') {
return false
}
if (isAtStart || !$anchor.parent.textContent.length) {
return this.editor.commands.clearNodes()
}
return false
},
ArrowDown: () => {
const state = this.editor.state
const { from, to } = state.selection
if (from > 1 && from === to) {
let inCodeBlock = false
state.doc.nodesBetween(from - 1, to - 1, (node) => {
if (node.type.name === 'codeBlock') inCodeBlock = true
})
let nothingOnRight = true
state.doc.nodesBetween(from + 1, to + 1, (node) => {
if (node) nothingOnRight = false
})
if (inCodeBlock && nothingOnRight) {
return (this.editor.commands as any).setHardBreak()
}
}
return false
},
}
},
addInputRules() {
return [
textblockTypeInputRule(/^```$/, this.type, ({ groups }: any) => groups),
textblockTypeInputRule(tildeInputRegex, this.type, ({ groups }: any) => groups),
]
},
})
Yeah, we should still improve behavior.
Btw you can extend without overwriting with parent
:
export const CustomCodeBlock = CodeBlock.extend({
addKeyboardShortcuts() {
return {
...this.parent.?(),
// new shortcuts here
ArrowDown: () => {
// ...
},
}
},
})
@andreasvirkus I opened two PRs with the arrow shortcuts functionality https://github.com/ueberdosis/tiptap/pull/1200 https://github.com/ueberdosis/tiptap/pull/1204
Description Gapcursor does not play nice with a code block atm.
Steps to reproduce the bug Steps to reproduce the behavior:
Expected behavior The gapcursor can be placed before or after a code block, like with an Image node
Screenshot, video, or GIF If applicable, add screenshots to help explain your problem.
https://user-images.githubusercontent.com/9140811/115612461-f371b480-a2f3-11eb-9267-d4159d27a13a.mov
Environment?