Plate
PlateEditorsTemplates
GitHub16kGitHub
DiscordDiscord
    • Overview
    • Why This Fork
    • Examples
    • Installing Plite
    • Adding Event Handlers
    • Defining Custom Elements
    • Applying Custom Formatting
    • Executing Commands
    • Saving to a Database
    • Canonical Change Substrate
    • Improving Performance
    • Interfaces
    • Nodes
    • Locations
    • Transforms
    • Document Changes
    • Commands
    • Editor
    • Plugins
    • Rendering
    • Serializing
    • Normalizing
    • Using TypeScript
    • Roots
    • Document State
    • Editing Behavior
    • Selection And DOM
    • Clipboard And Paste
    • Decorations, annotations, and widgets
    • Schema
    • Anchor API
    • Location API
    • Path API
    • PointEntry API
    • Point API
    • Range API
    • Selection API
    • Location Types APIs
    • Span API
    • Editor
    • Element API
    • NodeEntry API
    • Node API
    • Node Types APIs
    • Text API
    • Debug Value Scrubbing
    • Transforms API
    • Plite DOM
    • History Editor API
    • History Plugin Setup
    • History
    • Plite History
    • Plite Hyperscript
    • Plite PaginationExperimental
    • Annotations
    • DOM Coverage Boundaries
    • Editable Component
    • External Text Views
    • Plite React Event Handling
    • Virtualized Rendering
    • Plite React Hooks
    • React Editor Setup
    • React Editor
    • Plite React
    • Plite Component
    • Plite Yjs
    • Plite
    • Migration
    • Contributing
    • FAQ
    • Resources

Node API

PreviousNext

Pure node-tree helpers for traversing, querying, and checking Plite nodes.

  • Static methods
    • Retrieval methods
    • Text methods
    • Check methods

Static methods

Retrieval methods

NodeEntry APINode Types APIs

On This Page

Static methodsRetrieval methodsNodeApi.ancestor(root: Node, path: Path) => AncestorNodeApi.ancestors(root: Node, path: Path, options?) => Generator<NodeEntry<Ancestor>>NodeApi.child(root: Node, index: number) => DescendantNodeApi.children(root: Node, path: Path, options?) => Generator<NodeEntry<Descendant>>NodeApi.common(root: Node, path: Path, another: Path) => NodeEntryNodeApi.descendant(root: Node, path: Path) => DescendantNodeApi.descendants(root: Node, options?) => Generator<NodeEntry<Descendant>>NodeApi.elements(root: Node, options?) => Generator<ElementEntry>NodeApi.extractProps(node: Node) => NodePropsNodeApi.first(root: Node, path: Path) => NodeEntryNodeApi.fragment(root: Ancestor, range: Range) => readonly Descendant[]NodeApi.findTextRanges(root: Node | NodeTextRangeRoot | NodeTextRangeView, query: NodeTextRangeQuery, options?) => readonly Range[]NodeApi.get(root: Node, path: Path) => NodeNodeApi.getIf(root: Node, path: Path) => Node | undefinedNodeApi.last(root: Node, path: Path) => NodeEntryNodeApi.leaf(root: Node, path: Path) => TextNodeApi.levels(root: Node, path: Path, options?) => Generator<NodeEntry>NodeApi.nodes(root: Node, options?) => Generator<NodeEntry>NodeApi.parent(root: Node, path: Path) => AncestorText methodsNodeApi.string(root: Node) => stringNodeApi.texts(root: Node, options?) => Generator<NodeEntry<Text>>Check methodsNodeApi.has(root: Node, path: Path) => booleanNodeApi.isAncestor(node: Node) => node is AncestorNodeApi.isEditor(node: Node) => node is EditorNodeApi.isElement(node: Node) => node is ElementNodeApi.isNode(value: unknown, options?: { deep?: boolean }) => value is NodeNodeApi.isNodeList(value: unknown, options?: { deep?: boolean }) => value is readonly Node[]NodeApi.isText(node: Node) => node is TextNodeApi.matches(node: Node, match: NodeMatch<Node>, path?: Path) => boolean
Build your editor
Production-ready AI template and reusable components.
Get all-access
NodeApi.ancestor(root: Node, path: Path) => Ancestor

Get the node at a specific path, asserting that it is an ancestor node. If the specified node is not an ancestor node, throw an error.

NodeApi.ancestors(root: Node, path: Path, options?) => Generator<NodeEntry<Ancestor>>

Return a generator of all the ancestor nodes above a specific path. By default, the order is top-down, from highest to lowest ancestor in the tree, but you can pass the reverse: true option to go bottom-up.

Options: {reverse?: boolean}

NodeApi.child(root: Node, index: number) => Descendant

Get the child of a node at the specified index.

NodeApi.children(root: Node, path: Path, options?) => Generator<NodeEntry<Descendant>>

Iterate over the children of a node at a specific path.

Options: {reverse?: boolean}

NodeApi.common(root: Node, path: Path, another: Path) => NodeEntry

Get an entry for the common ancestor node of two paths. It might be a Text node, an Element, or the Editor itself.

For the common block ancestor, see selection.

NodeApi.descendant(root: Node, path: Path) => Descendant

Get the node at a specific path, asserting that it's a descendant node.

NodeApi.descendants(root: Node, options?) => Generator<NodeEntry<Descendant>>

Return a generator of all the descendant node entries inside a root node. Each iteration will return a NodeEntry tuple consisting of [Node, Path].

Options: {from?: Path, to?: Path, reverse?: boolean, pass?: (node: NodeEntry => boolean)}

NodeApi.elements(root: Node, options?) => Generator<ElementEntry>

Return a generator of all the element nodes inside a root node. Each iteration will return an ElementEntry tuple consisting of [Element, Path]. If the root node is an element, it will be included in the iteration as well.

Options: {from?: Path, to?: Path, reverse?: boolean, pass?: (node: NodeEntry => boolean)}

NodeApi.extractProps(node: Node) => NodeProps

Extract all properties from a Node except for its content-related fields (children for Element nodes and text for Text nodes).

// For an Element node
const element = {
  type: "paragraph",
  align: "center",
  children: [{ text: "Try it out for yourself!" }],
};
const props = NodeApi.extractProps(element);
// Returns: { type: 'paragraph', align: "center" }
 
// For a Text node
const text = { text: "Hello", bold: true };
const props = NodeApi.extractProps(text);
// Returns: { bold: true }
// For an Element node
const element = {
  type: "paragraph",
  align: "center",
  children: [{ text: "Try it out for yourself!" }],
};
const props = NodeApi.extractProps(element);
// Returns: { type: 'paragraph', align: "center" }
 
// For a Text node
const text = { text: "Hello", bold: true };
const props = NodeApi.extractProps(text);
// Returns: { bold: true }

NodeApi.first(root: Node, path: Path) => NodeEntry

Descend from path through first children until reaching a text node or an ancestor with no children, and return that node entry.

NodeApi.fragment(root: Ancestor, range: Range) => readonly Descendant[]

Get the sliced fragment represented by the range.

NodeApi.findTextRanges(root: Node | NodeTextRangeRoot | NodeTextRangeView, query: NodeTextRangeQuery, options?) => readonly Range[]

Find ranges for a text query inside text runs. Editor, read view, and transaction roots use their schema to join text through inline descendants without crossing block boundaries. String queries are literal. Use a regular expression or callback for custom matching.

NodeApi.get(root: Node, path: Path) => Node

Get the descendant node referred to by a specific path. If the path is an empty array, get the root node itself.

NodeApi.getIf(root: Node, path: Path) => Node | undefined

Get a descendant node at a specific path, returning undefined if the node does not exist. This is a safer alternative to NodeApi.get() as it won't throw an error if the path is invalid.

const node = NodeApi.getIf(root, [0, 1]);
if (node) {
  // node exists at path [0, 1]
} else {
  // no node exists at path [0, 1]
}
const node = NodeApi.getIf(root, [0, 1]);
if (node) {
  // node exists at path [0, 1]
} else {
  // no node exists at path [0, 1]
}

NodeApi.last(root: Node, path: Path) => NodeEntry

Descend from path through last children until reaching a text node or an ancestor with no children, and return that node entry.

NodeApi.leaf(root: Node, path: Path) => Text

Get the node at a specific path, ensuring it's a leaf text node. If the node is not a leaf text node, throw an error.

NodeApi.levels(root: Node, path: Path, options?) => Generator<NodeEntry>

Return a generator of the nodes in a branch of the tree, from a specific path. By default, the order is top-down, from the highest to the lowest node in the tree, but you can pass the reverse: true option to go bottom-up.

Options: {reverse?: boolean}

NodeApi.nodes(root: Node, options?) => Generator<NodeEntry>

Return a generator of all the node entries of a root node. Each entry is returned as a [Node, Path] tuple, with the path referring to the node's position inside the root node.

Options: {from?: Path, to?: Path, reverse?: boolean, pass?: (node: NodeEntry => boolean)}

NodeApi.parent(root: Node, path: Path) => Ancestor

Get the parent of a node at a specific path.

Text methods

Methods related to text leaves.

NodeApi.string(root: Node) => string

Get the concatenated text string of a node's content. Note that this will not include spaces or line breaks between block nodes. This is not intended as a user-facing string, but as a string for performing offset-related computations for a node.

NodeApi.texts(root: Node, options?) => Generator<NodeEntry<Text>>

Return a generator of all leaf text nodes in a root node.

Options: {from?: Path, to?: Path, reverse?: boolean, pass?: (node: NodeEntry => boolean)}

Check methods

Methods used to check attributes of a node.

NodeApi.has(root: Node, path: Path) => boolean

Check if a descendant node exists at a specific path.

NodeApi.isAncestor(node: Node) => node is Ancestor

Check if a node is an Editor or Element object.

NodeApi.isEditor(node: Node) => node is Editor

Check if a node is an Editor object.

NodeApi.isElement(node: Node) => node is Element

Check if a node is an Element object.

NodeApi.isNode(value: unknown, options?: { deep?: boolean }) => value is Node

Check if a value implements the Node interface.

NodeApi.isNodeList(value: unknown, options?: { deep?: boolean }) => value is readonly Node[]

Check if a value is a list of Node objects.

NodeApi.isText(node: Node) => node is Text

Check if a node is a Text object.

NodeApi.matches(node: Node, match: NodeMatch<Node>, path?: Path) => boolean

Check a node with a predicate. The predicate receives the node's path and preserves type narrowing.

NodeApi.matches(node, (candidate, path) => {
  return path.length === 1 && ElementApi.isElement(candidate)
}, path)
NodeApi.matches(node, (candidate, path) => {
  return path.length === 1 && ElementApi.isElement(candidate)
}, path)