From cfd29fac86e03d72a0c05ec8d26aac905d19c5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Fri, 23 Apr 2021 08:58:03 +0200 Subject: [PATCH] fix: better merge mark attributes for existing marks, fix #1039 --- packages/core/src/commands/setMark.ts | 37 +++++++++++++++---- .../core/src/commands/updateAttributes.ts | 10 ++++- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/packages/core/src/commands/setMark.ts b/packages/core/src/commands/setMark.ts index 9e3e0ff2..e97bcf38 100644 --- a/packages/core/src/commands/setMark.ts +++ b/packages/core/src/commands/setMark.ts @@ -18,18 +18,41 @@ export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) => const { selection } = tr const { empty, ranges } = selection const type = getMarkType(typeOrName, state.schema) - const oldAttributes = getMarkAttributes(state, type) - const newAttributes = { - ...oldAttributes, - ...attributes, - } if (dispatch) { if (empty) { - tr.addStoredMark(type.create(newAttributes)) + const oldAttributes = getMarkAttributes(state, type) + + tr.addStoredMark(type.create({ + ...oldAttributes, + ...attributes, + })) } else { ranges.forEach(range => { - tr.addMark(range.$from.pos, range.$to.pos, type.create(newAttributes)) + const from = range.$from.pos + const to = range.$to.pos + + state.doc.nodesBetween(from, to, (node, pos) => { + const trimmedFrom = Math.max(pos, from) + const trimmedTo = Math.min(pos + node.nodeSize, to) + const someHasMark = node.marks.find(mark => mark.type === type) + + // if there is already a mark of this type + // we know that we have to merge its attributes + // otherwise we add a fresh new mark + if (someHasMark) { + node.marks.forEach(mark => { + if (type === mark.type) { + tr.addMark(trimmedFrom, trimmedTo, type.create({ + ...mark.attrs, + ...attributes, + })) + } + }) + } else { + tr.addMark(trimmedFrom, trimmedTo, type.create(attributes)) + } + }) }) } } diff --git a/packages/core/src/commands/updateAttributes.ts b/packages/core/src/commands/updateAttributes.ts index 0c62cf5b..262a682d 100644 --- a/packages/core/src/commands/updateAttributes.ts +++ b/packages/core/src/commands/updateAttributes.ts @@ -40,7 +40,10 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at if (dispatch) { tr.selection.ranges.forEach(range => { - state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => { + const from = range.$from.pos + const to = range.$to.pos + + state.doc.nodesBetween(from, to, (node, pos) => { if (nodeType && nodeType === node.type) { tr.setNodeMarkup(pos, undefined, { ...node.attrs, @@ -51,7 +54,10 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at if (markType && node.marks.length) { node.marks.forEach(mark => { if (markType === mark.type) { - tr.addMark(pos, pos + node.nodeSize, markType.create({ + const trimmedFrom = Math.max(pos, from) + const trimmedTo = Math.min(pos + node.nodeSize, to) + + tr.addMark(trimmedFrom, trimmedTo, markType.create({ ...mark.attrs, ...attributes, }))