Skip to main content
Reference status

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();