add withAttributes and withMarks option to splitBlock command

This commit is contained in:
Philipp Kühn
2020-11-04 17:01:51 +01:00
parent 1d3de73f82
commit 09ddf954a7
4 changed files with 47 additions and 8 deletions

View File

@@ -131,7 +131,7 @@ export default class CommandManager {
view,
state: this.chainableState(tr, state),
dispatch: shouldDispatch
? () => true
? () => undefined
: undefined,
chain: () => this.createChain(tr),
can: () => this.createCan(tr),

View File

@@ -29,11 +29,11 @@ export const BaseKeymap = createExtension({
])
return {
Enter: () => this.editor.try(({ state, dispatch }) => [
Enter: () => this.editor.try(({ commands, state, dispatch }) => [
() => newlineInCode(state, dispatch),
() => createParagraphNear(state, dispatch),
() => liftEmptyBlock(state, dispatch),
() => splitBlockKeepMarks(state, dispatch),
() => commands.splitBlock(),
]),
'Mod-Enter': exitCode,
Backspace: () => handleBackspace(),

View File

@@ -1,6 +1,6 @@
import { canSplit } from 'prosemirror-transform'
import { ContentMatch, Fragment } from 'prosemirror-model'
import { NodeSelection, TextSelection } from 'prosemirror-state'
import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
@@ -13,10 +13,29 @@ function defaultBlockAt(match: ContentMatch) {
return null
}
interface SplitBlockOptions {
withAttributes: boolean,
withMarks: boolean,
}
function keepMarks(state: EditorState) {
const marks = state.storedMarks
|| (state.selection.$to.parentOffset && state.selection.$from.marks())
if (marks) {
state.tr.ensureMarks(marks)
}
}
export const SplitBlock = createExtension({
addCommands() {
return {
splitBlock: (copyAttributes = false): Command => ({ tr, dispatch }) => {
splitBlock: (options: Partial<SplitBlockOptions> = {}): Command => ({ tr, state, dispatch }) => {
const defaultOptions: SplitBlockOptions = {
withAttributes: false,
withMarks: true,
}
const config = { ...defaultOptions, ...options }
const { selection, doc } = tr
const { $from, $to } = selection
@@ -26,6 +45,10 @@ export const SplitBlock = createExtension({
}
if (dispatch) {
if (config.withMarks) {
keepMarks(state)
}
tr.split($from.pos).scrollIntoView()
}
@@ -48,7 +71,12 @@ export const SplitBlock = createExtension({
: defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
let types = atEnd && deflt
? [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }]
? [{
type: deflt,
attrs: config.withAttributes
? $from.node().attrs
: {},
}]
: undefined
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
@@ -60,7 +88,12 @@ export const SplitBlock = createExtension({
) {
can = true
types = deflt
? [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }]
? [{
type: deflt,
attrs: config.withAttributes
? $from.node().attrs
: {},
}]
: undefined
}
@@ -77,6 +110,10 @@ export const SplitBlock = createExtension({
}
}
if (config.withMarks) {
keepMarks(state)
}
tr.scrollIntoView()
}

View File

@@ -49,7 +49,9 @@ const TextAlign = createExtension({
// TODO: re-use only 'textAlign' attribute
// TODO: use custom splitBlock only for `this.options.types`
// TODO: use complete default enter handler (chainCommand) with custom splitBlock
Enter: () => this.editor.splitBlock(true),
Enter: () => this.editor.splitBlock({
withAttributes: true,
}),
}
},
})