feat: add support for checking for attributes in extendMarkRange
This commit is contained in:
@@ -10,20 +10,20 @@ declare module '@tiptap/core' {
|
||||
/**
|
||||
* Extends the text selection to the current mark.
|
||||
*/
|
||||
extendMarkRange: (typeOrName: string | MarkType) => Command,
|
||||
extendMarkRange: (typeOrName: string | MarkType, attributes?: Record<string, any>) => Command,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const extendMarkRange: RawCommands['extendMarkRange'] = typeOrName => ({ tr, state, dispatch }) => {
|
||||
export const extendMarkRange: RawCommands['extendMarkRange'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
|
||||
const type = getMarkType(typeOrName, state.schema)
|
||||
const { doc, selection } = tr
|
||||
const { $from, empty } = selection
|
||||
const { $from, from, to } = selection
|
||||
|
||||
if (empty && dispatch) {
|
||||
const range = getMarkRange($from, type)
|
||||
if (dispatch) {
|
||||
const range = getMarkRange($from, type, attributes)
|
||||
|
||||
if (range) {
|
||||
if (range && range.from <= from && range.to >= to) {
|
||||
const newSelection = TextSelection.create(doc, range.from, range.to)
|
||||
|
||||
tr.setSelection(newSelection)
|
||||
|
||||
31
packages/core/src/helpers/getDebugJSON.ts
Normal file
31
packages/core/src/helpers/getDebugJSON.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
||||
|
||||
/**
|
||||
* Returns a node tree with node positions.
|
||||
*/
|
||||
export default function getDebugJSON(node: ProseMirrorNode) {
|
||||
const debug = (startNode: ProseMirrorNode, startOffset = 0) => {
|
||||
const nodes: any[] = []
|
||||
|
||||
startNode.forEach((n, offset) => {
|
||||
const from = startOffset + offset
|
||||
const to = from + n.nodeSize
|
||||
|
||||
nodes.push({
|
||||
type: n.type.name,
|
||||
attrs: { ...n.attrs },
|
||||
from,
|
||||
to,
|
||||
marks: n.marks.map(mark => ({
|
||||
type: mark.type.name,
|
||||
attrs: { ...mark.attrs },
|
||||
})),
|
||||
content: debug(n, from + 1),
|
||||
})
|
||||
})
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
return debug(node)
|
||||
}
|
||||
@@ -1,7 +1,30 @@
|
||||
import { MarkType, ResolvedPos } from 'prosemirror-model'
|
||||
import { Mark as ProseMirrorMark, MarkType, ResolvedPos } from 'prosemirror-model'
|
||||
import objectIncludes from '../utilities/objectIncludes'
|
||||
import { Range } from '../types'
|
||||
|
||||
export default function getMarkRange($pos: ResolvedPos, type: MarkType): Range | void {
|
||||
function findMarkInSet(
|
||||
marks: ProseMirrorMark[],
|
||||
type: MarkType,
|
||||
attributes: Record<string, any> = {},
|
||||
): ProseMirrorMark | undefined {
|
||||
return marks.find(item => {
|
||||
return item.type === type && objectIncludes(item.attrs, attributes)
|
||||
})
|
||||
}
|
||||
|
||||
function isMarkInSet(
|
||||
marks: ProseMirrorMark[],
|
||||
type: MarkType,
|
||||
attributes: Record<string, any> = {},
|
||||
): boolean {
|
||||
return !!findMarkInSet(marks, type, attributes)
|
||||
}
|
||||
|
||||
export default function getMarkRange(
|
||||
$pos: ResolvedPos,
|
||||
type: MarkType,
|
||||
attributes: Record<string, any> = {},
|
||||
): Range | void {
|
||||
if (!$pos || !type) {
|
||||
return
|
||||
}
|
||||
@@ -12,9 +35,9 @@ export default function getMarkRange($pos: ResolvedPos, type: MarkType): Range |
|
||||
return
|
||||
}
|
||||
|
||||
const link = start.node.marks.find(mark => mark.type === type)
|
||||
const mark = findMarkInSet(start.node.marks, type, attributes)
|
||||
|
||||
if (!link) {
|
||||
if (!mark) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -23,12 +46,17 @@ export default function getMarkRange($pos: ResolvedPos, type: MarkType): Range |
|
||||
let endIndex = startIndex + 1
|
||||
let endPos = startPos + start.node.nodeSize
|
||||
|
||||
while (startIndex > 0 && link.isInSet($pos.parent.child(startIndex - 1).marks)) {
|
||||
findMarkInSet(start.node.marks, type, attributes)
|
||||
|
||||
while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
|
||||
startIndex -= 1
|
||||
startPos -= $pos.parent.child(startIndex).nodeSize
|
||||
}
|
||||
|
||||
while (endIndex < $pos.parent.childCount && link.isInSet($pos.parent.child(endIndex).marks)) {
|
||||
while (
|
||||
endIndex < $pos.parent.childCount
|
||||
&& isMarkInSet($pos.parent.child(endIndex).marks, type, attributes)
|
||||
) {
|
||||
endPos += $pos.parent.child(endIndex).nodeSize
|
||||
endIndex += 1
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ export { default as generateHTML } from './helpers/generateHTML'
|
||||
export { default as generateJSON } from './helpers/generateJSON'
|
||||
export { default as getSchema } from './helpers/getSchema'
|
||||
export { default as getHTMLFromFragment } from './helpers/getHTMLFromFragment'
|
||||
export { default as getDebugJSON } from './helpers/getDebugJSON'
|
||||
export { default as getAttributes } from './helpers/getAttributes'
|
||||
export { default as getMarkAttributes } from './helpers/getMarkAttributes'
|
||||
export { default as getMarkRange } from './helpers/getMarkRange'
|
||||
|
||||
Reference in New Issue
Block a user