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-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,
|
|
|
|
attributes = {},
|
|
|
|
): 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-01 16:11:58 +08:00
|
|
|
return selectionRange === range
|
2020-03-30 06:15:20 +08:00
|
|
|
}
|