Skip to content

Commit

Permalink
feat: add extendEmptyMarkRange option to mark commands (#1859)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippkuehn authored Sep 8, 2021
1 parent b955077 commit 14e458e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 23 deletions.
16 changes: 13 additions & 3 deletions packages/core/src/commands/toggleMark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,27 @@ declare module '@tiptap/core' {
/**
* Toggle a mark on and off.
*/
toggleMark: (typeOrName: string | MarkType, attributes?: Record<string, any>) => ReturnType,
toggleMark: (
typeOrName: string | MarkType,
attributes?: Record<string, any>,
options?: {
/**
* Removes the mark even across the current selection. Defaults to `false`.
*/
extendEmptyMarkRange?: boolean,
},
) => ReturnType,
}
}
}

export const toggleMark: RawCommands['toggleMark'] = (typeOrName, attributes = {}) => ({ state, commands }) => {
export const toggleMark: RawCommands['toggleMark'] = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
const { extendEmptyMarkRange = false } = options
const type = getMarkType(typeOrName, state.schema)
const isActive = isMarkActive(state, type, attributes)

if (isActive) {
return commands.unsetMark(type)
return commands.unsetMark(type, { extendEmptyMarkRange })
}

return commands.setMark(type, attributes)
Expand Down
47 changes: 29 additions & 18 deletions packages/core/src/commands/unsetMark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,46 @@ declare module '@tiptap/core' {
/**
* Remove all marks in the current selection.
*/
unsetMark: (typeOrName: string | MarkType) => ReturnType,
unsetMark: (
typeOrName: string | MarkType,
options?: {
/**
* Removes the mark even across the current selection. Defaults to `false`.
*/
extendEmptyMarkRange?: boolean,
},
) => ReturnType,
}
}
}

export const unsetMark: RawCommands['unsetMark'] = typeOrName => ({ tr, state, dispatch }) => {
export const unsetMark: RawCommands['unsetMark'] = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
const { extendEmptyMarkRange = false } = options
const { selection } = tr
const type = getMarkType(typeOrName, state.schema)
const { $from, empty, ranges } = selection

if (dispatch) {
if (empty) {
let { from, to } = selection
const range = getMarkRange($from, type)

if (range) {
from = range.from
to = range.to
}

tr.removeMark(from, to, type)
} else {
ranges.forEach(range => {
tr.removeMark(range.$from.pos, range.$to.pos, type)
})
if (!dispatch) {
return true
}

if (empty && extendEmptyMarkRange) {
let { from, to } = selection
const range = getMarkRange($from, type)

if (range) {
from = range.from
to = range.to
}

tr.removeStoredMark(type)
tr.removeMark(from, to, type)
} else {
ranges.forEach(range => {
tr.removeMark(range.$from.pos, range.$to.pos, type)
})
}

tr.removeStoredMark(type)

return true
}
4 changes: 2 additions & 2 deletions packages/extension-link/src/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ export const Link = Mark.create<LinkOptions>({
return commands.setMark('link', attributes)
},
toggleLink: attributes => ({ commands }) => {
return commands.toggleMark('link', attributes)
return commands.toggleMark('link', attributes, { extendEmptyMarkRange: true })
},
unsetLink: () => ({ commands }) => {
return commands.unsetMark('link')
return commands.unsetMark('link', { extendEmptyMarkRange: true })
},
}
},
Expand Down

0 comments on commit 14e458e

Please sign in to comment.