improve isActive for marks

This commit is contained in:
Philipp Kühn 2020-11-30 15:40:16 +01:00
parent 4fbdb0ff0c
commit c0911c315c
5 changed files with 59 additions and 70 deletions

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}