edytor/crdt/edytor
Every name edytor/crdt/edytor exports, with its declaration and documentation (generated from the published types).
Every name edytor/crdt/edytor exports, generated from the package’s published type declarations, with the documentation its JSDoc carries. The guides explain how the pieces fit; this page is the exhaustive list. 119 names.
ActorId
The durable per-block attribution record a replica sees.
export type ActorId = string;
ActorProfile
Replicated actor profile record payload (u/ values).
export type ActorProfile = {
name?: string;
color?: string;
};
AnchorAffinity
Selection-endpoint affinity — which side of a position the anchor binds
to (see T.atomAnchorAt):
'left'— bound to the atom BEFORE the position; resolves right after it, so a concurrent insert exactly at the position lands to the anchor’s right. Used for carets and range ENDS.'right'— bound to the atom AT the position; resolves right before it, so a concurrent insert lands to the anchor’s left — outside a range starting here. Used for range STARTS.
export type AnchorAffinity = 'left' | 'right';
attachDocument
See DocumentBinding.attachDocument.
declare const attachDocument: (doc: YDoc, options?: DocumentOptions) => EdytorDocument;
AttributionActor
The stable application-level author identity (mirrors DocumentActor).
export type AttributionActor = {
id: string;
name?: string;
color?: string;
};
AttributionController
export type AttributionController = {
readonly view: DocumentAttribution;
setProfile(profile: ActorProfile): void;
destroy(): void;
};
view: The public read surface handed toEdytorDocument.attribution.setProfile: Re-publish the local actor’s profile record (u/<actorId>LWW).destroy: Release the controller;setProfilebecomes a no-op.
Awareness
Simple shared state protocol for non-persistent data (cursor, username,
status…). Semantics are verbatim upstream: clock-ordered LWW per client,
remote null states mark peers offline, local state is re-published when
outdated, and remote states expire after outdatedTimeout.
export declare class Awareness extends IsolatedObservable<AwarenessEvents> {
#private;
doc: AwarenessDoc;
clientID: number;
states: AwarenessStates;
meta: Map<number, MetaClientState>;
private _destroyed;
constructor(doc: AwarenessDoc);
destroy(): void;
getLocalState(): Record<string, unknown> | null;
setLocalState(state: Record<string, unknown> | null): void;
setLocalStateField(field: string, value: unknown): void;
getStates(): AwarenessStates;
}
states: Maps from client id to client state
AwarenessDoc
Structural minimum an Awareness host must satisfy. Y.Doc (vendored v14)
satisfies this; the structural type keeps Awareness free of any engine
runtime import.
export interface AwarenessDoc {
clientID: number;
on(name: 'destroy', f: (doc: unknown) => void): void;
}
AwarenessStates
export type AwarenessStates = Map<number, Record<string, unknown>>;
AwarenessUpdate
export type AwarenessUpdate = {
added: number[];
updated: number[];
removed: number[];
};
bindCrdt
declare const bindCrdt: (Y: EngineApi) => {
createDoc: (opts?: ConstructorParameters<EngineApi["Doc"]>[0]) => YDoc;
Awareness: typeof _Awareness;
doc: {
SCHEMA: {
readonly version: 6;
readonly name: "edytor-doc";
readonly roots: {
readonly registry: "blocks";
readonly meta: "meta";
};
readonly metaAttrs: {
readonly version: "v";
readonly schema: "schema";
};
};
SCHEMA_VERSION: 6;
SCHEMA_NAME: "edytor-doc";
META_KEY: "meta";
init: (doc: import("./engine-api.js").EngineDoc, opts?: {
content?: import("./index.js").BlockSpec[];
defaultType?: string;
}) => void;
restore: (doc: import("./engine-api.js").EngineDoc, content: import("./index.js").BlockSpec[]) => void;
seed: (doc: import("./engine-api.js").EngineDoc, value?: import("./index.js").JSONBlock[], defaultType?: string, data?: import("./doc/types.js").JsonObj) => void;
isInitialized: (doc: import("./engine-api.js").EngineDoc) => boolean;
schemaVersion: (doc: import("./engine-api.js").EngineDoc) => number | undefined;
registryEmpty: (doc: import("./engine-api.js").EngineDoc) => boolean;
checkSchema: (doc: import("./engine-api.js").EngineDoc) => import("./edytor-doc.js").SchemaProblem | null;
assertSchema: (doc: import("./engine-api.js").EngineDoc, docName?: string) => void;
SchemaMismatchError: typeof import("./edytor-doc.js").SchemaMismatchError;
create: (doc: import("./engine-api.js").EngineDoc, config?: import("./edytor-doc.js").EdytorDocConfig) => {
prepare: {
insertFlow: (target: import("./flow.js").FlowTarget, flow: import("./flow.js").Flow, view?: import("./flow.js").FlowView) => import("./edytor-doc.js").Prepared;
deleteRange: (from: import("./rangeDelete.js").DocPosition, to: import("./rangeDelete.js").DocPosition, view?: import("./rangeDelete.js").RangeView) => import("./edytor-doc.js").Prepared;
replaceRange: (from: import("./rangeDelete.js").DocPosition, to: import("./rangeDelete.js").DocPosition, view?: import("./rangeDelete.js").RangeView) => import("./edytor-doc.js").Prepared;
insertBlocks: (dest: import("./index.js").Destination, specs: readonly (import("./index.js").BlockSpec | import("./index.js").JSONBlock)[]) => import("./edytor-doc.js").Prepared;
moveBlocks: (ids: readonly import("./index.js").BlockId[], dest: import("./index.js").Destination) => import("./edytor-doc.js").Prepared;
nestBlock: (id: import("./index.js").BlockId, parent: import("./index.js").BlockId) => import("./edytor-doc.js").Prepared;
unNestBlock: (id: import("./index.js").BlockId) => import("./edytor-doc.js").Prepared;
unNestBlocks: (ids: readonly import("./index.js").BlockId[]) => import("./edytor-doc.js").Prepared;
liftOut: (id: import("./index.js").BlockId, kind: string, { keep, after }?: {
keep?: boolean;
after?: readonly import("./index.js").BlockSpec[];
}) => import("./edytor-doc.js").Prepared;
placeBeside: (ids: readonly import("./index.js").BlockId[], target: import("./index.js").BlockId, side: "left" | "right", kind?: string) => import("./edytor-doc.js").Prepared;
wrapInLayout: (ids: readonly import("./index.js").BlockId[], kind?: string, columns?: number) => import("./edytor-doc.js").Prepared;
splitBlock: (id: import("./index.js").BlockId, offset: number, newId: import("./index.js").BlockId, tail?: import("./placement/model.js").SplitTail) => import("./edytor-doc.js").Prepared;
mergeBlocks: (fromId: import("./index.js").BlockId, intoId: import("./index.js").BlockId) => import("./edytor-doc.js").Prepared;
mergeBackward: (id: import("./index.js").BlockId) => import("./edytor-doc.js").Prepared;
mergeForward: (id: import("./index.js").BlockId) => import("./edytor-doc.js").Prepared;
deleteBlock: (id: import("./index.js").BlockId, opts?: {
keepChildren?: boolean;
}) => import("./edytor-doc.js").Prepared;
setBlock: (id: import("./index.js").BlockId, value: {
type?: string;
data?: Record<string, unknown>;
content?: (import("./index.js").ContentItem | import("./index.js").JSONText | import("./index.js").JSONInlineBlock)[];
children?: (import("./index.js").BlockSpec | import("./index.js").JSONBlock)[];
}) => import("./edytor-doc.js").Prepared;
setBlockType: (id: import("./index.js").BlockId, type: string) => import("./edytor-doc.js").Prepared;
patchData: (target: import("./edytor-doc.js").DataTarget, patches: readonly import("./data.js").DataPatch[]) => import("./edytor-doc.js").Prepared;
duplicateBlock: (id: import("./index.js").BlockId, freshId?: (oldId: string, kind: "block" | "inline") => string) => import("./edytor-doc.js").Prepared;
insertText: (id: import("./index.js").BlockId, offset: number, text: string, marks?: Record<string, unknown>) => import("./edytor-doc.js").Prepared;
deleteText: (id: import("./index.js").BlockId, offset: number, length: number) => import("./edytor-doc.js").Prepared;
formatRange: (id: import("./index.js").BlockId, offset: number, length: number, marks: Record<string, unknown>) => import("./edytor-doc.js").Prepared;
clearMarks: (id: import("./index.js").BlockId, offset: number, length: number) => import("./edytor-doc.js").Prepared;
insertInline: (id: import("./index.js").BlockId, offset: number, atom: import("./doc/content.js").NewInline) => import("./edytor-doc.js").Prepared;
removeInline: (id: import("./index.js").BlockId, inlineId: string) => import("./edytor-doc.js").Prepared;
deleteBlocks: (ids: readonly import("./index.js").BlockId[]) => import("./edytor-doc.js").Prepared;
};
apply: (p: import("./edytor-doc.js").Prepared) => import("./edytor-doc.js").OpResult;
compose: (...parts: import("./edytor-doc.js").Prepared[]) => import("./edytor-doc.js").Prepared;
transact: <R>(fn: () => R, origin?: unknown) => R;
model: {
REGISTRY_KEY: string;
registryOf: (doc: import("./engine-api.js").EngineDoc) => import("./engine-api.js").EngineNode;
blockNodeOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
liveNodeOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
isLive: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => boolean;
candidatesOf: (node: import("./engine-api.js").EngineNode) => import("./placement/model.js").PlacementCand[];
view: (doc: import("./engine-api.js").EngineDoc) => import("./placement/model.js").ModelView;
resolvePlacements: (blocks: Map<import("./index.js").BlockId, import("./placement/model.js").BlockRec>, ownerOf?: (b: import("./index.js").BlockId) => import("./text/model.js").Owner) => Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>;
childrenIndex: (placements: Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>, own: import("./placement/model.js").DisplayOwnership) => Map<import("./index.js").BlockId | null, import("./placement/model.js").ChildSlot[]>;
positionInView: (v: import("./placement/model.js").ModelView, id: import("./index.js").BlockId) => import("./index.js").Destination | null;
buildInline: (atom: import("./index.js").InlineSpec) => import("./engine-api.js").EngineNode;
isSelfOrDescendant: (placements: Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>, own: import("./text/model.js").Ownership, id: import("./index.js").BlockId, maybeAncestor: import("./index.js").BlockId) => boolean;
ranksAt: (siblings: readonly {
rank: string;
}[], index: number, count: number, clientId: number, rand?: () => number, run?: boolean) => string[];
writePlacement: (doc: import("./engine-api.js").EngineDoc, node: import("./engine-api.js").EngineNode, p: import("./index.js").BlockId | null, r: string) => void;
withdrawOnUndo: (doc: import("./engine-api.js").EngineDoc) => (item: import("./engine-api.js").EngineItemRef, stackItem: {
inserts: {
has(client: number, clock: number): boolean;
};
}) => boolean;
materializeSpec: (doc: import("./engine-api.js").EngineDoc, sp: import("./index.js").BlockSpec, parent: import("./index.js").BlockId | null, rank: string) => void;
collides: (doc: import("./engine-api.js").EngineDoc, specs: readonly import("./index.js").BlockSpec[]) => boolean;
writeSplit: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId, offset: number, newId: import("./index.js").BlockId, tail: import("./placement/model.js").SplitTail, place: import("./placement/model.js").PlacementValue) => void;
ownText: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => {
from: unknown;
to: number;
};
insertBlocks: (doc: import("./engine-api.js").EngineDoc, dest: import("./index.js").Destination, specs: import("./index.js").BlockSpec[]) => boolean;
insertBlock: (doc: import("./engine-api.js").EngineDoc, dest: import("./index.js").Destination, spec: import("./index.js").BlockSpec) => boolean;
restoreBlocks: (doc: import("./engine-api.js").EngineDoc, specs: import("./index.js").BlockSpec[]) => void;
project: (doc: import("./engine-api.js").EngineDoc) => import("./index.js").ProjectedDoc;
positionOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./index.js").Destination | null;
listBlockIds: (doc: import("./engine-api.js").EngineDoc) => import("./index.js").BlockId[];
blockText: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => string | null;
crdtId: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => string | null;
resolveBlock: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
};
text: {
newNode: (name: string) => import("./engine-api.js").EngineNode;
resolveAnchor: (doc: import("./engine-api.js").EngineDoc, text: import("./engine-api.js").EngineNode, anchor: import("./text/model.js").Anchor) => number | null;
anchorAt: (text: import("./engine-api.js").EngineNode, index: number, assoc: number) => import("./text/model.js").Anchor;
openRangeCursor: (text: import("./engine-api.js").EngineNode) => import("./text/model.js").RangeCursor;
itemsOfRange: (text: import("./engine-api.js").EngineNode, i0: number, i1: number) => import("./text/model.js").RangeItem[];
readSegs: (segs: readonly import("./text/model.js").Seg[], stats?: import("./text/model.js").RangeReadStats) => import("./text/model.js").RangeItem[];
computeOwnership: (doc: import("./engine-api.js").EngineDoc, given: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>) => import("./text/model.js").Ownership;
flatten: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => import("./text/model.js").Seg[];
ownedLength: (segs: readonly import("./text/model.js").Seg[]) => number;
contentItemsOf: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => import("./text/model.js").RangeItem[];
blockTextOf: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => string;
insertIntoText: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, payload: string | import("./engine-api.js").EngineNode, marks?: Record<string, unknown>) => void;
deleteRange: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, length: number) => void;
formatRangeIn: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, length: number, formats: Record<string, unknown>) => void;
purgeStreams: (streams: readonly import("./text/model.js").Stream[]) => void;
findAtom: (own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, inlineId: string) => {
text: import("./engine-api.js").EngineNode;
at: number;
node: import("./engine-api.js").EngineNode;
} | null;
splitAt: (blocks: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, newId: import("./text/model.js").BlockId, n: number) => import("./text/model.js").MergeClaim[];
claimInto: (blocks: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>, own: Pick<import("./text/model.js").Ownership, "streamOf">, from: import("./text/model.js").BlockId, into: import("./text/model.js").BlockId) => void;
ownText: (doc: import("./engine-api.js").EngineDoc, rec: import("./text/model.js").TextBlockRec) => {
from: unknown;
to: number;
};
};
runsView: import("./text/runs.js").RunView;
version: number;
insertFlow: (target: import("./flow.js").FlowTarget, flow: import("./flow.js").Flow, view?: import("./flow.js").FlowView | undefined) => import("./edytor-doc.js").OpResult;
deleteRange: (from: import("./rangeDelete.js").DocPosition, to: import("./rangeDelete.js").DocPosition, view?: import("./rangeDelete.js").RangeView | undefined) => import("./edytor-doc.js").OpResult;
replaceRange: (from: import("./rangeDelete.js").DocPosition, to: import("./rangeDelete.js").DocPosition, view?: import("./rangeDelete.js").RangeView | undefined) => import("./edytor-doc.js").OpResult;
insertBlocks: (dest: import("./index.js").Destination, specs: readonly (import("./index.js").BlockSpec | import("./index.js").JSONBlock)[]) => import("./edytor-doc.js").OpResult;
moveBlocks: (ids: readonly string[], dest: import("./index.js").Destination) => import("./edytor-doc.js").OpResult;
nestBlock: (id: string, parent: string) => import("./edytor-doc.js").OpResult;
unNestBlock: (id: string) => import("./edytor-doc.js").OpResult;
unNestBlocks: (ids: readonly string[]) => import("./edytor-doc.js").OpResult;
liftOut: (id: string, kind: string, args_2?: {
keep?: boolean;
after?: readonly import("./index.js").BlockSpec[];
} | undefined) => import("./edytor-doc.js").OpResult;
placeBeside: (ids: readonly string[], target: string, side: "right" | "left", kind?: string | undefined) => import("./edytor-doc.js").OpResult;
wrapInLayout: (ids: readonly string[], kind?: string | undefined, columns?: number | undefined) => import("./edytor-doc.js").OpResult;
splitBlock: (id: string, offset: number, newId: string, tail?: import("./placement/model.js").SplitTail | undefined) => import("./edytor-doc.js").OpResult;
mergeBlocks: (fromId: string, intoId: string) => import("./edytor-doc.js").OpResult;
mergeBackward: (id: string) => import("./edytor-doc.js").OpResult;
mergeForward: (id: string) => import("./edytor-doc.js").OpResult;
deleteBlock: (id: string, opts?: {
keepChildren?: boolean;
} | undefined) => import("./edytor-doc.js").OpResult;
setBlock: (id: string, value: {
type?: string;
data?: Record<string, unknown>;
content?: (import("./index.js").ContentItem | import("./index.js").JSONText | import("./index.js").JSONInlineBlock)[];
children?: (import("./index.js").BlockSpec | import("./index.js").JSONBlock)[];
}) => import("./edytor-doc.js").OpResult;
setBlockType: (id: string, type: string) => import("./edytor-doc.js").OpResult;
patchData: (target: import("./edytor-doc.js").DataTarget, patches: readonly import("./data.js").DataPatch[]) => import("./edytor-doc.js").OpResult;
duplicateBlock: (id: string, freshId?: ((oldId: string, kind: "block" | "inline") => string) | undefined) => import("./edytor-doc.js").OpResult;
insertText: (id: string, offset: number, text: string, marks?: Record<string, unknown> | undefined) => import("./edytor-doc.js").OpResult;
deleteText: (id: string, offset: number, length: number) => import("./edytor-doc.js").OpResult;
formatRange: (id: string, offset: number, length: number, marks: Record<string, unknown>) => import("./edytor-doc.js").OpResult;
clearMarks: (id: string, offset: number, length: number) => import("./edytor-doc.js").OpResult;
insertInline: (id: string, offset: number, atom: import("./doc/content.js").NewInline) => import("./edytor-doc.js").OpResult;
removeInline: (id: string, inlineId: string) => import("./edytor-doc.js").OpResult;
deleteBlocks: (ids: readonly string[]) => import("./edytor-doc.js").OpResult;
init: (opts?: Parameters<(doc: import("./engine-api.js").EngineDoc, opts?: {
content?: import("./index.js").BlockSpec[];
defaultType?: string;
}) => void>[1]) => void;
seed: (value: import("./index.js").JSONBlock[], data?: import("./doc/types.js").JsonObj) => void;
isInitialized: () => boolean;
schemaVersion: () => number | undefined;
checkSchema: () => import("./edytor-doc.js").SchemaProblem | null;
assertSchema: () => void;
dispose: () => void;
createUndoManager: (options?: import("./doc/history.js").HistoryOptions) => import("./doc/history.js").UndoManager;
project: () => import("./index.js").ProjectedDoc;
toJSON: () => import("./index.js").JSONDoc;
blockJSON: (id: string) => import("./index.js").JSONBlock;
childrenIds: (id: string | null) => string[];
childSlots: (parent: import("./index.js").BlockId | null) => import("./placement/model.js").ChildSlot[];
slotOf: (id: string) => {
parent: import("./index.js").BlockId | null;
rank: string;
} | null;
positionOf: (id: string) => import("./index.js").Destination | null;
pathOf: (id: string) => number[] | null;
parentOf: (id: string) => string | null;
ancestorsOf: (id: string) => string[];
listBlockIds: () => string[];
blockText: (id: string) => string | null;
blockTypeOf: (id: string) => string | undefined;
blockDataOf: (id: string) => Record<string, unknown> | undefined;
docData: () => import("./doc/types.js").JsonObj;
dataItemIds: (target: import("./edytor-doc.js").DataTarget, path: readonly string[]) => string[];
blockAttribution: (id: string) => import("./index.js").BlockAttribution | undefined;
crdtId: (id: string) => string | null;
resolveBlock: (id: string) => import("./engine-api.js").EngineNode | null;
displayLength: (id: string) => number;
contentItems: (id: string) => import("./index.js").ContentItem[];
hasBlock: (id: string) => boolean;
isVisibleBlock: (id: string) => boolean;
order: () => readonly import("./index.js").BlockId[];
compare: (a: import("./index.js").BlockId, b: import("./index.js").BlockId) => number;
next: (id: string, policy?: import("./edytor-doc.js").OrderPolicy | undefined) => string | null;
previous: (id: string, policy?: import("./edytor-doc.js").OrderPolicy | undefined) => string | null;
anchorAt: (id: string, offset: number, affinity?: import("./edytor-doc.js").AnchorAffinity | undefined) => import("./edytor-doc.js").DocAnchor | null;
resolveAnchor: (anchor: import("./edytor-doc.js").DocAnchor) => {
blockId: import("./index.js").BlockId;
offset: number;
} | null;
followUndo: (anchor: import("./edytor-doc.js").DocAnchor) => import("./edytor-doc.js").DocAnchor;
rolesChanged: () => void;
isVoid: (id: string) => boolean;
isIsland: (id: string) => boolean;
isLines: (id: string) => boolean;
isLayout: (id: string) => boolean;
isLayoutItem: (id: string) => boolean;
besideAt: (id: import("./index.js").BlockId, kind?: string) => string;
islandOf: (id: string) => string | null;
isTable: (id: string) => boolean;
isTableRow: (id: string) => boolean;
isTableCell: (id: string) => boolean;
tableOf: (id: string) => string | null;
tableColumns: (id: string) => {
id: string;
width?: number;
}[] | null;
tableGrid: (id: string) => {
columns: string[];
rows: {
id: import("./index.js").BlockId;
cells: (import("./index.js").BlockId | null)[];
}[];
} | null;
insideIsland: (id: string) => boolean;
canPlace: (ids: readonly import("./index.js").BlockId[], parent?: import("./index.js").BlockId | null) => boolean;
canMerge: (from: import("./index.js").BlockId, into: import("./index.js").BlockId) => boolean;
fits: (parent: import("./index.js").BlockId | null, kind: string) => boolean;
nestParent: (ids: readonly import("./index.js").BlockId[], parent: import("./index.js").BlockId) => string;
landingOf: (id: import("./index.js").BlockId, kind: string, after?: boolean) => {
parent: string | null;
levels: string[];
};
defaultChild: (id: string | null) => string;
runs: (id: string) => readonly import("./index.js").ContentRun[];
contentJSON: (id: string) => ({
text: string;
marks?: Record<string, unknown>;
} | {
id?: string;
type: string;
data?: unknown;
})[];
onChange: (cb: (change: import("./edytor-doc.js").DocChange) => void) => (() => void);
};
newDoc: (opts?: ConstructorParameters<EngineApi["Doc"]>[0]) => YDoc;
keepCopies: (doc: import("./engine-api.js").EngineDoc) => void;
purge: (doc: import("./engine-api.js").EngineDoc, facade: {
model: import("./placement/model.js").PlacementModel;
text: import("./text/model.js").TextEngine;
}, horizon: import("./purge.js").Horizon) => import("./purge.js").PurgeReport;
horizonOf: (doc: import("./engine-api.js").EngineDoc) => import("./purge.js").Horizon | null;
restoreTo: <Plan>(doc: import("./engine-api.js").EngineDoc, facade: import("./restore.js").RestoreFacade<Plan>, json: import("./index.js").JSONDoc) => import("./restore.js").RestoreReport;
model: {
REGISTRY_KEY: string;
registryOf: (doc: import("./engine-api.js").EngineDoc) => import("./engine-api.js").EngineNode;
blockNodeOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
liveNodeOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
isLive: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => boolean;
candidatesOf: (node: import("./engine-api.js").EngineNode) => import("./placement/model.js").PlacementCand[];
view: (doc: import("./engine-api.js").EngineDoc) => import("./placement/model.js").ModelView;
resolvePlacements: (blocks: Map<import("./index.js").BlockId, import("./placement/model.js").BlockRec>, ownerOf?: (b: import("./index.js").BlockId) => import("./text/model.js").Owner) => Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>;
childrenIndex: (placements: Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>, own: import("./placement/model.js").DisplayOwnership) => Map<import("./index.js").BlockId | null, import("./placement/model.js").ChildSlot[]>;
positionInView: (v: import("./placement/model.js").ModelView, id: import("./index.js").BlockId) => import("./index.js").Destination | null;
buildInline: (atom: import("./index.js").InlineSpec) => import("./engine-api.js").EngineNode;
isSelfOrDescendant: (placements: Map<import("./index.js").BlockId, import("./placement/model.js").ResolvedPlacement>, own: import("./text/model.js").Ownership, id: import("./index.js").BlockId, maybeAncestor: import("./index.js").BlockId) => boolean;
ranksAt: (siblings: readonly {
rank: string;
}[], index: number, count: number, clientId: number, rand?: () => number, run?: boolean) => string[];
writePlacement: (doc: import("./engine-api.js").EngineDoc, node: import("./engine-api.js").EngineNode, p: import("./index.js").BlockId | null, r: string) => void;
withdrawOnUndo: (doc: import("./engine-api.js").EngineDoc) => (item: import("./engine-api.js").EngineItemRef, stackItem: {
inserts: {
has(client: number, clock: number): boolean;
};
}) => boolean;
materializeSpec: (doc: import("./engine-api.js").EngineDoc, sp: import("./index.js").BlockSpec, parent: import("./index.js").BlockId | null, rank: string) => void;
collides: (doc: import("./engine-api.js").EngineDoc, specs: readonly import("./index.js").BlockSpec[]) => boolean;
writeSplit: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId, offset: number, newId: import("./index.js").BlockId, tail: import("./placement/model.js").SplitTail, place: import("./placement/model.js").PlacementValue) => void;
ownText: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => {
from: unknown;
to: number;
};
insertBlocks: (doc: import("./engine-api.js").EngineDoc, dest: import("./index.js").Destination, specs: import("./index.js").BlockSpec[]) => boolean;
insertBlock: (doc: import("./engine-api.js").EngineDoc, dest: import("./index.js").Destination, spec: import("./index.js").BlockSpec) => boolean;
restoreBlocks: (doc: import("./engine-api.js").EngineDoc, specs: import("./index.js").BlockSpec[]) => void;
project: (doc: import("./engine-api.js").EngineDoc) => import("./index.js").ProjectedDoc;
positionOf: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./index.js").Destination | null;
listBlockIds: (doc: import("./engine-api.js").EngineDoc) => import("./index.js").BlockId[];
blockText: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => string | null;
crdtId: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => string | null;
resolveBlock: (doc: import("./engine-api.js").EngineDoc, id: import("./index.js").BlockId) => import("./engine-api.js").EngineNode | null;
};
text: {
newNode: (name: string) => import("./engine-api.js").EngineNode;
resolveAnchor: (doc: import("./engine-api.js").EngineDoc, text: import("./engine-api.js").EngineNode, anchor: import("./text/model.js").Anchor) => number | null;
anchorAt: (text: import("./engine-api.js").EngineNode, index: number, assoc: number) => import("./text/model.js").Anchor;
openRangeCursor: (text: import("./engine-api.js").EngineNode) => import("./text/model.js").RangeCursor;
itemsOfRange: (text: import("./engine-api.js").EngineNode, i0: number, i1: number) => import("./text/model.js").RangeItem[];
readSegs: (segs: readonly import("./text/model.js").Seg[], stats?: import("./text/model.js").RangeReadStats) => import("./text/model.js").RangeItem[];
computeOwnership: (doc: import("./engine-api.js").EngineDoc, given: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>) => import("./text/model.js").Ownership;
flatten: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => import("./text/model.js").Seg[];
ownedLength: (segs: readonly import("./text/model.js").Seg[]) => number;
contentItemsOf: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => import("./text/model.js").RangeItem[];
blockTextOf: (b: import("./text/model.js").BlockId, blocks: unknown, own: import("./text/model.js").Ownership) => string;
insertIntoText: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, payload: string | import("./engine-api.js").EngineNode, marks?: Record<string, unknown>) => void;
deleteRange: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, length: number) => void;
formatRangeIn: (doc: import("./engine-api.js").EngineDoc, blocks: unknown, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, length: number, formats: Record<string, unknown>) => void;
purgeStreams: (streams: readonly import("./text/model.js").Stream[]) => void;
findAtom: (own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, inlineId: string) => {
text: import("./engine-api.js").EngineNode;
at: number;
node: import("./engine-api.js").EngineNode;
} | null;
splitAt: (blocks: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>, own: import("./text/model.js").Ownership, b: import("./text/model.js").BlockId, offset: number, newId: import("./text/model.js").BlockId, n: number) => import("./text/model.js").MergeClaim[];
claimInto: (blocks: ReadonlyMap<import("./text/model.js").BlockId, import("./text/model.js").TextBlockRec>, own: Pick<import("./text/model.js").Ownership, "streamOf">, from: import("./text/model.js").BlockId, into: import("./text/model.js").BlockId) => void;
ownText: (doc: import("./engine-api.js").EngineDoc, rec: import("./text/model.js").TextBlockRec) => {
from: unknown;
to: number;
};
};
runs: {
attach: (doc: import("./engine-api.js").EngineDoc) => import("./text/runs.js").RunView;
};
};
providers: {
prefetch: (options: PrefetchOptions) => Promise<import("./index.js").PrefetchResult>;
lastUpdated: (options: import("./index.js").LastUpdatedOptions) => Promise<number | null>;
documentSnapshot: (options: import("./index.js").LastUpdatedOptions) => Promise<import("./index.js").JSONDoc | null>;
IndexeddbPersistence: {
new (name: string, doc: YDoc, options?: import("./protocol.js").IndexeddbPersistenceOptions): {
doc: YDoc;
name: string;
dbName: string;
_dbref: number;
_dbsize: number;
db: IDBDatabase | null;
_db: Promise<IDBDatabase>;
_destroyed: boolean;
hasSynced: boolean;
whenSynced: Promise<any>;
_failedEmitted?: boolean;
_settleSynced: import("./providers/room.js").LifecycleHost["_settleSynced"];
_leave: () => void;
loadError: unknown;
_storeTimeout: number;
_storeTimeoutId: ReturnType<typeof setTimeout> | null;
_storeUpdate: (update: Uint8Array, origin: unknown) => void;
awareness: _Awareness;
bcconnected: boolean;
disableBc: boolean;
_ownsAwareness: boolean;
_bcSubscriber: (data: ArrayBuffer | Uint8Array, origin: unknown) => void;
_awarenessUpdateHandler: (updates: {
added: number[];
updated: number[];
removed: number[];
}, origin: unknown) => void;
get synced(): boolean;
messageHandlers: Record<number, import("./providers/room.js").RoomMessageHandler<any>>;
readMessage: (buf: Uint8Array, emitSynced: boolean) => import("lib0-v14/encoding").Encoder;
broadcastMessage(buf: Uint8Array): void;
connectBc(): void;
disconnectBc(): void;
destroy(): Promise<void>;
emit<N extends "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "load-error">(name: N, args: Parameters<{
synced: (provider: any) => void;
'protocol-mismatch': (mismatch: import("./protocol.js").ProtocolMismatch, provider: any) => void;
'load-error': (error: unknown, provider: any) => void;
'message-error': (error: unknown, provider: any) => void;
'schema-mismatch': (detail: import("./protocol.js").SchemaMismatchDetail, provider: any) => void;
failed: (error: unknown, provider: any) => void;
}[N]>): void;
_observers: Map<string, Set<any>>;
on<NAME extends "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
synced: (provider: any) => void;
'protocol-mismatch': (mismatch: import("./protocol.js").ProtocolMismatch, provider: any) => void;
'load-error': (error: unknown, provider: any) => void;
'message-error': (error: unknown, provider: any) => void;
'schema-mismatch': (detail: import("./protocol.js").SchemaMismatchDetail, provider: any) => void;
failed: (error: unknown, provider: any) => void;
}[NAME]): {
synced: (provider: any) => void;
'protocol-mismatch': (mismatch: import("./protocol.js").ProtocolMismatch, provider: any) => void;
'load-error': (error: unknown, provider: any) => void;
'message-error': (error: unknown, provider: any) => void;
'schema-mismatch': (detail: import("./protocol.js").SchemaMismatchDetail, provider: any) => void;
failed: (error: unknown, provider: any) => void;
}[NAME];
once<NAME extends "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
synced: (provider: any) => void;
'protocol-mismatch': (mismatch: import("./protocol.js").ProtocolMismatch, provider: any) => void;
'load-error': (error: unknown, provider: any) => void;
'message-error': (error: unknown, provider: any) => void;
'schema-mismatch': (detail: import("./protocol.js").SchemaMismatchDetail, provider: any) => void;
failed: (error: unknown, provider: any) => void;
}[NAME]): void;
off<NAME extends "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "load-error">(name: NAME, f: {
synced: (provider: any) => void;
'protocol-mismatch': (mismatch: import("./protocol.js").ProtocolMismatch, provider: any) => void;
'load-error': (error: unknown, provider: any) => void;
'message-error': (error: unknown, provider: any) => void;
'schema-mismatch': (detail: import("./protocol.js").SchemaMismatchDetail, provider: any) => void;
failed: (error: unknown, provider: any) => void;
}[NAME]): void;
};
};
WebsocketProvider: {
new (serverUrl: string, roomname: string, doc: YDoc, { connect, awareness, params, WebSocketPolyfill, resyncInterval, maxBackoffTime, connectTimeout, disableBc, maxFrameBytes }?: import("./protocol.js").WebsocketProviderOptions): {
serverUrl: string;
roomname: string;
doc: YDoc;
awareness: _Awareness;
params: Record<string, string>;
maxBackoffTime: number;
connectTimeout: number;
maxFrameBytes: number;
_WS: import("./protocol.js").WebsocketPolyfill;
shouldConnect: boolean;
ws: WebSocket | null;
wsconnected: boolean;
bcChannel: string;
bcconnected: boolean;
disableBc: boolean;
_bcSubscriber: (data: ArrayBuffer | Uint8Array, origin: unknown) => void;
_fromTab: {};
wsUnsuccessfulReconnects: number;
wsLastMessageReceived: number;
wsLastPingSent: number;
_synced: boolean;
_chunks: import("./protocol.js").ChunkReader;
_writes: {
pending: {
sv: Map<number, number>;
deletes: import("./protocols/sync.js").IdSet;
}[];
acked: Map<number, number>;
readOnly: boolean;
faults: number;
fault(): number;
readonly doc: YDoc;
readonly changed: (unsaved: number) => void;
trackDocument(): void;
track(sv: Map<number, number>, deletes: import("./protocols/sync.js").IdSet): void;
acknowledge(sv: Uint8Array, deletes?: import("./protocols/sync.js").IdSet | null): void;
deny(): void;
allow(): void;
};
messageHandlers: Record<number, import("./providers/room.js").RoomMessageHandler<any>>;
hasSynced: boolean;
whenSynced: Promise<unknown>;
_destroyed: boolean;
_failedEmitted?: boolean;
_settleSynced: import("./providers/room.js").LifecycleHost["_settleSynced"];
_leave: () => void;
_resync: ReturnType<typeof setInterval> | undefined;
_connectTimer: ReturnType<typeof setTimeout> | undefined;
_checkInterval: ReturnType<typeof setInterval>;
_updateHandler: (update: Uint8Array, origin: unknown, doc?: unknown, transaction?: {
local: boolean;
}) => void;
_awarenessUpdateHandler: (updates: {
added: number[];
updated: number[];
removed: number[];
}, origin: unknown) => void;
get url(): string;
get unsaved(): number;
get saved(): boolean;
get readOnly(): boolean;
get synced(): boolean;
set synced(state: boolean);
destroy(): void;
disconnect(): void;
connect(): void;
emit<N extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: N, args: Parameters<import("./protocol.js").WebsocketProviderEvents[N]>): void;
_observers: Map<string, Set<any>>;
on<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: import("./protocol.js").WebsocketProviderEvents[NAME]): import("./protocol.js").WebsocketProviderEvents[NAME];
once<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: import("./protocol.js").WebsocketProviderEvents[NAME]): void;
off<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: import("./protocol.js").WebsocketProviderEvents[NAME]): void;
};
};
watchComments: (server: string, roomName: string, listener: (message: import("./protocol.js").CommentMessage) => void) => (() => void);
storeState: (idbPersistence: {
db: IDBDatabase | null;
name: string;
doc: YDoc;
_dbref: number;
_dbsize: number;
_destroyed: boolean;
}, forceStore?: boolean) => Promise<undefined>;
clearDocument: (name: string) => Promise<void>;
PREFERRED_TRIM_SIZE: number;
createIndexeddbSync: (name: string) => import("./index.js").EdytorSync;
createWebsocketSync: (options: import("./index.js").WebsocketSyncOptions) => import("./index.js").WebsocketSync;
};
sync: {
messageYjsSyncStep1: number;
messageYjsSyncStep2: number;
messageYjsUpdate: number;
remoteApplyOrigin: symbol;
writeSyncStep1: (encoder: import("lib0-v14/encoding").Encoder, doc: YDoc) => void;
writeSyncStep2: (encoder: import("lib0-v14/encoding").Encoder, doc: YDoc, encodedStateVector?: Uint8Array) => void;
writeUpdate: (encoder: import("lib0-v14/encoding").Encoder, update: Uint8Array) => void;
applyRemote: (doc: YDoc, update: Uint8Array, transactionOrigin: unknown, errorHandler?: (error: Error) => unknown) => {
applied: boolean;
problem: import("./edytor-doc.js").SchemaProblem | null;
discarded?: import("./edytor-doc.js").SchemaProblem;
};
lacks: (doc: YDoc, sv: Uint8Array) => boolean;
writeSaved: (encoder: import("lib0-v14/encoding").Encoder, doc: YDoc, deletes?: import("./protocols/sync.js").IdSet, unstored?: import("./protocols/sync.js").IdSet | null) => void;
readSaved: (decoder: import("lib0-v14/decoding").Decoder) => {
stateVector: Uint8Array;
deletes: import("./protocols/sync.js").IdSet | null;
};
};
admission: {
admitUpdate: (update: Uint8Array | ReadonlyArray<Uint8Array>, docName?: string, options?: {
prepare?: (doc: YDoc) => void;
}) => YDoc;
};
attribution: {
attach: (doc: import("./engine-api.js").EngineDoc, opts: {
actor: import("./index.js").AttributionActor;
}) => import("./index.js").AttributionController;
};
};
BlockAttribution
export type BlockAttribution = {
createdBy?: ActorId;
contributors: ReadonlySet<ActorId>;
lastChangedBy?: ActorId;
};
createdBy: The actor that created the block — assigned at creation, never rewritten.contributors: Union set of actors that committed an edit addressing this block id, plus the pre-split snapshot a split/merge copies to siblings — block-identity LINEAGE, add-only.lastChangedBy: The actor whose state change currently wins the LWW resolution.
BlockId
Logical block identifier — caller-assigned, immutable per block.
export type BlockId = string;
BlockRole
Structural role of a block type (plugin-side policy, resolved per op).
export type BlockRole = {
void?: boolean;
island?: boolean;
lines?: boolean;
layout?: boolean;
table?: boolean;
atomic?: readonly (string | readonly string[])[];
};
void: Not editable through normal structural flow; no children, no merges.island: Editable, but its subtree is structurally sealed from outside blocks.lines: An island of lines (code): each direct child displays as itsdefaultChildkind and holds no children.layout: A layout (columns): it displays only its items — itsdefaultChildkind, a container that renders no content — side by side, and only while it shows two or more (layout.*in the delete contract).table: A table: it displays only its rows — itsdefaultChildkind, a container whose owndefaultChildis the cell kind (a text island) — and each row only its cells, in the order of the table’sdata.columns(table.*in the delete contract).atomic: Data paths written as one leaf (data.atomic): a top-level key, or an array of keys for a nested one (['link', ['media', 'source']]).
BlockSpec
Declarative block description used for inserts (and by seeders).
export type BlockSpec = {
id: BlockId;
type: string;
data?: Record<string, unknown>;
content?: ContentItem[];
children?: BlockSpec[];
};
codeKinds
createCodePlugin()’s structural rows: the code block is an island of codeLines (lines).
declare const codeKinds: {
code: {
island: true;
lines: true;
rendersContent: false;
defaultChild: string;
};
};
codeSemantics
createCodePlugin()’s block roles.
declare const codeSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
commentMarks
The comments plugin’s mark edge: a comment’s anchor (comment:<id>)
never grows at its ends, so text typed or inserted concurrently right
after commented text stays out of the comment (Notion).
declare const commentMarks: {
comment: {
edge: "exclusive";
};
};
ContentItem
One inline content element in a block spec / projection.
export type ContentItem = {
kind: 'text';
text: string;
marks?: Record<string, unknown>;
} | {
kind: 'inline';
id: string;
type: string;
data?: Record<string, unknown>;
};
ContentRun
One visible run of a block — the maintained form of ContentItem.
marks/data are interned: equal payloads share one frozen instance,
so === compares formatting without deep walks. A run carries no
authorship: runs never split at author boundaries, and durable
attribution is the compact per-block record (blockattr).
export type ContentRun = {
kind: 'text';
text: string;
marks?: Record<string, unknown>;
} | {
kind: 'inline';
id: string;
type: string;
data?: Record<string, unknown>;
};
Crdt
export type Crdt = ReturnType<typeof bindCrdt>;
createDocument
See DocumentBinding.createDocument.
declare const createDocument: (options?: CreateDocumentOptions) => EdytorDocument;
CreateDocumentOptions
export type CreateDocumentOptions = DocumentOptions & {
value?: JSONDoc;
};
DataPatch
One data edit at path (object keys and array indexes from the data’s
root): splice takes Array.prototype.splice’s arguments and order
the array’s current indexes in their new order; else it sets value, or
deletes the key or removes the item when there is none.
export type DataPatch = {
readonly path: readonly string[];
readonly value?: unknown;
readonly splice?: readonly [
start: number,
deleteCount?: number,
...items: unknown[]
];
readonly order?: readonly number[];
};
DataTarget
What a data patch edits: a block, one of its inline atoms, or the document (null).
export type DataTarget = BlockId | null | {
block: BlockId;
atom: string;
};
DEFAULT_HISTORY_LIMIT
The undo steps a document’s history keeps by default: older ones are released.
declare const DEFAULT_HISTORY_LIMIT = 200;
DEFAULT_READINESS_BOUND
How long (ms) an empty document waits for a provider that has not
settled before it decides without it (settle-or-bound) — the bound a
provider that cannot report “settled” gets, counted from its attach. A
factory sets its own with sync.bound, or arms it from transport state
(bound: Infinity + the payload’s armBound, as the websocket sync
does: from the socket’s open, so a slow dial never counts).
declare const DEFAULT_READINESS_BOUND = 1000;
defaultSemantics
The rich-text, code, image, media, columns, page, table of contents,
table and equation plugins’ block roles together (and the rich-text and
comment mark edges) — what the room and a headless
createDocument/loadDocument adopt by default (semantics: {} checks
none). The media, columns, page, table of contents, table and equation
plugins are not default plugins of <Edytor>, but their roles are here so their
blocks read the same on every replica.
declare const defaultSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
} & {
marks: Record<string, {
edge: MarkEdge;
}>;
};
Destination
Where a block goes: parent = logical block id or null for root.
export type Destination = {
parent: BlockId | null;
index: number;
};
DocAnchor
A selection endpoint: b is the home block of the backing text the
position lives in (NOT necessarily the block that displays it — merges and
splits reroute display while the anchor stays on the same items), a an
engine relative position whose a carries the side (< 0 left, >= 0
right). The containing stream and the side are two facts in two fields.
JSON-serializable — the presence and history wire shape.
export type DocAnchor = {
b: BlockId;
a: Anchor;
};
DocChange
One committed transaction’s semantic diff — the payload EdytorDoc.onChange
subscribers receive. Every collection names the affected ids; order
carries the NEW child-id list per changed parent so a mirror can apply the
diff without re-reading the doc. The report is shared: every subscriber
of the document (each view over it, its cells included) receives the same
object, so it is read-only.
export type DocChange = {
origin: unknown;
local: boolean;
version: number;
added: ReadonlyMap<BlockId, ProjectedBlock>;
removed: ReadonlySet<BlockId>;
moved: ReadonlySet<BlockId>;
meta: ReadonlyMap<BlockId, {
type: string;
data?: Record<string, unknown>;
}>;
content: ReadonlyMap<BlockId, readonly ContentRun[]>;
order: ReadonlyMap<BlockId | null, readonly BlockId[]>;
data?: Record<string, unknown>;
};
origin: Transaction origin (local origin object, remote marker, …).local:transaction.local— false for remote-applied updates.version: Monotonic event counter per facade.added: Newly visible blocks → full projected subtree (incl.removed: Ids no longer visible (deleted, merged-away, or hidden with subtree).moved: Ids whose display parent or sibling index changed.meta: Ids whosetype/datapayload changed → new values.content: Ids whose visible content changed → the new maintained runs.order: Parents (null= root) whose visible child list changed → new order (frozen — shared with the retained snapshot baseline).data: The document’s own data (docData()), when this commit changed it.
DocPosition
A position in one document version: a block and a display offset.
export type DocPosition = {
block: BlockId;
offset: number;
};
DOCUMENT_OPERATIONS
Every name of DocumentOperations, for the document’s own members (EdytorDocument).
declare const DOCUMENT_OPERATIONS: readonly [
"insertBlocks",
"moveBlocks",
"nestBlock",
"unNestBlock",
"unNestBlocks",
"liftOut",
"wrapInLayout",
"placeBeside",
"splitBlock",
"mergeBlocks",
"mergeBackward",
"mergeForward",
"deleteBlock",
"deleteBlocks",
"setBlock",
"setBlockType",
"patchData",
"duplicateBlock",
"insertText",
"deleteText",
"formatRange",
"clearMarks",
"insertInline",
"removeInline",
"deleteRange",
"replaceRange",
"insertFlow",
"toJSON",
"docData",
"dataItemIds",
"project",
"blockJSON",
"childrenIds",
"parentOf",
"ancestorsOf",
"positionOf",
"pathOf",
"blockTypeOf",
"blockDataOf",
"blockText",
"contentItems",
"displayLength",
"runs",
"hasBlock",
"isVisibleBlock",
"listBlockIds",
"blockAttribution",
"isVoid",
"isIsland",
"isLines",
"islandOf",
"insideIsland",
"isLayout",
"isLayoutItem",
"besideAt",
"isTable",
"isTableRow",
"isTableCell",
"tableOf",
"tableColumns",
"tableGrid",
"order",
"compare",
"next",
"previous",
"canPlace",
"canMerge",
"fits",
"nestParent",
"landingOf",
"anchorAt",
"resolveAnchor",
"prepare",
"apply",
"compose",
"transact",
"onChange",
"version"
];
DOCUMENT_WRITES
Every write of DocumentWrites: what a view dispatches under the same names (edytor.insertBlocks(…)).
declare const DOCUMENT_WRITES: readonly [
"insertBlocks",
"moveBlocks",
"nestBlock",
"unNestBlock",
"unNestBlocks",
"liftOut",
"wrapInLayout",
"placeBeside",
"splitBlock",
"mergeBlocks",
"mergeBackward",
"mergeForward",
"deleteBlock",
"deleteBlocks",
"setBlock",
"setBlockType",
"patchData",
"duplicateBlock",
"insertText",
"deleteText",
"formatRange",
"clearMarks",
"insertInline",
"removeInline",
"deleteRange",
"replaceRange",
"insertFlow"
];
DocumentActor
Local actor identity — durable across replicas, independent of presence profiles.
export type DocumentActor = {
id: string;
name?: string;
color?: string;
};
id: Stable author identifier (used by awareness and, later, native attribution).
DocumentAttribution
The document-level attribution surface. actors/actorOf/block
read replicated doc state directly — they resolve remote-applied
records identically and stay correct as old replicas append records.
export type DocumentAttribution = {
readonly actors: ReadonlyMap<string, ActorProfile>;
actorOf(client: number): string | undefined;
setProfile(profile: ActorProfile): void;
block(blockId: string): BlockAttribution | undefined;
};
actors: actorId → profile — the replicated actor dictionary (u/records).actorOf: Resolve an item’s inserting replica (clientID) to an actor id (c/records).setProfile: Re-publish the local actor’s profile record (u/<actorId>— LWW).block: Compact per-block attribution forblockId({createdBy, contributors, lastChangedBy}— durable actor ids, never replica clientIDs), orundefinedfor system/foreign blocks that carry no record.
DocumentDestroyedError
Raised when an operation runs against a torn-down document — every
attach reference has been released and the facade/history/awareness
teardown already ran. Distinct from DocumentNotReadyError:
destroyed is terminal, pending may still resolve.
export declare class DocumentDestroyedError extends Error {
constructor(service?: string);
}
DocumentNotReadyError
Raised when a readiness-gated service is used on a pending document.
export declare class DocumentNotReadyError extends Error {
constructor(service: string);
}
DocumentOperations
The document’s public operations: the writes, each also prepared
(prepare.<op>(…), pure, then apply(plan); compose joins plans),
the reads, transact, onChange and version. See the document API
reference.
export interface DocumentOperations extends DocumentWrites, DocumentReads {
readonly prepare: {
readonly [K in keyof DocumentWrites]: (...args: Parameters<DocumentWrites[K]>) => Prepared;
};
apply(plan: Prepared): OpResult;
compose(...parts: Prepared[]): Prepared;
transact<R>(fn: () => R, origin?: unknown): R;
onChange(listener: (change: DocChange) => void): () => void;
readonly version: number;
}
prepare: Every write, prepared: a plan of named steps and its effect, orrefused.apply: Write a prepared plan exactly (a refusal passes through).compose: One plan ofparts, applied in order.transact: Group writes in one transaction and one change event (no rollback on a throw).onChange: Hear each transaction’s change; answers the unsubscribe.version: Changes on every write that changed the tree.
DocumentOptions
export type DocumentOptions = {
actor?: DocumentActor;
semantics?: DocumentSemanticsConfig;
awareness?: Awareness;
history?: {
captureTimeout?: number;
limit?: number;
};
requireHydration?: boolean;
};
actor: Local actor — anonymous opaque id when absent.semantics: Up-front semantic configuration (views may also seed viaadoptSemantics).awareness: Borrow an existing awareness instance instead of creating one —destroy()will NOT destroy it (same owned/borrowed rule as the doc).history: History tuning — applied when the document’s undo manager attaches.requireHydration: Decide an EMPTY document only from a provider that synced: the room answered, or a local store hydrated.
DocumentReadiness
How the document’s content state was decided — the distinction the readiness contract requires:
pending— undecided (created without a value or attached beforesync(); a provider may still hydrate — nothing bootstrapped, nothing broadcast). Reads/attaches/sync()legal,historyrefuses;local— seeded locally (createDocument({value}), orsync()on a still-fresh doc — seed-if-empty bootstrap included). Full surface legal;hydrated— the doc was already initialized whensync()ran: provider-applied remote state or aloadDocumentrestore (schema asserted, content untouched). Full surface legal.
sync() is the only transition out of pending, and it is the
document-side admission re-check: a doc that arrived in a problem
state (unversioned/unsupported/foreign — e.g. via raw
applyUpdate bypass writes) refuses there with a typed error, stays
pending, and preserves the state — never silently becoming local.
export type DocumentReadiness = 'pending' | 'local' | 'hydrated';
DocumentReads
The document’s reads (transaction-aware where the reference says so).
export interface DocumentReads {
toJSON(): JSONDoc;
docData(): JsonObj;
dataItemIds(target: DataTarget, path: readonly string[]): string[];
project(): ProjectedDoc;
blockJSON(id: BlockId): JSONBlock;
childrenIds(parent: BlockId | null): BlockId[];
parentOf(id: BlockId): BlockId | null;
ancestorsOf(id: BlockId): BlockId[];
positionOf(id: BlockId): Destination | null;
pathOf(id: BlockId): number[] | null;
blockTypeOf(id: BlockId): string | undefined;
blockDataOf(id: BlockId): Record<string, unknown> | undefined;
blockText(id: BlockId): string | null;
contentItems(id: BlockId): ContentItem[];
displayLength(id: BlockId): number;
runs(id: BlockId): readonly ContentRun[];
hasBlock(id: BlockId): boolean;
isVisibleBlock(id: BlockId): boolean;
listBlockIds(): BlockId[];
blockAttribution(id: BlockId): BlockAttribution | undefined;
isVoid(id: BlockId): boolean;
isIsland(id: BlockId): boolean;
isLines(id: BlockId): boolean;
islandOf(id: BlockId): BlockId | null;
insideIsland(id: BlockId): boolean;
isLayout(id: BlockId): boolean;
isLayoutItem(id: BlockId): boolean;
besideAt(id: BlockId, kind?: string): BlockId;
isTable(id: BlockId): boolean;
isTableRow(id: BlockId): boolean;
isTableCell(id: BlockId): boolean;
tableOf(id: BlockId): BlockId | null;
tableColumns(id: BlockId): {
id: string;
width?: number;
}[] | null;
tableGrid(id: BlockId): {
columns: string[];
rows: {
id: BlockId;
cells: (BlockId | null)[];
}[];
} | null;
order(): readonly BlockId[];
compare(a: BlockId, b: BlockId): number;
next(id: BlockId, policy?: OrderPolicy): BlockId | null;
previous(id: BlockId, policy?: OrderPolicy): BlockId | null;
canPlace(ids: readonly BlockId[], parent?: BlockId | null): boolean;
canMerge(from: BlockId, into: BlockId): boolean;
fits(parent: BlockId | null, kind: string): boolean;
nestParent(ids: readonly BlockId[], parent: BlockId): BlockId;
landingOf(id: BlockId, kind: string, after?: boolean): {
parent: BlockId | null;
levels: BlockId[];
};
anchorAt(id: BlockId, offset: number, affinity?: AnchorAffinity): DocAnchor | null;
resolveAnchor(anchor: DocAnchor): {
blockId: BlockId;
offset: number;
} | null;
}
DocumentSemanticsConfig
Document-level semantic configuration — the structural subset of what
plugin BlockDefinitions carry (roles, rendersContent, defaultChild)
plus the default block type. Snippets/DOM hooks are deliberately NOT
part of this: they are view-side rendering policy.
export type DocumentSemanticsConfig = {
roles?: Record<string, BlockRole>;
rendersContent?: Record<string, boolean>;
defaultChild?: Record<string, string>;
defaultType?: string;
marks?: Record<string, {
edge?: MarkEdge;
}>;
};
roles: Structural role per block type ({void?, island?, lines?, layout?}— absent flags mean false).rendersContent: Whether a kind renders its own content slot (undeclared kinds do).defaultChild: Default child type per parent type (undeclared parents takedefaultType).defaultType: Default block type — the root’s default child and the bootstrap block.marks: Per mark, its edge (its record’sedge) — where a concurrent insert at each end of a mark lands.
DocumentWrites
The document’s writes: each one transaction, answering what it did (OpResult).
export interface DocumentWrites {
insertBlocks(dest: Destination, specs: readonly (JSONBlock | BlockSpec)[]): OpResult;
moveBlocks(ids: readonly BlockId[], dest: Destination): OpResult;
nestBlock(id: BlockId, parent: BlockId): OpResult;
unNestBlock(id: BlockId): OpResult;
unNestBlocks(ids: readonly BlockId[]): OpResult;
liftOut(id: BlockId, kind: string, options?: {
keep?: boolean;
after?: readonly BlockSpec[];
}): OpResult;
wrapInLayout(ids: readonly BlockId[], kind?: string, columns?: number): OpResult;
placeBeside(ids: readonly BlockId[], target: BlockId, side: 'left' | 'right', kind?: string): OpResult;
splitBlock(id: BlockId, offset: number, newId: BlockId, tail?: SplitTail): OpResult;
mergeBlocks(fromId: BlockId, intoId: BlockId): OpResult;
mergeBackward(id: BlockId): OpResult;
mergeForward(id: BlockId): OpResult;
deleteBlock(id: BlockId, options?: {
keepChildren?: boolean;
}): OpResult;
deleteBlocks(ids: readonly BlockId[]): OpResult;
setBlock(id: BlockId, value: {
type?: string;
data?: Record<string, unknown>;
content?: (ContentItem | JSONText | JSONInlineBlock)[];
children?: (BlockSpec | JSONBlock)[];
}): OpResult;
setBlockType(id: BlockId, type: string): OpResult;
patchData(target: DataTarget, patches: readonly DataPatch[]): OpResult;
duplicateBlock(id: BlockId, freshId?: (oldId: string, kind: 'block' | 'inline') => string): OpResult;
insertText(id: BlockId, offset: number, text: string, marks?: Record<string, unknown>): OpResult;
deleteText(id: BlockId, offset: number, length: number): OpResult;
formatRange(id: BlockId, offset: number, length: number, marks: Record<string, unknown>): OpResult;
clearMarks(id: BlockId, offset: number, length: number): OpResult;
insertInline(id: BlockId, offset: number, atom: NewInline): OpResult;
removeInline(id: BlockId, inlineId: string): OpResult;
deleteRange(from: DocPosition, to: DocPosition, view?: RangeView): OpResult;
replaceRange(from: DocPosition, to: DocPosition, view?: RangeView): OpResult;
insertFlow(target: FlowTarget, flow: Flow, view?: FlowView): OpResult;
}
duplicateBlock:freshIdnames each copy (fresh ids by default).insertInline: An atom without an id gets a fresh one.
EdytorDoc
export type EdytorDoc = ReturnType<EdytorDocBinding['create']>;
EdytorDocDisposedError
Raised when a mutating facade op runs after dispose() — disposal is
terminal for writes (reads stay dead-safe: a stale handle may still be
inspected while its document outlives the facade). The facade-level
counterpart of DocumentDestroyedError — kept in this module because a
bare bindEdytorDoc facade has no document layer above it.
export declare class EdytorDocDisposedError extends Error {
constructor(service?: string);
}
EdytorDocument
The document’s operations and reads are its own members
(document.insertBlocks(…), document.toJSON()): see DocumentOperations.
transact is the document’s (its local origin by default).
export interface EdytorDocument extends Omit<DocumentOperations, 'transact'> {
}
export declare class EdytorDocument {
#private;
readonly doc: YDoc;
readonly awareness: Awareness;
readonly actor: DocumentActor;
get attribution(): DocumentAttribution;
readonly transaction: TRANSACTION;
private _destroyed;
readonly requireHydration: boolean;
get clientID(): number;
get ready(): boolean;
get readiness(): DocumentReadiness;
get destroyed(): boolean;
get writable(): boolean;
onWritableChange: (listener: (writable: boolean) => void) => (() => void);
get historyLimit(): number;
get semantics(): {
defaultType: string;
roles: Map<string, BlockRole>;
rendersContent: Map<string, boolean>;
defaultChild: Map<string, string>;
marks: Map<string, MarkEdge>;
};
defaultChild: (parentType: string | null) => string;
rendersContent: (type: string) => boolean;
adoptSemantics: (config: DocumentSemanticsConfig) => void;
sync: (value?: JSONDoc) => void;
get history(): YUndoManager;
trackOrigin: (origin: unknown) => void;
untrackOrigin: (origin: unknown) => void;
clearHistory: () => void;
transact: <T>(cb: () => T, origin?: unknown) => T;
onReady: (listener: () => void) => (() => void);
get syncPending(): boolean;
get syncRefusal(): SyncRefusedError | undefined;
onSyncRefused: (listener: (refusal: SyncRefusedError) => void) => (() => void);
private _decide;
attachSync: (sync: EdytorSync, opts?: {
value?: JSONDoc;
}) => EdytorSyncCleanup | void;
encode: () => Uint8Array;
retain: () => (() => void);
destroy: () => void;
}
doc: The underlying engine doc — raw reads/providers borrow it; they never own it.awareness: One shared awareness instance for every view/provider of this document.actor: The local actor identity (anonymous opaque id when none was supplied).attribution: The attribution surface — compact per-block records and the replicated actor dictionary (u/profiles,c/replica bindings).transaction: The document’s own local-edit transaction origin — headless edits viatransactcarry it so history capture attributes them.requireHydration:DocumentOptions.requireHydration: an empty document waits for a provider’ssynced.clientID: The replica id (doc.clientID) — identifies the replica, not the actor.ready:trueonce the document’s content state is decided — seeded locally or hydrated then synced.readiness:pending|local|hydrated— distinguishes a locally-seeded ready from a provider-hydrated/restored ready (the contract consumers need to tell “I decided this content” from “sync brought it”).writable:falsewhile the document carries a schema stamp this build cannot own (a foreign stamp got in despite the transport’s inbound refusal): every write refuses with aSchemaMismatchError, and the providers neither persist nor broadcast it.onWritableChange: Subscribe towritabletransitions — the visible signal that the document turned read-only (once per transition, not per refused edit).historyLimit: The undo steps this document’s history keeps: the configuredhistory.limit, elseDEFAULT_HISTORY_LIMIT.semantics: The document-level semantic configuration (snapshot).defaultChild: The default child type under a parent ofparentType(null= the root) — the one answer split, paragraph insert, merge-unnest, clear and root normalization apply against the new block’s actual parent.rendersContent: Whether kindtyperenders its own content slot (undeclared kinds do).adoptSemantics: Contribute document-level semantics — the seam views use to seed the structural roles implied by their plugin block definitions.sync: The readiness transition — decide the document’s content state.history: The default local history (the registry-scoped undo manager —undo/redo/stopCapturing/stacks).trackOrigin: Track a local-edit transaction origin for history capture — the seam views use to enroll their ownTRANSACTIONinstance in this document’s history.untrackOrigin: Release a previously-tracked origin — the view-teardown counterpart oftrackOrigin.clearHistory: Drop the undo/redo stacks.transact: Local document transaction — headless edits, one undo step per call (origin: another origin, which the document’s history tracks only when it is tracked).onReady: Subscribe to the readiness transition — fires once, synchronously, insidesyncwhen_readinessleaves'pending'(every decision path goes throughsync(): providersynced, local seed, explicit call).syncPending: Whether an attached provider has neither settled nor reached its bound.syncRefusal: The server’s refusal of a provider (a1008/4xxxclose — seeSyncRefusedError), the latest still standing: that provider stopped.onSyncRefused: Subscribe to provider refusals (syncRefusal).attachSync: Attach a provider sync factory to this document (headlessEdytorSyncpath — the same contract views use).encode: Full replicated state as a v14 update —loadDocumentrestores it on a fresh replica.retain: Acquire one more attach reference and return its ONE-SHOT release capability.destroy: Release ONE attach reference.
EdytorSync
export type EdytorSync = ((payload: EdytorSyncPayload) => void | EdytorSyncCleanup) & {
bound?: number;
target?: string;
};
EdytorSyncCleanup
export type EdytorSyncCleanup = () => void | Promise<void>;
EdytorSyncPayload
Payload a sync factory receives — the v13 contract plus failed:
the terminal half of the sync lifecycle. A provider that can never reach
synced (destroyed before syncing, persistence load failure, refused
hydration, denied auth) reports it here exactly once; a transient
disconnect or a provider that already synced never does. A
SyncRefusedError is the exception: the server refused this
client for good, reported synced or not, and an empty document does not
seed over it.
export type EdytorSyncPayload = {
doc: YDoc;
awareness: Awareness;
synced: (provider?: unknown) => void;
failed?: (error: unknown, provider: unknown) => void;
armBound?: () => void;
holdBound?: () => void;
attach?: (sync: EdytorSync) => EdytorSyncCleanup | void;
};
armBound: (Re)start this provider’s readiness bound (DEFAULT_READINESS_BOUNDms from now) — for a factory whoseboundisInfinitybecause only its transport knows when waiting starts to count (the websocket sync: from the socket’s open, or its first failed dial).holdBound: Stop this provider’s readiness bound: an empty document waits for it to settle (or for the nextarmBound()), as the websocket sync does after expired credentials on a first visit.attach: Attach another sync to the same document as its own provider (its own target, bound and settle): how a sync brings a companion, e.g.
EngineApi
The engine surface every bind* receives: the object in engine.js
(exactly the symbols edytor calls, so consumer bundles tree-shake the
rest). The full namespace import * as Y from 'edytor/crdt' is a
superset and satisfies it.
export type EngineApi = typeof Engine;
EngineDoc
Structural minimum of the vendored Y.Doc.
export interface EngineDoc {
clientID: number;
keepReplaced?: ((item: never) => boolean) | null;
get(key?: string): EngineNode;
transact<T>(f: (transaction: unknown) => T, origin?: unknown): T;
on(name: 'update', f: (update: Uint8Array, origin: unknown, doc: EngineDoc, transaction: unknown) => void): void;
off(name: 'update', f: (update: Uint8Array, origin: unknown, doc: EngineDoc, transaction: unknown) => void): void;
on(name: 'commit', f: (transaction: never) => void): void;
off(name: 'commit', f: (transaction: never) => void): void;
on(name: 'destroy', f: () => void): void;
off(name: 'destroy', f: () => void): void;
readonly store?: {
pendingStructs: null | {
missing: Map<number, number>;
update: Uint8Array;
};
pendingDs: null | Uint8Array;
getClock(client: number): number;
};
readonly _transaction?: EngineTransaction | null;
}
keepReplaced: Which node values a concurrent write of the same key replaced keep their subtree (null: none, upstream’s semantics).on: Doc-levelupdatechannel — fires once per transaction that produced replicated state (local commits AND remoteapplyUpdates), carrying the transaction’s origin and the transaction itself (transaction.localdistinguishes local commits from remote applies).on: Doc-levelupdatechannel — fires once per transaction that produced replicated state (local commits AND remoteapplyUpdates), carrying the transaction’s origin and the transaction itself (transaction.localdistinguishes local commits from remote applies).on: Doc-levelupdatechannel — fires once per transaction that produced replicated state (local commits AND remoteapplyUpdates), carrying the transaction’s origin and the transaction itself (transaction.localdistinguishes local commits from remote applies).store: The doc’s struct store — present on a real engine doc._transaction: The engine’s CURRENT transaction (nulloutside one) — vendoredDoc._transaction.
EngineItemRef
Engine item identity — used by crdtId (client:clock).
export type EngineItemRef = {
id?: {
client: number;
clock: number;
};
deleted?: boolean;
parent?: unknown;
parentSub?: string | null;
} | null;
EngineNode
Structural minimum of the vendored Y.Node (v14) used by the placement
model. A real YNode satisfies this at runtime; typed consumers cast once
at the boundary (doc as unknown as EngineDoc).
export interface EngineNode {
readonly name: string;
readonly doc: unknown | null;
readonly length: number;
readonly _item: EngineItemRef;
getAttr(key: string): unknown;
setAttr(key: string, value: unknown): unknown;
deleteAttr(key: string): void;
forEachAttr(f: (value: unknown, key: string, node: EngineNode) => void): void;
attrKeys(): IterableIterator<string>;
insert(index: number, content: unknown): void;
delete(index: number, length?: number): void;
}
name: Node name (‘block’ | ‘content’ | ‘at’ | ‘inline’ in our schema).doc: The doc this node is integrated into;nullwhile detached.length: Sequence length (invalid read on detached nodes — track offsets instead)._item: The item this node is attached to (identity anchor forcrdtId).
EngineTransaction
Structural minimum of the in-flight engine Transaction — exposed on the
doc as doc._transaction while a transaction is open. changed maps each
touched shared type to the set of parentSub keys whose items changed
(attr names for map-like children, null for sequence edits); the
document index folds it once at commit.
export interface EngineTransaction {
changed?: Map<unknown, Set<string | null>>;
}
equationKinds
The equation plugin’s structural row: a block equation is a void that
draws its TeX (data.expression) and shows no text of its own. Its
inline equation is an atom, which needs no role.
declare const equationKinds: {
equation: {
void: true;
rendersContent: false;
};
};
equationSemantics
The equation plugin’s block role.
declare const equationSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
facadeConfigOf
The facade configuration (EdytorDocConfig) a document with no view
reads semantics with — the room’s: roles, default children, content-less kinds
and mark edges, each answered only for a kind the tables name.
declare const facadeConfigOf: (semantics: DocumentSemanticsConfig) => {
roleOf: (type: string) => BlockRole | undefined;
kinds: () => string[];
defaultChildOf: (type: string) => string | undefined;
rendersContent: (type: string) => boolean;
markEdge: (mark: string) => MarkEdge | undefined;
defaultType: string | undefined;
};
FlowView
What the view tells flow placement beyond range deletion’s view: a
container’s flat item kind (numbered-list-item for an ordered-list).
export type FlowView = RangeView & {
itemKind?: (parent: BlockId) => string | undefined;
header?: (id: BlockId) => boolean | 'closed';
};
imageKinds
createImagePlugin()’s structural rows: void, its only text is the caption.
declare const imageKinds: {
image: {
void: true;
};
};
imageSemantics
createImagePlugin()’s block roles.
declare const imageSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
IndexeddbSyncOptions
export type IndexeddbSyncOptions = {
awareness?: Awareness;
};
InlineSpec
export type InlineSpec = {
id: string;
type: string;
data?: Record<string, unknown>;
};
JSONBlock
export type JSONBlock = {
type: string;
id?: string;
data?: Record<string, SerializableContent>;
children?: JSONBlock[];
content?: (JSONText | JSONInlineBlock)[];
};
JSONDoc
export type JSONDoc = {
data?: Record<string, SerializableContent>;
children: JSONBlock[];
} & Partial<Record<string, unknown>>;
JSONInlineBlock
export type JSONInlineBlock = {
id?: string;
data?: any;
type: string;
};
JSONText
export type JSONText = {
text: string;
marks?: Record<string, SerializableContent>;
};
KindRecord
A kind record as a plugin declares it (plugin.blocks[type]): its
structural row with whatever else it holds (a snippet, an element,
presets), or a bare snippet, a plain kind.
export type KindRecord = KindSemantics | ((...args: never[]) => unknown);
KindSemantics
One kind’s structural row — the fields of its BlockDefinition a document adopts.
export type KindSemantics = BlockRole & {
rendersContent?: boolean;
defaultChild?: string;
};
LastUpdatedOptions
What lastUpdated takes: the room it asks, and the params (a token) its dial would carry.
export type LastUpdatedOptions = WebsocketTarget & {
params?: Record<string, string>;
fetch?: typeof fetch;
};
layoutKinds
The columns plugin’s structural rows: columns is a layout of columns
(layout.* in the delete contract), a column a container that holds any
block. In defaultSemantics: a document holding no columns block
is unchanged by them, and every replica of one that does (a view with the
plugin, a headless document, the room) reads the same layout rules.
declare const layoutKinds: {
columns: {
layout: true;
rendersContent: false;
defaultChild: string;
};
column: {
rendersContent: false;
};
};
layoutSemantics
The columns plugin’s block roles (a layout of columns).
declare const layoutSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
loadDocument
See DocumentBinding.loadDocument.
declare const loadDocument: (update: Uint8Array, options?: LoadDocumentOptions) => EdytorDocument;
LoadDocumentOptions
export type LoadDocumentOptions = DocumentOptions;
MarkEdge
Whether a mark grows at its edges — always, never, or at its start only.
export type MarkEdge = 'inclusive' | 'exclusive' | 'side-dependent';
markName
The record a mark key names: comment:c1 → comment (a key of its own otherwise).
declare const markName: (key: string) => string;
mediaKinds
The media plugins’ structural rows (createEmbedPlugin(), createBookmarkPlugin(),
createFilePlugin(), createVideoPlugin(), createAudioPlugin()): void like the image, their
only text is the caption.
declare const mediaKinds: {
embed: {
void: true;
};
bookmark: {
void: true;
};
file: {
void: true;
};
video: {
void: true;
};
audio: {
void: true;
};
};
mediaSemantics
The media plugins’ block roles (embed, bookmark, file, video, audio).
declare const mediaSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
MergedSemantics
The merged config’s fields, each present (empty when no config named one).
export type MergedSemantics = {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
marks: Record<string, {
edge?: MarkEdge;
}>;
defaultType?: string;
};
mergeSemantics
Several configs as one, deeply frozen, merged field by field (roles,
rendersContent, defaultChild, marks, defaultType): the room’s or
a headless document’s roles for an app’s own kinds beside the bundled
ones, mergeSemantics(defaultSemantics, semanticsOf(myKinds)). A
top-level spread of two configs would keep only the last one’s fields.
A kind (or mark, or the default type) two configs declare otherwise
throws SemanticConflictError, as a view’s conflicting plugin does
on a document; an equal declaration merges.
declare const mergeSemantics: (...configs: DocumentSemanticsConfig[]) => MergedSemantics;
MetaClientState
export type MetaClientState = {
clock: number;
lastUpdated: number;
};
lastUpdated: unix timestamp
OpResult
The observed outcome of one document operation — the one result
shape every op returns, empty inputs included. refused: the op did not
apply and wrote nothing; noop: it applied and changed nothing; applied:
the transaction wrote. Read from the transaction’s effects, never predicted.
export type OpResult = {
readonly status: 'refused' | 'noop' | 'applied';
readonly ids: readonly BlockId[];
readonly reason?: string;
};
ids: What the op is about — created, moved, merge target, or its target; empty unless applied.reason: Why a refused op refused, when it names a reason ('id-collision').
OrderPolicy
Island-sealing policy for a walk in document order (see next).
export type OrderPolicy = {
sealed?: boolean;
};
pageKinds
The page plugin’s structural row: a link to another document (a subpage), void and showing no text of its own, as a divider.
declare const pageKinds: {
page: {
void: true;
rendersContent: false;
};
};
pageSemantics
The page plugin’s block role (a link to another document).
declare const pageSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
Plan
A prepared operation: its steps, their effect, the ids the op is about, and the document version it was prepared against — valid only there, applied in the same synchronous turn.
export type Plan = {
readonly ids: readonly BlockId[];
readonly writes: readonly PlanStep[];
readonly effect: PlanEffect;
readonly version: number;
readonly at?: DocPosition;
};
at: Where the op leaves the caret, when it decides one (deleteRange).
PrefetchOptions
What bindProviders’ prefetch takes: a websocket sync’s target and options.
export type PrefetchOptions = (WebsocketSyncOptions extends infer O ? O extends unknown ? Omit<O, 'onExpired' | 'persist' | 'disableBc'> : never : never) & {
timeout?: number;
};
PrefetchResult
What prefetch found: whether the room sent the store anything it lacked.
export type PrefetchResult = {
updated: boolean;
};
Prepared
prepare’s answer: a plan, or the op’s refusal.
export type Prepared = Plan | OpResult;
ProjectedBlock
Canonical projected block — the comparison surface for convergence.
export type ProjectedBlock = {
id: BlockId;
type: string;
data?: Record<string, unknown>;
content: ContentItem[];
children: ProjectedBlock[];
malformed?: true;
};
malformed: Set when the registry node could not be read completely.
ProjectedDoc
export type ProjectedDoc = {
children: ProjectedBlock[];
};
ProviderStack
export type ProviderStack = ReturnType<typeof bindProviders>;
RangeView
What the view knows of a range (view state the document does not hold):
whether it hides a block, and, given removed, whether the block stays
hidden once those go (a removed closed toggle’s children take its place, shown).
export type RangeView = {
hidden?: (id: BlockId, removed?: ReadonlySet<BlockId>) => boolean;
};
richTextKinds
createRichTextPlugin()’s structural rows (its other kinds are plain).
declare const richTextKinds: {
divider: {
void: true;
rendersContent: false;
};
'ordered-list': {
rendersContent: false;
defaultChild: string;
};
'unordered-list': {
rendersContent: false;
defaultChild: string;
};
};
richTextMarks
createRichTextPlugin()’s mark edges: where a concurrent insert at each end
of a mark lands. A link grows at its start only (typing after it
stays out of it unless from inside the anchor); the others are inclusive.
declare const richTextMarks: {
link: {
edge: "side-dependent";
};
};
richTextSemantics
createRichTextPlugin()’s block roles and mark edges, for createDocument({ semantics }) and the room.
declare const richTextSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
} & {
marks: Record<string, {
edge: MarkEdge;
}>;
};
SchemaMismatchError
Error raised by assertSchema — carries the detected problem.
export declare class SchemaMismatchError extends Error {
readonly docName: string;
readonly problem: SchemaProblem;
constructor(docName: string, problem: SchemaProblem);
}
SemanticConflictError
Raised when two declarations of one kind’s structural facts disagree —
a view’s plugin and the document (adoptSemantics), or two configs
mergeSemantics is given: no replica may silently read another
rule than its peers.
export declare class SemanticConflictError extends Error {
readonly subject: string;
readonly existing: unknown;
readonly incoming: unknown;
constructor(subject: string, existing: unknown, incoming: unknown);
}
subject: What conflicted (e.g.
semanticsDigest
A config’s facts as one short hash per kind, per mark (mark:<name>) and
for the default type (@defaultType): what a document advertises in its
presence in development builds, so the room can name the kinds it reads
otherwise than a client (semanticsMismatch). A plain kind (no
role, content, no default child) hashes as an undeclared one.
declare const semanticsDigest: (config: DocumentSemanticsConfig) => Record<string, string>;
semanticsMismatch
The keys of a client’s advertised digest that ours (the room’s
semanticsDigest) hashes otherwise: kinds, marks or the default
type the two read differently. A kind the client does not name is not
its mismatch (a view without that plugin); a kind only the client
names counts when it has facts. Anything but a digest compares nothing.
declare const semanticsMismatch: (ours: Record<string, string>, theirs: unknown) => string[];
semanticsOf
Kind tables (type → row) as one DocumentSemanticsConfig, deeply
frozen: semanticsOf({ embed: { void: true, rendersContent: false } }).
A row may be a plugin’s kind record (plugin.blocks): only its
structural fields are read (void, island, lines, layout,
table, atomic, rendersContent, defaultChild), and a bare snippet is a
plain kind. To add kinds to a bundled config, use mergeSemantics.
declare const semanticsOf: (...tables: Record<string, KindRecord>[]) => {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
SerializableContent
export type SerializableContent = {
[key: string]: SerializableContent;
} | SerializableContent[] | string | boolean | number | null;
SyncRefusedError
A terminal refusal: the server closed the socket with a policy code
(isRefusal), so the next dial would be refused the same way (a
stale generation, another user’s replica, a foreign stamp). The provider
stops dialing and the document does not seed.
export declare class SyncRefusedError extends Error {
code: number;
reason: string;
constructor(code: number, reason?: string);
}
code: The close code.reason: The close reason the server gave, e.g.
tableBlock
A table block in the document JSON: rows × columns cells, the table’s
columns and each cell’s column set. It names no block id, so a value
holding it seeds the same table every time.
createDocument({
value: { children: [tableBlock({ cells: [['Name', 'Role'], ['Ada', 'Eng']], headerRow: true })] }
});
declare const tableBlock: (options?: TableBlockOptions) => JSONBlock;
TableBlockOptions
What tableBlock builds.
export type TableBlockOptions = {
rows?: number;
columns?: number;
cells?: readonly (readonly (string | readonly JSONText[])[])[];
headerRow?: boolean;
headerColumn?: boolean;
widths?: readonly (number | undefined)[];
};
rows: Rows (default: the rows ofcells, else 2).columns: Columns (default: the widest row ofcells, else 2).cells: Each cell’s text, by row then column (a string, or rich text).headerRow: The first row is a header row.headerColumn: The first column is a header column.widths: Column widths in pixels, by position (absent: the default width).
tableKinds
The table plugin’s structural rows: table displays only its
tableRows, a row only its tableCells, in the order of the table’s
data.columns (table.* in the delete contract); a cell is a text
island (its text holds its lines, as soft breaks). In
defaultSemantics, so every replica of a document holding a table
reads the same rules.
declare const tableKinds: {
table: {
table: true;
rendersContent: false;
defaultChild: string;
};
tableRow: {
rendersContent: false;
defaultChild: string;
};
tableCell: {
island: true;
};
};
tableSemantics
The table plugin’s block roles (a table of rows of cells).
declare const tableSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
toBlockSpec
A canonical JSONBlock (from facade.toJSON()/blockJSON, a template, an
import) as the BlockSpec facade.insertBlocks takes: ids are kept, and
minted where missing; freshIds mints every id (a duplicate).
declare const toBlockSpec: (block: JSONBlock, { freshIds }?: {
freshIds?: boolean | undefined;
}) => BlockSpec;
tocKinds
The table of contents plugin’s structural row: a void that lists the document’s headings, showing no text of its own.
declare const tocKinds: {
toc: {
void: true;
rendersContent: false;
};
};
tocSemantics
The table of contents plugin’s block role.
declare const tocSemantics: {
roles: Record<string, BlockRole>;
rendersContent: Record<string, boolean>;
defaultChild: Record<string, string>;
};
UndecodableUpdateError
Raised when a candidate update cannot even be decoded or integrated — refused before the schema question is ever asked. Distinct from the schema refusals: this payload was never document-shaped.
export declare class UndecodableUpdateError extends Error {
readonly docName: string;
readonly cause: unknown;
constructor(docName: string, cause: unknown);
}
docName: What the update was offered as (e.g.
UnsupportedDocError
Error raised by assertUsableDoc — the doc cannot host a v14 facade:
a foreign engine object (a v13 yjs Doc — a different CRDT implementation
entirely).
export declare class UnsupportedDocError extends Error {
readonly kind: 'foreign';
constructor(kind: 'foreign');
}
WebsocketSync
A websocket sync; persistName names its local store (for clearDocument), unset without one.
export type WebsocketSync = EdytorSync & {
persistName?: string;
};
WebsocketSyncOptions
export type WebsocketSyncOptions = WebsocketTarget & {
params?: Record<string, string>;
WebSocketPolyfill?: import('./websocket.js').WebsocketPolyfill;
maxBackoffTime?: number;
connectTimeout?: number;
onExpired?: (state: Parameters<WebsocketProviderEvents['expired']>[0]) => void;
disableBc?: boolean;
maxFrameBytes?: number;
persist?: boolean;
persistName?: string;
};
YDoc
export type YDoc = InstanceType<typeof Y.Doc>;
YItem
export type YItem = Y.Item;
YNode
export type YNode = InstanceType<typeof Y.Node>;
YTransaction
export type YTransaction = Y.Transaction;
YUndoManager
The document’s undo manager (doc/history.ts).
export type YUndoManager = import('./doc/history.js').UndoManager;