add keepOnSplit option to attributes

This commit is contained in:
Philipp Kühn 2021-01-28 19:56:35 +01:00
parent cde0d8690a
commit ee7daa3f43
5 changed files with 39 additions and 19 deletions

View File

@ -95,15 +95,18 @@ export default class ExtensionManager {
.flat() .flat()
} }
get attributes() {
return getAttributesFromExtensions(this.extensions)
}
get nodeViews() { get nodeViews() {
const { editor } = this const { editor } = this
const { nodeExtensions } = splitExtensions(this.extensions) const { nodeExtensions } = splitExtensions(this.extensions)
const allAttributes = getAttributesFromExtensions(this.extensions)
return Object.fromEntries(nodeExtensions return Object.fromEntries(nodeExtensions
.filter(extension => !!extension.config.addNodeView) .filter(extension => !!extension.config.addNodeView)
.map(extension => { .map(extension => {
const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.config.name) const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.config.name)
const context = { const context = {
options: extension.options, options: extension.options,
editor, editor,

View File

@ -15,7 +15,6 @@ function defaultBlockAt(match: ContentMatch) {
} }
export interface SplitBlockOptions { export interface SplitBlockOptions {
withAttributes: boolean,
withMarks: boolean, withMarks: boolean,
} }
@ -31,15 +30,35 @@ function keepMarks(state: EditorState) {
/** /**
* Forks a new node from an existing node. * Forks a new node from an existing node.
*/ */
export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command => ({ tr, state, dispatch }) => { export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command => ({
tr,
state,
dispatch,
editor,
}) => {
const defaultOptions: SplitBlockOptions = { const defaultOptions: SplitBlockOptions = {
withAttributes: false,
withMarks: true, withMarks: true,
} }
const config = { ...defaultOptions, ...options } const config = { ...defaultOptions, ...options }
const { selection, doc } = tr const { selection, doc } = tr
const { $from, $to } = selection const { $from, $to } = selection
const extensionAttributes = editor.extensionManager.attributes
.filter(item => item.type === $from.node().type.name)
const currentAttributes = $from.node().attrs
const newAttributes = Object.fromEntries(Object
.entries(currentAttributes)
.filter(([name]) => {
const extensionAttribute = extensionAttributes.find(item => item.name === name)
if (!extensionAttribute) {
return false
}
return extensionAttribute.attribute.keepOnSplit
}))
if (selection instanceof NodeSelection && selection.node.isBlock) { if (selection instanceof NodeSelection && selection.node.isBlock) {
if (!$from.parentOffset || !canSplit(doc, $from.pos)) { if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
return false return false
@ -74,9 +93,7 @@ export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command =>
let types = atEnd && deflt let types = atEnd && deflt
? [{ ? [{
type: deflt, type: deflt,
attrs: config.withAttributes attrs: newAttributes,
? $from.node().attrs
: {},
}] }]
: undefined : undefined
@ -91,9 +108,7 @@ export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command =>
types = deflt types = deflt
? [{ ? [{
type: deflt, type: deflt,
attrs: config.withAttributes attrs: newAttributes,
? $from.node().attrs
: {},
}] }]
: undefined : undefined
} }

View File

@ -20,6 +20,7 @@ export default function getAttributesFromExtensions(extensions: Extensions): Ext
rendered: true, rendered: true,
renderHTML: null, renderHTML: null,
parseHTML: null, parseHTML: null,
keepOnSplit: true,
} }
extensions.forEach(extension => { extensions.forEach(extension => {

View File

@ -60,6 +60,7 @@ export type Attribute = {
rendered?: boolean, rendered?: boolean,
renderHTML?: ((attributes: { [key: string]: any }) => { [key: string]: any } | null) | null, renderHTML?: ((attributes: { [key: string]: any }) => { [key: string]: any } | null) | null,
parseHTML?: ((element: HTMLElement) => { [key: string]: any } | null) | null, parseHTML?: ((element: HTMLElement) => { [key: string]: any } | null) | null,
keepOnSplit: boolean,
} }
export type Attributes = { export type Attributes = {

View File

@ -59,14 +59,14 @@ export const TextAlign = Extension.create({
return { return {
// TODO: re-use only 'textAlign' attribute // TODO: re-use only 'textAlign' attribute
// TODO: use custom splitBlock only for `this.options.types` // TODO: use custom splitBlock only for `this.options.types`
Enter: () => this.editor.commands.first(({ commands }) => [ // Enter: () => this.editor.commands.first(({ commands }) => [
() => commands.newlineInCode(), // () => commands.newlineInCode(),
() => commands.createParagraphNear(), // () => commands.createParagraphNear(),
() => commands.liftEmptyBlock(), // () => commands.liftEmptyBlock(),
() => commands.splitBlock({ // () => commands.splitBlock({
withAttributes: true, // withAttributes: true,
}), // }),
]), // ]),
'Mod-Shift-l': () => this.editor.commands.setTextAlign('left'), 'Mod-Shift-l': () => this.editor.commands.setTextAlign('left'),
'Mod-Shift-e': () => this.editor.commands.setTextAlign('center'), 'Mod-Shift-e': () => this.editor.commands.setTextAlign('center'),
'Mod-Shift-r': () => this.editor.commands.setTextAlign('right'), 'Mod-Shift-r': () => this.editor.commands.setTextAlign('right'),