Skip to content

Commit

Permalink
feat(core): the delete event can now detect mark deletions too (#6047)
Browse files Browse the repository at this point in the history
  • Loading branch information
nperez0111 authored Jan 24, 2025
1 parent 704f462 commit 18923ea
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 22 deletions.
46 changes: 42 additions & 4 deletions packages/core/src/extensions/delete.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { RemoveMarkStep } from '@tiptap/pm/transform'

import { Extension } from '../Extension.js'
import { combineTransactionSteps, getChangedRanges } from '../helpers/index.js'

Expand All @@ -23,13 +25,17 @@ export const Delete = Extension.create({
nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter &&
nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore
) {
nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, pos) => {
const isFullyWithinRange = change.oldRange.from <= pos && pos + node.nodeSize - 2 <= change.oldRange.to
nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, from) => {
const to = from + node.nodeSize - 2
const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to

this.editor.emit('delete', {
type: 'node',
node,
pos,
newPos: nextTransaction.mapping.map(pos),
from,
to,
newFrom: nextTransaction.mapping.map(from),
newTo: nextTransaction.mapping.map(to),
deletedRange: change.oldRange,
newRange: change.newRange,
partial: !isFullyWithinRange,
Expand All @@ -40,6 +46,38 @@ export const Delete = Extension.create({
})
}
})

const mapping = nextTransaction.mapping
nextTransaction.steps.forEach((step, index) => {
if (step instanceof RemoveMarkStep) {
const newStart = mapping.slice(index).map(step.from, -1)
const newEnd = mapping.slice(index).map(step.to)
const oldStart = mapping.invert().map(newStart, -1)
const oldEnd = mapping.invert().map(newEnd)

const foundBeforeMark = nextTransaction.doc.nodeAt(newStart - 1)?.marks.some(mark => mark.eq(step.mark))
const foundAfterMark = nextTransaction.doc.nodeAt(newEnd)?.marks.some(mark => mark.eq(step.mark))

this.editor.emit('delete', {
type: 'mark',
mark: step.mark,
from: step.from,
to: step.to,
deletedRange: {
from: oldStart,
to: oldEnd,
},
newRange: {
from: newStart,
to: newEnd,
},
partial: Boolean(foundAfterMark || foundBeforeMark),
editor: this.editor,
transaction,
combinedTransform: nextTransaction,
})
}
})
}

if (this.editor.options.coreExtensionOptions?.delete?.async ?? true) {
Expand Down
61 changes: 43 additions & 18 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,23 +184,6 @@ export interface EditorEvents {
* The editor instance
*/
editor: Editor
/**
* The node which the deletion occurred in
* @note This can be a parent node of the deleted content
*/
node: ProseMirrorNode
/**
* Whether the deletion was partial (only a part of this node was deleted)
*/
partial: boolean
/**
* This is the position of the node in the document (before the deletion)
*/
pos: number
/**
* The new position of the node in the document (after the deletion)
*/
newPos: number
/**
* The range of the deleted content (before the deletion)
*/
Expand All @@ -217,7 +200,49 @@ export interface EditorEvents {
* The combined transform (including all appended transactions) that caused the deletion
*/
combinedTransform: Transform
}
/**
* Whether the deletion was partial (only a part of this content was deleted)
*/
partial: boolean
/**
* This is the start position of the mark in the document (before the deletion)
*/
from: number
/**
* This is the end position of the mark in the document (before the deletion)
*/
to: number
} & (
| {
/**
* The content that was deleted
*/
type: 'node'
/**
* The node which the deletion occurred in
* @note This can be a parent node of the deleted content
*/
node: ProseMirrorNode
/**
* The new start position of the node in the document (after the deletion)
*/
newFrom: number
/**
* The new end position of the node in the document (after the deletion)
*/
newTo: number
}
| {
/**
* The content that was deleted
*/
type: 'mark'
/**
* The mark that was deleted
*/
mark: ProseMirrorMark
}
)
}

export type EnableRules = (AnyExtension | string)[] | boolean
Expand Down

0 comments on commit 18923ea

Please sign in to comment.