From d735cf3c758d52ecb2273e45cc0c9727dbf6eccd Mon Sep 17 00:00:00 2001 From: Alex Casillas Date: Wed, 11 Dec 2024 09:36:11 +0100 Subject: [PATCH] fix: update the logic of the removeEmptyTextStyle command from text-syle extension (#5909) Co-authored-by: Alex Casillas --- .changeset/green-students-serve.md | 5 +++ .../extension-text-style/src/text-style.ts | 34 ++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 .changeset/green-students-serve.md diff --git a/.changeset/green-students-serve.md b/.changeset/green-students-serve.md new file mode 100644 index 0000000000..007026c662 --- /dev/null +++ b/.changeset/green-students-serve.md @@ -0,0 +1,5 @@ +--- +"@tiptap/extension-text-style": minor +--- + +fix: #4311 - update the logic of removeEmptyTextStyle to manually handle the selection of all of the nodes within the selection to check for their marks independently to fix an issue where unsetting the font family on a selection would remove all applied text style marks from the selection as well diff --git a/packages/extension-text-style/src/text-style.ts b/packages/extension-text-style/src/text-style.ts index 3665701779..baa7849333 100644 --- a/packages/extension-text-style/src/text-style.ts +++ b/packages/extension-text-style/src/text-style.ts @@ -1,5 +1,4 @@ import { - getMarkAttributes, Mark, mergeAttributes, } from '@tiptap/core' @@ -89,15 +88,34 @@ export const TextStyle = Mark.create({ addCommands() { return { - removeEmptyTextStyle: () => ({ state, commands }) => { - const attributes = getMarkAttributes(state, this.type) - const hasStyles = Object.entries(attributes).some(([, value]) => !!value) + removeEmptyTextStyle: () => ({ tr }) => { + + const { selection } = tr + + // Gather all of the nodes within the selection range. + // We would need to go through each node individually + // to check if it has any inline style attributes. + // Otherwise, calling commands.unsetMark(this.name) + // removes everything from all the nodes + // within the selection range. + tr.doc.nodesBetween(selection.from, selection.to, (node, pos) => { + + // Check if it's a paragraph element, if so, skip this node as we apply + // the text style to inline text nodes only (span). + if (node.isTextblock) { + return true + } - if (hasStyles) { - return true - } + // Check if the node has no inline style attributes. + // Filter out non-`textStyle` marks. + if ( + !node.marks.filter(mark => mark.type === this.type).some(mark => Object.values(mark.attrs).some(value => !!value))) { + // Proceed with the removal of the `textStyle` mark for this node only + tr.removeMark(pos, pos + node.nodeSize, this.type) + } + }) - return commands.unsetMark(this.name) + return true }, } },