Overview
ProseKit provides a collection of helper utilities that make common editor operations easier and more convenient.
Node Utilities
findNode()
Finds the first node that satisfies a predicate in the document.
function findNode(
doc: ProseMirrorNode,
predicate: (node: ProseMirrorNode) => boolean
): FindNodeResult | undefined
Parameters
The document to search in
predicate
(node: ProseMirrorNode) => boolean
required
A function that returns true for the node you’re looking for
Return Value
result
FindNodeResult | undefined
An object containing the found node and its position, or undefined if not found.The node that satisfies the predicate
The position of the node in the document
The index of the node in its parent
Example
import { findNode } from 'prosekit/core'
const result = findNode(
editor.state.doc,
node => node.type.name === 'heading' && node.attrs.level === 1
)
if (result) {
console.log('Found H1 at position:', result.pos)
console.log('Content:', result.node.textContent)
}
findNodes()
Finds all nodes that satisfy a predicate in the document.
function findNodes(
doc: ProseMirrorNode,
predicate: (node: ProseMirrorNode) => boolean
): FindNodeResult[]
Parameters
The document to search in
predicate
(node: ProseMirrorNode) => boolean
required
A function that returns true for nodes you’re looking for
Return Value
An array of objects containing the found nodes and their positions
Example
import { findNodes } from 'prosekit/core'
// Find all images
const images = findNodes(
editor.state.doc,
node => node.type.name === 'image'
)
console.log(`Found ${images.length} images`)
images.forEach(img => {
console.log('Image at:', img.pos, 'src:', img.node.attrs.src)
})
findParentNode()
Finds the nearest parent node that satisfies a predicate.
function findParentNode(
predicate: (node: ProseMirrorNode) => boolean
): FindParentNodeResult | undefined
Example
import { findParentNode } from 'prosekit/core'
const { selection } = editor.state
const $pos = selection.$from
const listParent = findParentNode(
node => node.type.name === 'bulletList' || node.type.name === 'orderedList'
)($pos)
if (listParent) {
console.log('Inside a list at depth:', listParent.depth)
}
findParentNodeOfType()
Finds the nearest parent node of a specific type.
function findParentNodeOfType(
type: string | NodeType
): FindParentNodeResult | undefined
Example
import { findParentNodeOfType } from 'prosekit/core'
const { selection } = editor.state
const tableParent = findParentNodeOfType('table')(selection.$from)
if (tableParent) {
console.log('Inside a table')
}
Type Utilities
getMarkType()
Gets a MarkType from the schema by name or returns the MarkType if already provided.
function getMarkType(schema: Schema, type: string | MarkType): MarkType
Parameters
type
string | MarkType
required
The mark type name or MarkType instance
Return Value
The MarkType instance. Throws an error if the type doesn’t exist in the schema.
Example
import { getMarkType } from 'prosekit/core'
const boldType = getMarkType(editor.schema, 'bold')
const boldMark = boldType.create()
getNodeType()
Gets a NodeType from the schema by name or returns the NodeType if already provided.
function getNodeType(schema: Schema, type: string | NodeType): NodeType
Parameters
type
string | NodeType
required
The node type name or NodeType instance
Return Value
The NodeType instance. Throws an error if the type doesn’t exist in the schema.
Example
import { getNodeType } from 'prosekit/core'
const paragraphType = getNodeType(editor.schema, 'paragraph')
const paragraph = paragraphType.create()
State Checking Utilities
isMarkActive()
Checks if a mark is active in the current selection.
function isMarkActive(
state: EditorState,
type: string | MarkType,
attrs?: Attrs | null
): boolean
Parameters
type
string | MarkType
required
The mark type to check
Optional attributes to match
Return Value
Returns true if the mark is active in the selection, false otherwise
Example
import { isMarkActive } from 'prosekit/core'
const isBold = isMarkActive(editor.state, 'bold')
if (isBold) {
console.log('Bold is active')
}
// Check with specific attributes
const hasYellowHighlight = isMarkActive(
editor.state,
'highlight',
{ color: 'yellow' }
)
isMarkAbsent()
Checks if a mark is completely absent from a range.
function isMarkAbsent(
doc: ProseMirrorNode,
from: number,
to: number,
type: MarkType,
attrs?: Attrs | null
): boolean
Example
import { isMarkAbsent, getMarkType } from 'prosekit/core'
const boldType = getMarkType(editor.schema, 'bold')
const noBold = isMarkAbsent(
editor.state.doc,
10,
20,
boldType
)
isAtBlockStart()
Checks if the selection is at the start of a block.
function isAtBlockStart(state: EditorState): boolean
Example
import { isAtBlockStart } from 'prosekit/core'
if (isAtBlockStart(editor.state)) {
console.log('Cursor is at the start of a block')
}
isInCodeBlock()
Checks if the selection is inside a code block.
function isInCodeBlock(state: EditorState): boolean
Example
import { isInCodeBlock } from 'prosekit/core'
if (isInCodeBlock(editor.state)) {
console.log('Inside a code block')
}
Content Utilities
containsInlineNode()
Checks if a node contains inline content.
function containsInlineNode(node: ProseMirrorNode): boolean
Example
import { containsInlineNode } from 'prosekit/core'
const node = editor.state.doc.firstChild
if (containsInlineNode(node)) {
console.log('Node contains inline content')
}
defaultBlockAt()
Finds the default block type at a given position.
function defaultBlockAt(pos: ResolvedPos): NodeType | null
Example
import { defaultBlockAt } from 'prosekit/core'
const { $from } = editor.state.selection
const defaultBlock = defaultBlockAt($from)
if (defaultBlock) {
console.log('Default block type:', defaultBlock.name)
}
Environment Utilities
isApple()
Checks if the current platform is macOS or iOS.
function isApple(): boolean
Example
import { isApple } from 'prosekit/core'
const modKey = isApple() ? 'Cmd' : 'Ctrl'
console.log(`Use ${modKey}+B for bold`)
canUseRegexLookbehind()
Checks if the environment supports regex lookbehind.
function canUseRegexLookbehind(): boolean
Example
import { canUseRegexLookbehind } from 'prosekit/core'
if (canUseRegexLookbehind()) {
// Use advanced regex features
}
Utility Functions
assert()
Throws an error if a condition is not met.
function assert(condition: unknown, message?: string): asserts condition
Example
import { assert } from 'prosekit/core'
function processNode(node: ProseMirrorNode | null) {
assert(node, 'Node must be defined')
// TypeScript knows node is not null here
console.log(node.type.name)
}
clsx()
Utility for conditionally constructing className strings.
function clsx(...args: ClassValue[]): string
Example
import { clsx } from 'prosekit/core'
const className = clsx(
'editor',
isActive && 'active',
{ 'dark-mode': isDark },
['foo', 'bar']
)
// Result: 'editor active dark-mode foo bar'
maybeRun()
Runs a function if it exists and returns its result.
function maybeRun<T>(
fn: (() => T) | undefined | null
): T | undefined
Example
import { maybeRun } from 'prosekit/core'
const result = maybeRun(config.onInit)
if (result) {
console.log('Init result:', result)
}
withSkipCodeBlock()
Wraps a command to skip execution when inside a code block.
function withSkipCodeBlock(command: Command): Command
Example
import { withSkipCodeBlock } from 'prosekit/core'
import { toggleMark } from 'prosekit/core'
// Bold won't work inside code blocks
const safeBold = withSkipCodeBlock(
toggleMark({ type: 'bold' })
)
Common Patterns
Finding Specific Content
import { findNodes } from 'prosekit/core'
function findAllLinks(editor) {
return findNodes(
editor.state.doc,
node => node.marks.some(mark => mark.type.name === 'link')
)
}
function findEmptyParagraphs(editor) {
return findNodes(
editor.state.doc,
node => node.type.name === 'paragraph' && node.childCount === 0
)
}
Checking Editor State
import { isMarkActive, isAtBlockStart, isInCodeBlock } from 'prosekit/core'
function getEditorStatus(editor) {
return {
bold: isMarkActive(editor.state, 'bold'),
italic: isMarkActive(editor.state, 'italic'),
atStart: isAtBlockStart(editor.state),
inCode: isInCodeBlock(editor.state)
}
}
import { isApple } from 'prosekit/core'
import { defineKeymap } from 'prosekit/core'
function createPlatformKeymap() {
const modKey = isApple() ? 'Cmd' : 'Ctrl'
return defineKeymap({
[`${modKey}-b`]: toggleMark({ type: 'bold' }),
[`${modKey}-i`]: toggleMark({ type: 'italic' })
})
}
Safe Command Execution
import { withSkipCodeBlock } from 'prosekit/core'
import { toggleMark } from 'prosekit/core'
const safeCommands = {
bold: withSkipCodeBlock(toggleMark({ type: 'bold' })),
italic: withSkipCodeBlock(toggleMark({ type: 'italic' })),
// Code blocks should still work
code: toggleMark({ type: 'code' })
}
See Also