tiptap/packages/core/src/helpers/isNodeActive.ts

68 lines
1.6 KiB
TypeScript
Raw Normal View History

2020-03-30 06:15:20 +08:00
import { EditorState } from 'prosemirror-state'
import { Node, NodeType } from 'prosemirror-model'
2020-11-30 22:40:16 +08:00
import objectIncludes from '../utilities/objectIncludes'
2020-12-01 16:11:58 +08:00
import getNodeType from './getNodeType'
2020-12-01 16:20:25 +08:00
import { AnyObject } from '../types'
2020-03-30 06:15:20 +08:00
2020-12-01 16:11:58 +08:00
export type NodeRange = {
2020-12-01 04:10:13 +08:00
node: Node,
from: number,
to: number,
}
2020-12-01 16:11:58 +08:00
export default function isNodeActive(
state: EditorState,
typeOrName: NodeType | string | null,
2020-12-01 16:20:25 +08:00
attributes: AnyObject = {},
2020-12-01 16:11:58 +08:00
): boolean {
2020-12-01 04:10:13 +08:00
const { from, to, empty } = state.selection
2020-11-30 22:40:16 +08:00
const type = typeOrName
? getNodeType(typeOrName, state.schema)
: null
2020-03-30 06:15:20 +08:00
2020-12-01 04:10:13 +08:00
let nodeRanges: NodeRange[] = []
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.isText) {
const relativeFrom = Math.max(from, pos)
const relativeTo = Math.min(to, pos + node.nodeSize)
2020-03-30 06:15:20 +08:00
2020-12-01 04:10:13 +08:00
nodeRanges = [...nodeRanges, {
node,
from: relativeFrom,
to: relativeTo,
}]
}
2020-11-30 16:21:31 +08:00
})
2020-11-30 22:40:16 +08:00
2020-12-01 04:10:13 +08:00
if (empty) {
return !!nodeRanges
.filter(nodeRange => {
if (!type) {
return true
}
return type.name === nodeRange.node.type.name
})
.find(nodeRange => objectIncludes(nodeRange.node.attrs, attributes))
}
2020-12-01 16:11:58 +08:00
const selectionRange = to - from
2020-12-01 04:10:13 +08:00
const range = nodeRanges
.filter(nodeRange => {
2020-11-30 22:40:16 +08:00
if (!type) {
return true
}
2020-12-01 04:10:13 +08:00
return type.name === nodeRange.node.type.name
2020-11-30 22:40:16 +08:00
})
2020-12-01 04:10:13 +08:00
.filter(nodeRange => objectIncludes(nodeRange.node.attrs, attributes))
.reduce((sum, nodeRange) => {
const size = nodeRange.to - nodeRange.from
return sum + size
}, 0)
2020-12-02 15:55:34 +08:00
return range >= selectionRange
2020-03-30 06:15:20 +08:00
}