Transforms are transaction helpers used inside editor.update(...).
Basic Usage
editor.update((tx) => {
tx.text.insert("Hello");
});editor.update((tx) => {
tx.text.insert("Hello");
});On This Page
- Node options
- Node methods
- Block methods
- Break methods
- Fragment methods
- Text methods
- Selection methods
- Mark methods
- Value and root methods
- State field methods
- Normalization methods
- Operation methods
Node options
Node methods accept method-specific options objects. These options appear
across most node methods:
type NodeSelectorOptions = {
at?: NodeTarget;
match?: NodeMatch<Node>;
mode?: "highest" | "lowest" | "all";
voids?: boolean;
};type NodeSelectorOptions = {
at?: NodeTarget;
match?: NodeMatch<Node>;
mode?: "highest" | "lowest" | "all";
voids?: boolean;
};at?: NodeTarget: An explicit location or live descendant to change. When omitted insideeditor.update(...), selection-sensitive methods use the transaction target.match?: NodeMatch<Node>: A predicate or shallow property object that filters which nodes are changed. Array property values mean one-of.mode?: 'highest' | 'lowest': Controls which matching node level is used. Methods documented withmode?: 'highest' | 'lowest' | 'all'also acceptall.voids?: boolean: Includes void elements whentrue.
Node methods
Use node methods from tx.nodes.
tx.nodes.insert(nodes: Node | Node[], options?)
Insert nodes at options.at or the transaction target.
Options: at, match, mode, hanging, select, voids, batchDirty.
hanging?: boolean: Preserve hanging range edges.select?: boolean: Select the inserted nodes.batchDirty?: boolean: Batch dirty-path work for a multi-node insert.
editor.update((tx) => {
tx.nodes.insert({ type: targetType, children: [{ text: "" }] }, { at: [0] });
});editor.update((tx) => {
tx.nodes.insert({ type: targetType, children: [{ text: "" }] }, { at: [0] });
});tx.nodes.remove(options?)
Remove nodes at options.at or the transaction target.
Options: at, match, mode, hanging, voids.
tx.nodes.merge(options?)
Merge a node with the previous node at the same depth.
Options: at, match, mode, hanging, voids.
tx.nodes.split(options?)
Split nodes at a location.
Options: at, match, mode, always, height, position, voids.
always?: boolean: Split even when the target is already at an edge.height?: number: Split at an ancestor height.position?: number: Split at an explicit child position.
tx.nodes.wrap(element: Element, options?)
Wrap matching nodes in element.
Options: at, match, mode, split, voids.
tx.nodes.unwrap(options?)
Unwrap matching nodes.
Options: at, match, mode, split, voids.
tx.nodes.set(props: Partial<Node>, options?)
Set properties on matching nodes.
Options: at, match, mode, hanging, split, voids, compare,
merge.
compare?: PropsCompare: Decide whether a property should be written.merge?: PropsMerge: Merge incoming and existing property values.
Pass an exact node as at to preserve its property inference.
editor.update.nodes.set({ icon: "🔥" }, { at: calloutElement });editor.update.nodes.set({ icon: "🔥" }, { at: calloutElement });tx.nodes.unset(props: string | string[], options?)
Unset properties on matching nodes.
Options: at, match, mode, hanging, split, voids.
tx.nodes.lift(options?)
Lift matching nodes upward in the document tree.
Options: at, match, mode, voids.
tx.nodes.move(options)
Move nodes from options.at to options.to.
Options: at, match, mode, to, voids.
to: Path: Destination path for the moved nodes.
Block methods
Use semantic block mutations from tx.blocks inside a transaction or from
editor.update.blocks for a direct update.
tx.blocks.insertAfter(blocks, options?)
Insert one or more block elements after the block containing options.at.
When at is omitted, the transaction selection is the reference. Ranges use
their document-order end. Missing or blockless references are no-ops.
Options:
at?: NodeTarget: Reference location or live descendant.select?: boolean: Select the inserted blocks.
editor.update.blocks.insertAfter(
{ type: "callout", children: [{ text: "" }] },
{ at: calloutElement, select: true }
);editor.update.blocks.insertAfter(
{ type: "callout", children: [{ text: "" }] },
{ at: calloutElement, select: true }
);tx.blocks.duplicate(options?)
Duplicate the targeted blocks after the last matching block.
tx.blocks.lift(options?)
Lift the targeted blocks one structural level.
tx.blocks.reset(props, options?)
Reset a block to props, removing other block properties unless their keys
are listed in options.preserve.
tx.blocks.toggle(type, options?)
Toggle targeted blocks between type and the editor default block type.
Break methods
Use break methods from tx.break.
tx.break.insert()
Insert a block break at the transaction target.
tx.break.insertSoft()
Insert a soft break at the transaction target.
Fragment methods
Use fragment methods from tx.fragment.
tx.fragment(options?)
Read the fragment at options.at or the current selection.
Options:
at?: Range: Range to read. Defaults to the active selection.
tx.fragment.insert(fragment: Node[], options?)
Insert a fragment at options.at or the transaction target.
Plite's default insertion policy is structural. When a fragment contains nested
blocks that match the active structural container, the first compatible source
block can merge into the active block and later source siblings stay as inserted
siblings. Product-specific positional behavior, such as multi-cell table-grid
paste, belongs in an extension clipboard/fragment policy.
Options:
at?: NodeTarget: Where to insert. Defaults to the transaction target.hanging?: boolean: Preserve hanging range edges instead of un-hanging first.voids?: boolean: Allow insertion into void elements.batchDirty?: boolean: Batch dirty-path work for the fragment insert.
tx.fragment.delete(options?)
Delete the fragment at options.at or the transaction target.
Options:
at?: NodeTarget: Location or live descendant to delete. Defaults to the transaction target.direction?: 'forward' | 'backward': Direction used for collapsed deletion.
Text methods
tx.text.insert(text: string, options?)
Insert text at options.at or the transaction target.
Options:
at?: NodeTarget: Where to insert. Defaults to the transaction target.voids?: boolean: Allow insertion into void elements.
When at is an expanded range, the inserted text replaces the range and the
selection moves after the inserted text.
tx.text.delete(options?)
Delete text at options.at or the transaction target.
Options:
at?: NodeTarget: Location or live descendant to delete from. Defaults to the transaction target.distance?: number: Number of units to delete. Defaults to one unit.unit?: 'character' | 'word' | 'line' | 'block': Unit used for collapsed deletion.reverse?: boolean: Delete before the target instead of after it.hanging?: boolean: Preserve hanging range edges instead of un-hanging first.voids?: boolean: Allow deletion inside void elements.
editor.update((tx) => {
tx.text.delete({ reverse: true, unit: "word" });
});editor.update((tx) => {
tx.text.delete({ reverse: true, unit: "word" });
});tx.text.deleteBackward(options?)
Delete before the transaction target.
Options:
unit?: 'character' | 'word' | 'line' | 'block': Unit to delete. Defaults to one character.
tx.text.deleteForward(options?)
Delete after the transaction target.
Options:
unit?: 'character' | 'word' | 'line' | 'block': Unit to delete. Defaults to one character.
Selection methods
tx.selection reads the transaction selection and exposes the same query
predicates as editor.read.selection: contains(target),
intersects(target), isCollapsed(), isExpanded(), isWithinText(),
isWithinBlock(options?), isAcrossBlocks(options?),
isAtBlockStart(options?), and isAtBlockEnd(options?).
tx.selection.set(target: Location | null)
Set the selection to a new target.
editor.update((tx) => {
tx.selection.set({
anchor: { path: [0, 0], offset: 0 },
focus: { path: [1, 0], offset: 0 },
});
});editor.update((tx) => {
tx.selection.set({
anchor: { path: [0, 0], offset: 0 },
focus: { path: [1, 0], offset: 0 },
});
});tx.selection.clear()
Clear the selection.
tx.selection.collapse(options?)
Collapse the selection to a single point.
Options:
edge?: 'anchor' | 'focus' | 'start' | 'end': Edge to collapse to.
tx.selection.move(options?)
Move the selection by offset, character, word, line, or block.
Options:
distance?: number: Number of units to move.unit?: 'offset' | 'character' | 'word' | 'line': Unit used for movement.reverse?: boolean: Move backward.edge?: 'anchor' | 'focus' | 'start' | 'end': Selection edge to move.
tx.selection.setPoint(props: Partial<Point>, options?)
Set properties on one selection point.
Options:
edge?: 'anchor' | 'focus' | 'start' | 'end': Selection edge to update.
tx.selection.setRange(props: Partial<Range>)
Set properties on an active selection.
Mark methods
tx.marks()
Return the active marks for the transaction.
tx.marks.add(key: string, value: unknown)
Add a mark to the current selection or pending marks.
tx.marks.remove(key: string)
Remove a mark from the current selection or pending marks.
tx.marks.set(marks: Record<string, unknown> | null)
Replace the pending insertion marks. Use {} to force plain inserted text at a
collapsed selection, or null to let inserted text inherit from the selected
text position.
tx.marks.toggle(key: string, value?, options?)
Toggle a mark for the current selection or pending marks.
options.clear?: string | string[]: Remove mutually exclusive marks before enabling the target mark. If the target mark is active, only the target mark is removed.
Value and root methods
Use value and root methods for whole-root or whole-document replacement. Normal
typing commands should use tx.text, tx.nodes, tx.fragment, or
tx.selection.
For one-shot snapshot imports, call the direct update method:
editor.update({ history: "skip" }).value.replace({
children: [{ type: "paragraph", children: [{ text: "Imported" }] }],
selection: "end",
});editor.update({ history: "skip" }).value.replace({
children: [{ type: "paragraph", children: [{ text: "Imported" }] }],
selection: "end",
});selection accepts a range, null, "start", or "end". Configure history
and tags through editor.update(policy) before calling the direct method.
tx.value.replace(input: SnapshotInput)
Replace the active root or complete snapshot inside a larger transaction.
editor.update((tx) => {
tx.value.replace({
children: [{ type: "paragraph", children: [{ text: "Imported" }] }],
selection: null,
});
});editor.update((tx) => {
tx.value.replace({
children: [{ type: "paragraph", children: [{ text: "Imported" }] }],
selection: null,
});
});Pass roots in the input when replacing multiple roots at once, or combine
tx.value.replace, tx.roots, and tx.setField when the import also updates
document meta fields.
tx.roots.create(root: RootKey, children: Node[])
Create a named root.
tx.roots.replace(root: RootKey, children: Node[])
Replace an existing named root.
tx.roots.delete(root: RootKey)
Delete an extra root. The primary document is not deleted through tx.roots.
State field methods
tx.setField(field, value)
Write a registered state field.
editor.update((tx) => {
tx.setField(documentTitle, "Q3 Launch Brief");
});editor.update((tx) => {
tx.setField(documentTitle, "Q3 Launch Brief");
});State-field writes appear in commit.statePatches.
tx.statePatches.replay(statePatches)
Replay accepted state-field patches through the transaction boundary.
Filter remote or collaborative patches before replaying them.
Normalization methods
tx.normalize(options?)
Run an explicit normalization barrier inside the active transaction. Normal grouped updates already normalize before commit; use this only when subsequent transaction logic must read the repaired tree.
Operation methods
tx.operations.replay(operations: Operation[])
Replay operations through the transaction boundary.
editor.update({ tags: "remote-import" }, (tx) => {
tx.operations.replay(remoteOperations);
});editor.update({ tags: "remote-import" }, (tx) => {
tx.operations.replay(remoteOperations);
});On This Page
Basic UsageOn This PageNode optionsNode methodstx.nodes.insert(nodes: Node | Node[], options?)tx.nodes.remove(options?)tx.nodes.merge(options?)tx.nodes.split(options?)tx.nodes.wrap(element: Element, options?)tx.nodes.unwrap(options?)tx.nodes.set(props: Partial<Node>, options?)tx.nodes.unset(props: string | string[], options?)tx.nodes.lift(options?)tx.nodes.move(options)Block methodstx.blocks.insertAfter(blocks, options?)tx.blocks.duplicate(options?)tx.blocks.lift(options?)tx.blocks.reset(props, options?)tx.blocks.toggle(type, options?)Break methodstx.break.insert()tx.break.insertSoft()Fragment methodstx.fragment(options?)tx.fragment.insert(fragment: Node[], options?)tx.fragment.delete(options?)Text methodstx.text.insert(text: string, options?)tx.text.delete(options?)tx.text.deleteBackward(options?)tx.text.deleteForward(options?)Selection methodstx.selection.set(target: Location | null)tx.selection.clear()tx.selection.collapse(options?)tx.selection.move(options?)tx.selection.setPoint(props: Partial<Point>, options?)tx.selection.setRange(props: Partial<Range>)Mark methodstx.marks()tx.marks.add(key: string, value: unknown)tx.marks.remove(key: string)tx.marks.set(marks: Record<string, unknown> | null)tx.marks.toggle(key: string, value?, options?)Value and root methodstx.value.replace(input: SnapshotInput)tx.roots.create(root: RootKey, children: Node[])tx.roots.replace(root: RootKey, children: Node[])tx.roots.delete(root: RootKey)State field methodstx.setField(field, value)tx.statePatches.replay(statePatches)Normalization methodstx.normalize(options?)Operation methodstx.operations.replay(operations: Operation[])