This page predates the current package split. Use the current package guides for checked installation, public imports, and onboarding examples. The detailed examples below have not all been revalidated.
Model Operation DSL API
DSL (Domain-Specific Language) helpers provide a simple, declarative API for defining operations. They return { type, payload } objects that are used in transactions.
Overview
DSL helpers are defined using defineOperationDSL() and are used with control() to create transaction operations.
Usage Pattern
import { insertText, control, transaction } from '@barocss/model';
// DSL helper returns { type, payload }
const op = insertText(5, 'Hello');
// { type: 'insertText', payload: { pos: 5, text: 'Hello' } }
// With control (injects nodeId)
const ops = control('text-1', [
insertText(5, 'Hello')
]);
// [{ type: 'insertText', payload: { nodeId: 'text-1', pos: 5, text: 'Hello' } }]
// Use in transaction
const result = await transaction(editor, ops).commit();
Control Function
The control() function injects a nodeId into operation payloads:
control(nodeId, [
insertText(5, 'Hello'),
toggleMark('bold', [0, 5])
])
// Becomes:
[
{ type: 'insertText', payload: { nodeId, pos: 5, text: 'Hello' } },
{ type: 'toggleMark', payload: { nodeId, markType: 'bold', range: [0, 5] } }
]
Text Operations
insertText
Inserts text at a position.
Signature:
insertText(pos: number, text: string): DSLOperationDescriptor
insertText(nodeId: string, pos: number, text: string): DSLOperationDescriptor
Returns:
{
type: 'insertText';
payload: { pos: number; text: string; nodeId?: string };
}
Example:
// In control chain
control('text-1', [
insertText(5, 'Hello')
])
// Direct call
insertText('text-1', 5, 'Hello')
deleteTextRange
Deletes text in a range.
Signature:
deleteTextRange(startPosition: number, endPosition: number): DSLOperationDescriptor
deleteTextRange(nodeId: string, startPosition: number, endPosition: number): DSLOperationDescriptor
Returns:
{
type: 'deleteTextRange';
payload: { startPosition: number; endPosition: number; nodeId?: string };
}
Example:
control('text-1', [
deleteTextRange(0, 5)
])
replaceText
Replaces text in a range.
Signature:
replaceText(newText: string): DSLOperationDescriptor
replaceText(nodeId: string, newText: string): DSLOperationDescriptor
replaceText(nodeId: string, startPosition: number, endPosition: number, newText: string): DSLOperationDescriptor
Returns:
{
type: 'replaceText';
payload: { newText: string; nodeId?: string; startPosition?: number; endPosition?: number };
}
Example:
control('text-1', [
replaceText('New text')
])
// Or with range
replaceText('text-1', 0, 5, 'New text')
Node Operations
create
Creates a node with children.
Signature:
create(stype: string, attributes?: Record<string, any>, content?: INode[]): DSLOperationDescriptor
Returns:
{
type: 'create';
payload: { node: INode; options?: any };
}
Example:
// Create paragraph with text
create('paragraph', {}, [
{ stype: 'inline-text', text: 'Hello' }
])
// Create heading
create('heading', { level: 1 }, [
{ stype: 'inline-text', text: 'Title' }
])
delete
Deletes a node.
Signature:
delete(): DSLOperationDescriptor
delete(nodeId: string): DSLOperationDescriptor
Returns:
{
type: 'delete';
payload: { nodeId?: string };
}
Example:
// In control chain
control('node-1', [
delete()
])
// Direct call
delete('node-1')
update
Updates a node with partial changes.
Signature:
update(updates: Partial<INode>): DSLOperationDescriptor
Returns:
{
type: 'update';
payload: { updates: Partial<INode>; nodeId?: string };
}
Example:
control('text-1', [
update({ text: 'Updated text' })
])
control('node-1', [
update({ attributes: { level: 2 } })
])
Content Operations
addChild
Adds a child to a parent.
Signature:
addChild(child: INode | string, position?: number): DSLOperationDescriptor
addChild(nodeId: string, child: INode | string, position?: number): DSLOperationDescriptor
Returns:
{
type: 'addChild';
payload: { child: INode | string; position?: number; nodeId?: string };
}
Example:
// Add existing node
control('parent-1', [
addChild('child-1', 0)
])
// Create and add new node
control('parent-1', [
addChild({ stype: 'paragraph', text: 'New' }, 0)
])
removeChild
Removes a child from parent.
Signature:
removeChild(childId: string): DSLOperationDescriptor
removeChild(nodeId: string, childId: string): DSLOperationDescriptor
Returns:
{
type: 'removeChild';
payload: { childId: string; nodeId?: string };
}
Example:
control('parent-1', [
removeChild('child-1')
])
moveNode
Moves a node to a new parent.
Signature:
moveNode(newParentId: string, position?: number): DSLOperationDescriptor
moveNode(nodeId: string, newParentId: string, position?: number): DSLOperationDescriptor
Returns:
{
type: 'moveNode';
payload: { newParentId: string; position?: number; nodeId?: string };
}
Example:
control('node-1', [
moveNode('new-parent-1', 0)
])
reorderChildren
Reorders children in a parent.
Signature:
reorderChildren(childIds: string[]): DSLOperationDescriptor
reorderChildren(nodeId: string, childIds: string[]): DSLOperationDescriptor
Returns:
{
type: 'reorderChildren';
payload: { childIds: string[]; nodeId?: string };
}
Example:
control('parent-1', [
reorderChildren(['child-3', 'child-1', 'child-2'])
])
Mark Operations
applyMark
Applies a mark to a range.
Signature:
applyMark(markType: string, range: [number, number], attrs?: Record<string, any>): DSLOperationDescriptor
applyMark(nodeId: string, markType: string, range: [number, number], attrs?: Record<string, any>): DSLOperationDescriptor
Returns:
{
type: 'applyMark';
payload: { markType: string; range: [number, number]; attrs?: Record<string, any>; nodeId?: string };
}
Example:
control('text-1', [
applyMark('bold', [0, 5]),
applyMark('link', [0, 5], { href: 'https://example.com' })
])
removeMark
Removes a mark from a range.
Signature:
removeMark(markType: string, range?: [number, number]): DSLOperationDescriptor
removeMark(nodeId: string, markType: string, range?: [number, number]): DSLOperationDescriptor
Returns:
{
type: 'removeMark';
payload: { markType: string; range?: [number, number]; nodeId?: string };
}
Example:
control('text-1', [
removeMark('bold', [0, 5])
])
toggleMark
Toggles a mark on/off.
Signature:
toggleMark(markType: string, range: [number, number], attrs?: Record<string, any>): DSLOperationDescriptor
toggleMark(nodeId: string, markType: string, range: [number, number], attrs?: Record<string, any>): DSLOperationDescriptor
Returns:
{
type: 'toggleMark';
payload: { markType: string; range: [number, number]; attrs?: Record<string, any>; nodeId?: string };
}
Example:
control('text-1', [
toggleMark('bold', [0, 5])
])
Split/Merge Operations
splitTextNode
Splits a text node at a position.
Signature:
splitTextNode(splitPosition: number): DSLOperationDescriptor
splitTextNode(nodeId: string, splitPosition: number): DSLOperationDescriptor
Returns:
{
type: 'splitTextNode';
payload: { splitPosition: number; nodeId?: string };
}
Example:
control('text-1', [
splitTextNode(5)
])
mergeTextNodes
Merges two adjacent text nodes.
Signature:
mergeTextNodes(rightNodeId: string): DSLOperationDescriptor
mergeTextNodes(nodeId: string, rightNodeId: string): DSLOperationDescriptor
Returns:
{
type: 'mergeTextNodes';
payload: { rightNodeId: string; nodeId?: string };
}
Example:
control('text-1', [
mergeTextNodes('text-2')
])
splitBlockNode
Splits a block node at a position.
Signature:
splitBlockNode(splitPosition: number): DSLOperationDescriptor
splitBlockNode(nodeId: string, splitPosition: number): DSLOperationDescriptor
Example:
control('block-1', [
splitBlockNode(2)
])
mergeBlockNodes
Merges two adjacent block nodes.
Signature:
mergeBlockNodes(rightNodeId: string): DSLOperationDescriptor
mergeBlockNodes(nodeId: string, rightNodeId: string): DSLOperationDescriptor
Example:
control('block-1', [
mergeBlockNodes('block-2')
])
Transform Operations
wrap
Wraps a range with a new node.
Signature:
wrap(wrapperType: string, wrapperAttrs?: Record<string, any>): DSLOperationDescriptor
wrap(nodeId: string, endNodeId: string, wrapperType: string, wrapperAttrs?: Record<string, any>): DSLOperationDescriptor
Example:
// Wrap selection
wrap('blockquote', {})
// Or with explicit range
wrap('text-1', 'text-3', 'blockquote', {})
unwrap
Removes wrapper node.
Signature:
unwrap(): DSLOperationDescriptor
unwrap(nodeId: string): DSLOperationDescriptor
Example:
control('wrapper-1', [
unwrap()
])
indentNode / outdentNode
Indents or outdents a block node.
Signature:
indentNode(): DSLOperationDescriptor
indentNode(nodeId: string): DSLOperationDescriptor
outdentNode(): DSLOperationDescriptor
outdentNode(nodeId: string): DSLOperationDescriptor
Example:
control('block-1', [
indentNode()
])
control('block-1', [
outdentNode()
])
indentText / outdentText
Indents or outdents text.
Signature:
indentText(prefix?: string): DSLOperationDescriptor
indentText(nodeId: string, prefix?: string): DSLOperationDescriptor
outdentText(prefix?: string): DSLOperationDescriptor
outdentText(nodeId: string, prefix?: string): DSLOperationDescriptor
Example:
control('text-1', [
indentText(' ')
])
control('text-1', [
outdentText(' ')
])
Clipboard Operations
copy
Copies selected content.
Signature:
copy(): DSLOperationDescriptor
Example:
// Uses current selection
const ops = [copy()];
cut
Cuts selected content.
Signature:
cut(): DSLOperationDescriptor
Example:
// Uses current selection
const ops = [cut()];
paste
Pastes content at selection.
Signature:
paste(content?: INode[]): DSLOperationDescriptor
Example:
// Paste from clipboard
const ops = [paste()];
// Paste specific content
const ops = [paste([
{ stype: 'paragraph', text: 'Pasted' }
])];
Utility Operations
autoMergeTextNodes
Automatically merges adjacent text nodes.
Signature:
autoMergeTextNodes(): DSLOperationDescriptor
autoMergeTextNodes(nodeId: string): DSLOperationDescriptor
Example:
control('text-1', [
autoMergeTextNodes()
])
cloneNodeWithChildren
Clones a node with all its children.
Signature:
cloneNodeWithChildren(newParentId?: string): DSLOperationDescriptor
cloneNodeWithChildren(nodeId: string, newParentId?: string): DSLOperationDescriptor
Example:
control('node-1', [
cloneNodeWithChildren('new-parent-1')
])
Complete Example
import { transaction, control, insertText, toggleMark, create } from '@barocss/model';
// Complex transaction with multiple operations
const result = await transaction(editor, [
// Create new paragraph
create('paragraph', {}, [
{ stype: 'inline-text', text: 'Hello' }
]),
// Insert text and apply mark
...control('text-1', [
insertText(5, ' World'),
toggleMark('bold', [0, 11])
]),
// Move node
...control('node-1', [
moveNode('new-parent-1', 0)
])
]).commit();
Related
- Operations Overview - Understanding the operation hierarchy
- DataStore Operations API - DataStore layer operations
- Model Operations API - Model layer operations
- Operation Selection Guide - How to choose operations