diff --git a/packages/core/src/helpers/isActive.ts b/packages/core/src/helpers/isActive.ts index 0c212f3a..1f9f637b 100644 --- a/packages/core/src/helpers/isActive.ts +++ b/packages/core/src/helpers/isActive.ts @@ -1,8 +1,6 @@ import { EditorState } from 'prosemirror-state' -import { Node, Mark } from 'prosemirror-model' import nodeIsActive from './nodeIsActive' import markIsActive from './markIsActive' -import objectIncludes from '../utilities/objectIncludes' import getSchemaTypeNameByName from './getSchemaTypeNameByName' export default function isActive(state: EditorState, name: string | null, attributes: { [key: string ]: any } = {}): boolean { @@ -14,32 +12,9 @@ export default function isActive(state: EditorState, name: string | null, attrib } if (schemaType === 'mark') { return markIsActive(state, state.schema.marks[name], attributes) } + + return false } - if (!name) { - const { from, to, empty } = state.selection - let nodes: Node[] = [] - let marks: Mark[] = [] - - if (empty) { - marks = state.selection.$head.marks() - } - - state.doc.nodesBetween(from, to, node => { - nodes = [...nodes, node] - - if (!empty) { - marks = [...marks, ...node.marks] - } - }) - - const anyNodeWithAttributes = nodes.find(node => objectIncludes(node.attrs, attributes)) - const anyMarkWithAttributes = marks.find(mark => objectIncludes(mark.attrs, attributes)) - - if (anyNodeWithAttributes || anyMarkWithAttributes) { - return true - } - } - - return false + return nodeIsActive(state, null, attributes) || markIsActive(state, null, attributes) } diff --git a/packages/core/src/helpers/markHasAttributes.ts b/packages/core/src/helpers/markHasAttributes.ts deleted file mode 100644 index 42fd84a7..00000000 --- a/packages/core/src/helpers/markHasAttributes.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { EditorState } from 'prosemirror-state' -import { MarkType } from 'prosemirror-model' -import getMarkAttributes from './getMarkAttributes' -import isEmptyObject from '../utilities/isEmptyObject' -import objectIncludes from '../utilities/objectIncludes' - -export default function markHasAttributes(state: EditorState, type: MarkType, attributes: {}) { - if (isEmptyObject(attributes)) { - return true - } - - const originalAttributes = getMarkAttributes(state, type) - - return objectIncludes(originalAttributes, attributes) -} diff --git a/packages/core/src/helpers/markIsActive.ts b/packages/core/src/helpers/markIsActive.ts index 2f7cebc5..65338fc1 100644 --- a/packages/core/src/helpers/markIsActive.ts +++ b/packages/core/src/helpers/markIsActive.ts @@ -1,20 +1,33 @@ import { EditorState } from 'prosemirror-state' -import { MarkType } from 'prosemirror-model' -import markHasAttributes from './markHasAttributes' +import { Mark, MarkType } from 'prosemirror-model' +import objectIncludes from '../utilities/objectIncludes' +import getMarkType from '../helpers/getMarkType' -export default function markIsActive(state: EditorState, type: MarkType, attributes = {}) { - const { - from, - $from, - to, - empty, - } = state.selection +export default function markIsActive(state: EditorState, typeOrName: MarkType | string | null, attributes = {}) { + const { from, to, empty } = state.selection + const type = typeOrName + ? getMarkType(typeOrName, state.schema) + : null - const hasMark = empty - ? !!(type.isInSet(state.storedMarks || $from.marks())) - : state.doc.rangeHasMark(from, to, type) + let marks: Mark[] = [] - const hasAttributes = markHasAttributes(state, type, attributes) + if (empty) { + marks = state.selection.$head.marks() + } else { + state.doc.nodesBetween(from, to, node => { + marks = [...marks, ...node.marks] + }) + } - return hasMark && hasAttributes + const markWithAttributes = marks + .filter(mark => { + if (!type) { + return true + } + + return type.name === mark.type.name + }) + .find(mark => objectIncludes(mark.attrs, attributes)) + + return !!markWithAttributes } diff --git a/packages/core/src/helpers/nodeIsActive.ts b/packages/core/src/helpers/nodeIsActive.ts index de1ed513..d68bade0 100644 --- a/packages/core/src/helpers/nodeIsActive.ts +++ b/packages/core/src/helpers/nodeIsActive.ts @@ -1,18 +1,29 @@ -import { findParentNode, findSelectedNodeOfType } from 'prosemirror-utils' import { EditorState } from 'prosemirror-state' import { Node, NodeType } from 'prosemirror-model' +import objectIncludes from '../utilities/objectIncludes' +import getNodeType from '../helpers/getNodeType' -export default function nodeIsActive(state: EditorState, type: NodeType, attributes = {}) { - const predicate = (node: Node) => node.type === type - const node = findSelectedNodeOfType(type)(state.selection) - || findParentNode(predicate)(state.selection) +export default function nodeIsActive(state: EditorState, typeOrName: NodeType | string | null, attributes = {}) { + const { from, to } = state.selection + const type = typeOrName + ? getNodeType(typeOrName, state.schema) + : null - if (!Object.keys(attributes).length || !node) { - return !!node - } + let nodes: Node[] = [] - return node.node.hasMarkup(type, { - ...node.node.attrs, - ...attributes, + state.doc.nodesBetween(from, to, node => { + nodes = [...nodes, node] }) + + const nodeWithAttributes = nodes + .filter(node => { + if (!type) { + return true + } + + return type.name === node.type.name + }) + .find(node => objectIncludes(node.attrs, attributes)) + + return !!nodeWithAttributes } diff --git a/packages/core/src/utilities/objectIncludes.ts b/packages/core/src/utilities/objectIncludes.ts index e8fef855..141bb3d1 100644 --- a/packages/core/src/utilities/objectIncludes.ts +++ b/packages/core/src/utilities/objectIncludes.ts @@ -4,8 +4,13 @@ * @param object2 Object */ export default function objectIncludes(object1: { [key: string ]: any }, object2: { [key: string ]: any }): boolean { - return !!Object - .keys(object2) + const keys = Object.keys(object2) + + if (!keys.length) { + return true + } + + return !!keys .filter(key => object2[key] === object1[key]) .length }