From 3afe5af21e17f7aee94f2a65330212597e38a761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Mon, 30 Nov 2020 21:10:13 +0100 Subject: [PATCH] invert nodeIsActive --- packages/core/src/helpers/nodeIsActive.ts | 51 +++++++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/packages/core/src/helpers/nodeIsActive.ts b/packages/core/src/helpers/nodeIsActive.ts index d68bade0..711cceac 100644 --- a/packages/core/src/helpers/nodeIsActive.ts +++ b/packages/core/src/helpers/nodeIsActive.ts @@ -3,27 +3,60 @@ import { Node, NodeType } from 'prosemirror-model' import objectIncludes from '../utilities/objectIncludes' import getNodeType from '../helpers/getNodeType' +type NodeRange = { + node: Node, + from: number, + to: number, +} + export default function nodeIsActive(state: EditorState, typeOrName: NodeType | string | null, attributes = {}) { - const { from, to } = state.selection + const { from, to, empty } = state.selection const type = typeOrName ? getNodeType(typeOrName, state.schema) : null - let nodes: Node[] = [] + let nodeRanges: NodeRange[] = [] - state.doc.nodesBetween(from, to, node => { - nodes = [...nodes, node] + state.doc.nodesBetween(from, to, (node, pos) => { + if (!node.isText) { + const relativeFrom = Math.max(from, pos) + const relativeTo = Math.min(to, pos + node.nodeSize) + + nodeRanges = [...nodeRanges, { + node, + from: relativeFrom, + to: relativeTo, + }] + } }) - const nodeWithAttributes = nodes - .filter(node => { + if (empty) { + return !!nodeRanges + .filter(nodeRange => { + if (!type) { + return true + } + + return type.name === nodeRange.node.type.name + }) + .find(nodeRange => objectIncludes(nodeRange.node.attrs, attributes)) + } + + const range = nodeRanges + .filter(nodeRange => { if (!type) { return true } - return type.name === node.type.name + return type.name === nodeRange.node.type.name }) - .find(node => objectIncludes(node.attrs, attributes)) + .filter(nodeRange => objectIncludes(nodeRange.node.attrs, attributes)) + .reduce((sum, nodeRange) => { + const size = nodeRange.to - nodeRange.from + return sum + size + }, 0) - return !!nodeWithAttributes + const selectionRange = to - from + + return selectionRange <= range }