improve isActive for marks
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
import { EditorState } from 'prosemirror-state'
|
import { EditorState } from 'prosemirror-state'
|
||||||
import { Node, Mark } from 'prosemirror-model'
|
|
||||||
import nodeIsActive from './nodeIsActive'
|
import nodeIsActive from './nodeIsActive'
|
||||||
import markIsActive from './markIsActive'
|
import markIsActive from './markIsActive'
|
||||||
import objectIncludes from '../utilities/objectIncludes'
|
|
||||||
import getSchemaTypeNameByName from './getSchemaTypeNameByName'
|
import getSchemaTypeNameByName from './getSchemaTypeNameByName'
|
||||||
|
|
||||||
export default function isActive(state: EditorState, name: string | null, attributes: { [key: string ]: any } = {}): boolean {
|
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') {
|
} if (schemaType === 'mark') {
|
||||||
return markIsActive(state, state.schema.marks[name], attributes)
|
return markIsActive(state, state.schema.marks[name], attributes)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeIsActive(state, null, attributes) || markIsActive(state, null, attributes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,33 @@
|
|||||||
import { EditorState } from 'prosemirror-state'
|
import { EditorState } from 'prosemirror-state'
|
||||||
import { MarkType } from 'prosemirror-model'
|
import { Mark, MarkType } from 'prosemirror-model'
|
||||||
import markHasAttributes from './markHasAttributes'
|
import objectIncludes from '../utilities/objectIncludes'
|
||||||
|
import getMarkType from '../helpers/getMarkType'
|
||||||
|
|
||||||
export default function markIsActive(state: EditorState, type: MarkType, attributes = {}) {
|
export default function markIsActive(state: EditorState, typeOrName: MarkType | string | null, attributes = {}) {
|
||||||
const {
|
const { from, to, empty } = state.selection
|
||||||
from,
|
const type = typeOrName
|
||||||
$from,
|
? getMarkType(typeOrName, state.schema)
|
||||||
to,
|
: null
|
||||||
empty,
|
|
||||||
} = state.selection
|
|
||||||
|
|
||||||
const hasMark = empty
|
let marks: Mark[] = []
|
||||||
? !!(type.isInSet(state.storedMarks || $from.marks()))
|
|
||||||
: state.doc.rangeHasMark(from, to, type)
|
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
import { findParentNode, findSelectedNodeOfType } from 'prosemirror-utils'
|
|
||||||
import { EditorState } from 'prosemirror-state'
|
import { EditorState } from 'prosemirror-state'
|
||||||
import { Node, NodeType } from 'prosemirror-model'
|
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 = {}) {
|
export default function nodeIsActive(state: EditorState, typeOrName: NodeType | string | null, attributes = {}) {
|
||||||
const predicate = (node: Node) => node.type === type
|
const { from, to } = state.selection
|
||||||
const node = findSelectedNodeOfType(type)(state.selection)
|
const type = typeOrName
|
||||||
|| findParentNode(predicate)(state.selection)
|
? getNodeType(typeOrName, state.schema)
|
||||||
|
: null
|
||||||
|
|
||||||
if (!Object.keys(attributes).length || !node) {
|
let nodes: Node[] = []
|
||||||
return !!node
|
|
||||||
|
state.doc.nodesBetween(from, to, node => {
|
||||||
|
nodes = [...nodes, node]
|
||||||
|
})
|
||||||
|
|
||||||
|
const nodeWithAttributes = nodes
|
||||||
|
.filter(node => {
|
||||||
|
if (!type) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.node.hasMarkup(type, {
|
return type.name === node.type.name
|
||||||
...node.node.attrs,
|
|
||||||
...attributes,
|
|
||||||
})
|
})
|
||||||
|
.find(node => objectIncludes(node.attrs, attributes))
|
||||||
|
|
||||||
|
return !!nodeWithAttributes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,13 @@
|
|||||||
* @param object2 Object
|
* @param object2 Object
|
||||||
*/
|
*/
|
||||||
export default function objectIncludes(object1: { [key: string ]: any }, object2: { [key: string ]: any }): boolean {
|
export default function objectIncludes(object1: { [key: string ]: any }, object2: { [key: string ]: any }): boolean {
|
||||||
return !!Object
|
const keys = Object.keys(object2)
|
||||||
.keys(object2)
|
|
||||||
|
if (!keys.length) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!keys
|
||||||
.filter(key => object2[key] === object1[key])
|
.filter(key => object2[key] === object1[key])
|
||||||
.length
|
.length
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user