lib0
Version:
isomorphic utility functions
1,662 lines • 74.3 kB
TypeScript
/**
* Provenance metadata on a content/attr op: *who/what* inserted, deleted, or formatted it. The canonical
* shape below is a convention — apply/diff/equality treat attribution as an **opaque** object (never branching
* on these field names), so custom keys flow through — with ONE exception: the nested `format` key merges per
* inner key (one level), so applying `{format:{italic:[…]}}` *adds* italic while keeping a pre-existing
* `{format:{bold:[…]}}`, and `{format:{bold:null}}` removes just that inner key (an emptied `format` is
* dropped). Every other key is flat/wholesale. The `format`/`formatAt` part exists only on
* children (content ops), never on node attribute ops. As an *update value* on `retain`/`modify`/`*Attr`,
* attribution uses the same unified tri-state as {@link Formats} (`undefined` skip / `null`
* clear / `{k:v}` set / `{k:null}` remove) — see the delta `readme.md` "Formats & Attributions". The blanket
* `null`-clear channel caveat on {@link Formats} applies here too; note `rebase` does not
* reconcile attribution at all (concurrent attribution edits don't converge), so prefer deterministic
* attribution assignment outside of concurrent editing.
*
* @typedef {{
* insert?: string[]
* insertAt?: number
* delete?: string[]
* deleteAt?: number
* format?: Record<string,string[]>
* formatAt?: number
* }} Attribution
*/
/**
* @type {s.Schema<Attribution>}
*/
export const $attribution: s.Schema<Attribution>;
/**
* Rich-text formatting attributes (`{ bold: true, … }`). As an *update value* on `retain`/`modify` it is a
* unified tri-state (identical to {@link Attribution}): `undefined`/omitted = skip, `null` = clear all,
* `{k:v}` = set, `{k:null}` = remove key — see the delta `readme.md` "Formats & Attributions".
*
* ⚠️ **Blanket `null` clear is a local-only utility — never send it over a channel.** A `null` clear carries
* no key information, so it cannot be reconciled key-by-key under `rebase`: a clear *always wins* a concurrent
* edit (priority-independent — that is what makes it converge), which silently DROPS the other side's set. For
* collaborative / transmitted data, clear keys individually with `{k:null}` removals instead — those reconcile
* by priority and converge without data loss (this is what {@link diff} emits and what the rebase fuzz uses).
*
* @typedef {{ [key: string]: any }} Formats
*/
/**
* @typedef {{ id: string, key: number|string, assoc: 1|-1, attrs?: object, transient?: boolean }} MarkJSON
*/
/**
* @typedef {{
* type: 'delta',
* name?: string,
* attrs?: { [Key in string|number]: DeltaAttrOpJSON },
* children?: Array<DeltaListOpJSON>,
* marks?: Array<MarkJSON>,
* deleteMarks?: Array<string>
* }} DeltaJSON
*/
/**
* @typedef {{ type: 'insert', insert: string|Array<any>, format?: { [key: string]: any }, attribution?: Attribution } | { delete: number } | { type: 'retain', retain: number, format?: { [key:string]: any }|null, attribution?: Attribution|null } | { type: 'modify', value: object, format?: { [key:string]: any }|null, attribution?: Attribution|null }} DeltaListOpJSON
*/
/**
* @typedef {{ type: 'insert', value: any, attribution?: Attribution } | { type: 'delete', attribution?: Attribution } | { type: 'modify', value: DeltaJSON, attribution?: Attribution|null }} DeltaAttrOpJSON
*/
/**
* @typedef {TextOp|InsertOp<any>|DeleteOp<any>|RetainOp|ModifyOp<any>} ChildrenOpAny
*/
/**
* @typedef {SetAttrOp<any>|DeleteAttrOp<any>|ModifyAttrOp} AttrOpAny
*/
/**
* @typedef {ChildrenOpAny|AttrOpAny} _OpAny
*/
/**
* @type {s.Schema<DeltaAttrOpJSON>}
*/
export const $deltaMapChangeJson: s.Schema<DeltaAttrOpJSON>;
/**
* Invariants shared by all op classes below (TextOp, InsertOp, DeleteOp,
* RetainOp, ModifyOp, SetAttrOp, DeleteAttrOp, ModifyAttrOp):
*
* - **Only code inside `delta.js` may mutate op fields.** External consumers
* treat ops as immutable; structural fields are JSDoc-annotated `@readonly`
* to reinforce this. Mutation is permitted only while the owning Delta is
* not `done` — every builder entry point routes through `modDeltaCheck`
* to enforce this at runtime.
* - **Any mutation of a fingerprinted field MUST null `_fingerprint`.** The
* fingerprint is a lazy cache; if it has already been computed and the
* underlying data changes without invalidating it, every subsequent
* fingerprint read (and any `diff` / equality check that relies on it) is
* wrong. Fields covered: insert, delete, retain, format, attribution,
* value, key.
* - **A `clone` copies `_fingerprint` when the copy is content-identical:** a full range and the
* same key. Freezing a nested value with `done()` is fingerprint-neutral (trailing plain retains
* are not fingerprinted), so nothing else can differ. The root delta returned by
* `clone`/`slice`/`cloneDeep` never inherits a fingerprint.
*
* @internal not part of the consumer API — a content op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class TextOp extends list.ListNode {
/**
* @param {string} insert
* @param {Formats|null} format
* @param {Attribution?} attribution
*/
constructor(insert: string, format: Formats | null, attribution: Attribution | null);
/**
* @readonly
* @type {string}
*/
readonly insert: string;
/**
* @readonly
* @type {Formats|null}
*/
readonly format: Formats | null;
attribution: Attribution | null;
/**
* @type {string?}
*/
_fingerprint: string | null;
/**
* @return {'insert'}
*/
get type(): "insert";
get length(): number;
get fingerprint(): string;
/**
* Remove a part of the operation (similar to Array.splice)
*
* @param {number} offset
* @param {number} len
*/
_splice(offset: number, len: number): this;
/**
* @return {DeltaListOpJSON}
*/
toJSON(): DeltaListOpJSON;
/**
* @param {number} [start]
* @param {number} [end]
* @param {boolean} [_markAsDone] accepted for a uniform children-op `clone` signature; ignored (text
* holds no nested deltas to freeze).
* @return {TextOp}
*/
clone(start?: number, end?: number, _markAsDone?: boolean): TextOp;
$type: s.Schema<TextOp>;
/**
* @param {TextOp} other
*/
[equalityTrait.EqualityTraitSymbol](other: TextOp): boolean;
}
/**
* @template {any} ArrayContent
* @internal not part of the consumer API — a content op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class InsertOp<ArrayContent extends unknown> extends list.ListNode {
/**
* @param {Array<ArrayContent>} insert
* @param {Formats|null} format
* @param {Attribution?} attribution
*/
constructor(insert: Array<ArrayContent>, format: Formats | null, attribution: Attribution | null);
/**
* @readonly
* @type {Array<ArrayContent>}
*/
readonly insert: Array<ArrayContent>;
/**
* @readonly
* @type {Formats?}
*/
readonly format: Formats | null;
/**
* @readonly
* @type {Attribution?}
*/
readonly attribution: Attribution | null;
/**
* @type {string?}
*/
_fingerprint: string | null;
/**
* @return {'insert'}
*/
get type(): "insert";
get length(): number;
/**
* @param {number} i
* @return {Extract<ArrayContent,DeltaAny>}
*/
_modValue(i: number): Extract<ArrayContent, DeltaAny>;
get fingerprint(): string;
/**
* Remove a part of the operation (similar to Array.splice)
*
* @param {number} offset
* @param {number} len
*/
_splice(offset: number, len: number): this;
/**
* @return {DeltaListOpJSON}
*/
toJSON(): DeltaListOpJSON;
/**
* @param {number} [start]
* @param {number} [end]
* @param {boolean} [markAsDone] freeze the cloned child deltas (the default — a shared clone must be
* immutable). Pass `false` only when the caller is the SOLE owner of the cloned range (a *move*, e.g.
* `splitHere` which `_splice`s the range out of the source), so the content can stay mutable and is
* not re-cloned on the next modify (see {@link modValue}).
* @return {InsertOp<ArrayContent>}
*/
clone(start?: number, end?: number, markAsDone?: boolean): InsertOp<ArrayContent>;
$type: s.Schema<InsertOp<any>>;
/**
* @param {InsertOp<ArrayContent>} other
*/
[equalityTrait.EqualityTraitSymbol](other: InsertOp<ArrayContent>): boolean;
}
/**
* @template {DeltaConf} [Conf={}]
* @internal not part of the consumer API — a content op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class DeleteOp<Conf extends DeltaConf = {}> extends list.ListNode {
/**
* @param {number} len
*/
constructor(len: number);
delete: number;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @return {'delete'}
*/
get type(): "delete";
get length(): number;
get fingerprint(): string;
/**
* Remove a part of the operation (similar to Array.splice)
*
* @param {number} _offset
* @param {number} len
*/
_splice(_offset: number, len: number): this;
/**
* @return {DeltaListOpJSON}
*/
toJSON(): DeltaListOpJSON;
/**
* @param {number} [start]
* @param {number} [end]
* @param {boolean} [_markAsDone] accepted for a uniform children-op `clone` signature; ignored (a
* delete holds no nested content).
* @return {DeleteOp<any>}
*/
clone(start?: number, end?: number, _markAsDone?: boolean): DeleteOp<any>;
$type: s.Schema<DeleteOp<any>>;
/**
* @param {DeleteOp<any>} other
*/
[equalityTrait.EqualityTraitSymbol](other: DeleteOp<any>): boolean;
}
/**
* @internal not part of the consumer API — a content op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class RetainOp extends list.ListNode {
/**
* @param {number} retain
* @param {Formats|null|undefined} format tri-state: `undefined` skip / `null` clear / object merge
* @param {Attribution|null|undefined} attribution tri-state: `undefined` skip / `null` clear / object merge
*/
constructor(retain: number, format: Formats | null | undefined, attribution: Attribution | null | undefined);
/**
* @readonly
* @type {number}
*/
readonly retain: number;
/**
* @readonly
* @type {Formats|null|undefined}
*/
readonly format: Formats | null | undefined;
/**
* @readonly
* @type {Attribution|null|undefined}
*/
readonly attribution: Attribution | null | undefined;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @return {'retain'}
*/
get type(): "retain";
get length(): number;
get fingerprint(): string;
/**
* Remove a part of the operation (similar to Array.splice)
*
* @param {number} _offset
* @param {number} len
*/
_splice(_offset: number, len: number): this;
/**
* @return {DeltaListOpJSON}
*/
toJSON(): DeltaListOpJSON;
/**
* @param {number} [start]
* @param {number} [end]
* @param {boolean} [_markAsDone] accepted for a uniform children-op `clone` signature; ignored (retain
* holds no nested deltas).
* @return {RetainOp}
*/
clone(start?: number, end?: number, _markAsDone?: boolean): RetainOp;
$type: s.Schema<RetainOp>;
/**
* @param {RetainOp} other
*/
[equalityTrait.EqualityTraitSymbol](other: RetainOp): boolean;
}
/**
* Delta that can be applied on a YType Embed
*
* @template {Delta<any>} [DTypes=DeltaAny]
* @internal not part of the consumer API — a content op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class ModifyOp<DTypes extends Delta<any> = DeltaAny> extends list.ListNode {
/**
* @param {DTypes} delta
* @param {Formats|null|undefined} format tri-state: `undefined` skip / `null` clear / object merge
* @param {Attribution|null|undefined} attribution tri-state: `undefined` skip / `null` clear / object merge
*/
constructor(delta: DTypes, format: Formats | null | undefined, attribution: Attribution | null | undefined);
/**
* @readonly
* @type {DTypes}
*/
readonly value: DTypes;
/**
* @readonly
* @type {Formats|null|undefined}
*/
readonly format: Formats | null | undefined;
/**
* @readonly
* @type {Attribution|null|undefined}
*/
readonly attribution: Attribution | null | undefined;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @return {'modify'}
*/
get type(): "modify";
get length(): number;
/**
* @type {DeltaBuilderAny}
*/
get _modValue(): DeltaBuilderAny;
get fingerprint(): string;
/**
* Remove a part of the operation (similar to Array.splice)
*
* @param {number} _offset
* @param {number} _len
*/
_splice(_offset: number, _len: number): this;
/**
* @return {DeltaListOpJSON}
*/
toJSON(): DeltaListOpJSON;
/**
* @param {number} [_start] ignored (a modify is atomic); accepted for a uniform children-op signature.
* @param {number} [_end] ignored.
* @param {boolean} [markAsDone] freeze the cloned value (default); `false` shares it mutable — see
* {@link InsertOp#clone}. The op itself is still a fresh node; only its `value` is consumed.
* @return {ModifyOp<DTypes>}
*/
clone(_start?: number, _end?: number, markAsDone?: boolean): ModifyOp<DTypes>;
$type: s.Schema<ModifyOp<Delta<any>>>;
/**
* @param {ModifyOp<any>} other
*/
[equalityTrait.EqualityTraitSymbol](other: ModifyOp<any>): boolean;
}
/**
* @template {any} [V=any]
* @template {string|number} [K=any]
* @internal not part of the consumer API — an attribute op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class SetAttrOp<V extends unknown = any, K extends string | number = any> {
/**
* @param {K} key
* @param {V} value
* @param {Attribution?} attribution
*/
constructor(key: K, value: V, attribution: Attribution | null);
/**
* @readonly
* @type {K}
*/
readonly key: K;
/**
* @readonly
* @type {V}
*/
readonly value: V;
/**
* @readonly
* @type {Attribution?}
*/
readonly attribution: Attribution | null;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @return {'insert'}
*/
get type(): "insert";
/**
* @type {DeltaBuilderAny}
*/
get _modValue(): DeltaBuilderAny;
get fingerprint(): string;
toJSON(): {
type: "insert";
value: DeltaJSON | V;
} & ({
attribution: Attribution;
} | {
attribution?: undefined;
});
/**
* Full (frozen) clone. A `move` apply reuses the source op instead of cloning, so there is no
* shared-mutable variant — see {@link DeltaBuilder#apply}.
*
* @template {string|number} [K2=K]
* @param {K2} [key] retarget the clone to another attribute key (a transformer projecting or
* renaming an attribute); defaults to this op's key.
* @return {SetAttrOp<V,K2>}
*/
clone<K2 extends string | number = K>(key?: K2): SetAttrOp<V, K2>;
$type: s.Schema<SetAttrOp<any, any>>;
/**
* @param {SetAttrOp<V>} other
*/
[equalityTrait.EqualityTraitSymbol](other: SetAttrOp<V>): boolean;
}
/**
* @template [V=any]
* @template {string|number} [K=string|number]
* @internal not part of the consumer API — an attribute op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class DeleteAttrOp<V = any, K extends string | number = string | number> {
/**
* @param {K} key
* @param {Attribution?} attribution
*/
constructor(key: K, attribution: Attribution | null);
/**
* @type {K}
*/
key: K;
attribution: Attribution | null;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @type {'delete'}
*/
get type(): "delete";
get value(): undefined;
get fingerprint(): string;
/**
* @return {DeltaAttrOpJSON}
*/
toJSON(): DeltaAttrOpJSON;
/**
* Full (frozen) clone; a `move` apply reuses the source op instead — see {@link DeltaBuilder#apply}.
*
* @template {string|number} [K2=K]
* @param {K2} [key] retarget the clone to another attribute key; defaults to this op's key.
* @return {DeleteAttrOp<V,K2>}
*/
clone<K2 extends string | number = K>(key?: K2): DeleteAttrOp<V, K2>;
$type: s.Schema<DeleteAttrOp<any, string | number>>;
/**
* @param {DeleteAttrOp<V>} other
*/
[equalityTrait.EqualityTraitSymbol](other: DeleteAttrOp<V>): boolean;
}
/**
* @template {DeltaAny} [Modifier=DeltaAny]
* @template {string|number} [K=string]
* @internal not part of the consumer API — an attribute op; build deltas via {@link create}/{@link DeltaBuilder}.
*/
export class ModifyAttrOp<Modifier extends DeltaAny = DeltaAny, K extends string | number = string> {
/**
* @param {K} key
* @param {Modifier} delta
* @param {Attribution|null|undefined} attribution tri-state: `undefined` skip / `null` clear / object merge
*/
constructor(key: K, delta: Modifier, attribution: Attribution | null | undefined);
/**
* @readonly
* @type {K}
*/
readonly key: K;
/**
* @readonly
* @type {Modifier}
*/
readonly value: Modifier;
/**
* @readonly
* @type {Attribution|null|undefined}
*/
readonly attribution: Attribution | null | undefined;
/**
* @type {string|null}
*/
_fingerprint: string | null;
/**
* @type {'modify'}
*/
get type(): "modify";
get fingerprint(): string;
/**
* @return {DeltaBuilder<any>}
*/
get _modValue(): DeltaBuilder<any>;
/**
* @return {DeltaAttrOpJSON}
*/
toJSON(): DeltaAttrOpJSON;
/**
* Full (frozen) clone; a `move` apply reuses the source op instead — see {@link DeltaBuilder#apply}.
*
* @template {string|number} [K2=K]
* @param {K2} [key] retarget the clone to another attribute key; defaults to this op's key.
* @return {ModifyAttrOp<Modifier,K2>}
*/
clone<K2 extends string | number = K>(key?: K2): ModifyAttrOp<Modifier, K2>;
$type: s.Schema<ModifyAttrOp<any, string>>;
/**
* @param {ModifyAttrOp<Modifier>} other
*/
[equalityTrait.EqualityTraitSymbol](other: ModifyAttrOp<Modifier>): boolean;
}
export const $insertOp: s.Schema<InsertOp<any>>;
export const $modifyOp: s.Schema<ModifyOp<Delta<any>>>;
export const $textOp: s.Schema<TextOp>;
export const $deleteOp: s.Schema<DeleteOp<any>>;
export const $retainOp: s.Schema<RetainOp>;
export const $anyOp: s.Schema<TextOp | InsertOp<any> | DeleteOp<any> | ModifyOp<Delta<any>>>;
export const $setAttrOp: s.Schema<SetAttrOp<any>>;
export const $modifyAttrOp: s.Schema<ModifyAttrOp<any>>;
export const $deleteAttrOp: s.Schema<DeleteAttrOp<any>>;
export const $anyAttrOp: s.Schema<SetAttrOp<any, any> | DeleteAttrOp<any, string | number> | ModifyAttrOp<any, string>>;
export function $setAttrOpWith<Content extends fingerprintTrait.Fingerprintable>($content: s.Schema<Content>): s.Schema<SetAttrOp<Content>>;
export function $insertOpWith<Content extends fingerprintTrait.Fingerprintable>($content: s.Schema<Content>): s.Schema<InsertOp<Content>>;
export function $modifyOpWith<Modify extends DeltaAny>($content: s.Schema<Modify>): s.Schema<ModifyOp<Modify>>;
export function $modifyAttrOpWith<Modify extends DeltaAny>($content: s.Schema<Modify>): s.Schema<ModifyAttrOp<Modify>>;
export const $mark: s.Schema<Mark>;
export function createMark(key: number | string, id?: string, assoc?: 1 | -1, attrs?: object | null, transient?: boolean): Mark;
/**
* @template {DeltaConf} [Conf={}]
* @extends {DeltaData<
* DeltaConfGetName<Conf>,
* DeltaConfGetAttrs<Conf>,
* DeltaConfGetChildren<Conf>,
* Conf extends {text:true} ? true : false
* >}
*/
export class Delta<Conf extends DeltaConf = {}> extends DeltaData<DeltaConfGetName<Conf>, import("../ts.js").TypeIsAny<Conf, {
[K: string]: any;
[K: number]: any;
}, Conf extends {
attrs: infer Attrs_1;
} ? Attrs_1 extends undefined ? {} : Attrs_1 : {}>, DeltaConfGetChildren<Conf>, Conf extends {
text: true;
} ? true : false> {
/**
* @param {string?} name
* @param {s.Schema<Delta<any>>?} $schema
*/
constructor(name: string | null, $schema: s.Schema<Delta<any>> | null);
/**
* @type {string}
*/
get fingerprint(): string;
isEmpty(): boolean;
/**
* @return {DeltaJSON}
*/
toJSON(): DeltaJSON;
/**
* @param {Delta<any>} other
* @return {boolean}
*/
equals(other: Delta<any>): boolean;
/**
* Mark this delta as done and perform some cleanup (e.g. remove appended retains without
* formats&attributions). In the future, there might be additional merge operations that can be
* performed to result in smaller deltas. Set `markAsDone=false` to only perform the cleanup.
*
* @return {Delta<Conf>}
*/
done(markAsDone?: boolean): Delta<Conf>;
$type: s.Schema<Delta<any>>;
[fingerprintTrait.FingerprintTraitSymbol](): string;
/**
* @param {any} other
* @return {boolean}
*/
[equalityTrait.EqualityTraitSymbol](other: any): boolean;
}
export function slice<Conf_1 extends DeltaConf>(d: Delta<Conf_1>, start?: number, end?: number, currNode?: ChildrenOpAny | null): DeltaBuilder<Conf_1>;
export function clone<D extends DeltaAny>(d: D): D extends Delta<infer Conf_1> ? DeltaBuilder<Conf_1> : never;
export function cloneDeep<Conf_1 extends DeltaConf>(d: Delta<Conf_1>): DeltaBuilder<Conf_1>;
export function cloneShallow<D extends DeltaAny>(d: D): D extends Delta<infer Conf_1> ? DeltaBuilder<Conf_1> : never;
export function _mergeChildWithPrev(d: DeltaBuilderAny, op: InsertOp<any> | RetainOp | DeleteOp<any> | TextOp | ModifyOp<any>): boolean;
export function _splitChildAt(d: DeltaBuilderAny, op: ChildrenOpAny, offset: number): ChildrenOpAny;
export function _insertChild(d: DeltaBuilderAny, ref: ChildrenOpAny | null, op: ChildrenOpAny): ChildrenOpAny;
export function _removeChild(d: DeltaBuilderAny, op: ChildrenOpAny): void;
export function _shrinkChild(d: DeltaBuilderAny, op: ChildrenOpAny, offset: number, len: number): void;
export function _growRun(d: DeltaBuilderAny, op: RetainOp | DeleteOp<any>, n: number): void;
export function _spliceInsert(d: DeltaBuilderAny, op: InsertOp<any>, offset: number, elems: Array<any>): void;
/**
* @template {DeltaConf} [Conf={}]
* @template {boolean} [FixedConf=false]
* @extends {Delta<Conf>}
*/
export class DeltaBuilder<Conf extends DeltaConf = {}, FixedConf extends boolean = false> extends Delta<Conf> {
/**
* @param {string?} name
* @param {s.Schema<Delta<Conf>>?} $schema
*/
constructor(name: string | null, $schema: s.Schema<Delta<Conf>> | null);
/**
* @type {Formats?}
*/
_usedFormats: Formats | null;
/**
* @type {Attribution?}
*/
_usedAttribution: Attribution | null;
/**
* Resolved data-companion cache for the `used*` contexts ({@link resolveUsedData}): what data
* ops inherit instead of the raw context. `undefined` = stale, recomputed on the next data-op
* consumption ({@link DeltaBuilder#_getUsedFormatsData}) — {@link DeltaBuilder#useFormats} & co
* clear it whenever they swap the context (which is why the public slots are read-only).
*
* @type {Formats|null|undefined}
*/
_usedFormatsData: Formats | null | undefined;
/**
* @type {Attribution|null|undefined}
*/
_usedAttributionData: Attribution | null | undefined;
/**
* The ambient formats context inherited by subsequent ops. Read-only: set it via
* {@link DeltaBuilder#useFormats} / {@link DeltaBuilder#updateUsedFormats}, which also invalidate
* the cached data companion — a direct overwrite would leave it stale.
*
* @return {Formats?}
*/
get usedFormats(): Formats | null;
/**
* The ambient attribution context inherited by subsequent ops. Read-only — see
* {@link DeltaBuilder#usedFormats}; set it via {@link DeltaBuilder#useAttribution} /
* {@link DeltaBuilder#updateUsedAttribution}.
*
* @return {Attribution?}
*/
get usedAttribution(): Attribution | null;
/**
* Set the ambient attribution context inherited by subsequent ops (`undefined`/empty dim args).
* The object is interned — instruction ops store it, and data ops store its resolved companion
* ({@link resolveUsedData}), BY REFERENCE. Never mutate it after setting; pass a fresh object
* instead (same invariant as the objects stored on ops).
*
* @param {Attribution?} attribution
*/
useAttribution(attribution: Attribution | null): this;
/**
* Set the ambient formats context inherited by subsequent ops (`undefined`/empty dim args). The
* object is interned — see {@link DeltaBuilder#useAttribution}: never mutate it after setting.
*
* @param {Formats?} attributes
* @return {this}
*/
useFormats(attributes: Formats | null): this;
/**
* The `usedFormats` context resolved for data-op consumption ({@link resolveUsedData}): the slot
* object itself when it carries no `{k:null}` removals, one shared stripped copy otherwise.
* Cached until the context is swapped — no per-op traversal.
*
* @return {Formats?}
*/
_getUsedFormatsData(): Formats | null;
/**
* See {@link DeltaBuilder#_getUsedFormatsData} — the `usedAttribution` analogue (its `format` key
* resolves one level deeper).
*
* @return {Attribution?}
*/
_getUsedAttributionData(): Attribution | null;
/**
* @param {string} name
* @param {any} value
*/
updateUsedFormats(name: string, value: any): this;
/**
* @template {keyof Attribution} NAME
* @param {NAME} name
* @param {Attribution[NAME]?} value
*/
updateUsedAttribution<NAME extends keyof Attribution>(name: NAME, value: Attribution[NAME] | null): this;
/**
* @template {(FixedConf extends true ? never : (Array<any>|string)) | (DeltaConfGetChildren<Conf> extends infer Children ? (Children extends never ? never : Array<Children>) : never) | DeltaConfGetText<Conf>} NewContent
* @param {NewContent} insert
* @param {Formats?} [formatting]
* @param {Attribution?} [attribution]
* @return {DeltaBuilder<FixedConf extends true ? Conf : DeltaConfOverwrite<Conf,
* (Exclude<NewContent,string> extends never ? {} : {
* children: Exclude<NewContent,string>[number]|DeltaConfGetChildren<Conf>
* }) & (Extract<NewContent,string> extends never ? {} : { text: true })>, FixedConf>}
*/
insert<NewContent extends (FixedConf extends true ? never : (Array<any> | string)) | (DeltaConfGetChildren<Conf> extends infer Children_1 ? (Children_1 extends never ? never : Array<Children_1>) : never) | DeltaConfGetText<Conf>>(insert: NewContent, formatting?: Formats | null, attribution?: Attribution | null): DeltaBuilder<FixedConf extends true ? Conf : DeltaConfOverwrite<Conf, (Exclude<NewContent, string> extends never ? {} : {
children: Exclude<NewContent, string>[number] | DeltaConfGetChildren<Conf>;
}) & (Extract<NewContent, string> extends never ? {} : {
text: true;
})>, FixedConf>;
/**
* @template {Extract<DeltaConfGetAllowedChildren<Conf, FixedConf>,Delta<any>|DeltaData<any,any,any,any>|DeltaBuilder<any>>} NewContent
* @param {NewContent} modify
* @param {Formats?} [formatting] tri-state: omit/`undefined` skip, `null` clear, `{k:v}`/`{k:null}` set/remove
* @param {Attribution?} [attribution] tri-state: omit/`undefined` skip, `null` clear, `{k:v}`/`{k:null}` set/remove
* @return {DeltaBuilder<DeltaConfOverwrite<Conf, {children: DeltaConfGetChildren<Conf>|NewContent}>, FixedConf>}
*/
modify<NewContent extends Extract<DeltaConfGetAllowedChildren<Conf, FixedConf>, Delta<any> | DeltaData<any, any, any, any> | DeltaBuilder<any>>>(modify: NewContent, formatting?: Formats | null, attribution?: Attribution | null): DeltaBuilder<DeltaConfOverwrite<Conf, {
children: DeltaConfGetChildren<Conf> | NewContent;
}>, FixedConf>;
/**
* Add a cursor/selection {@link Mark} at `pos` — a {@link import('./position.js').Pos}: a `path` of
* content-index / attribute-key steps plus an `assoc` and optional immutable `attrs` (user data
* carried with the mark). Returns `this` for chaining (like every other builder method). Pass an
* explicit `id` to reference the mark later — re-adding the same `id` replaces it (e.g. to move a
* cursor or update its `attrs`) and {@link DeltaBuilder#removeMark} deletes it; an anonymous one-shot
* mark gets a fresh GUID otherwise.
*
* @param {import('./position.js').Pos} pos
* @param {string} [id]
* @param {boolean} [transient] flag the mark as never-to-be-stored (a one-shot mapping probe, see
* {@link Mark#transient} and {@link import('./position.js').mapPositionsA})
* @return {this}
*/
addMark(pos: import("./position.js").Pos, id?: string, transient?: boolean): this;
/**
* Remove the mark with `id`, located via `pos` (the position it was added at). On a settled document
* that holds the mark this removes it in place; on a fresh/markless builder it records a transmittable
* `deleteMarks` change (symmetric to {@link DeltaBuilder#addMark}), so
* `delta.create().removeMark(pos, id)` yields the delete-mark change to apply / rebase / transmit.
*
* @param {import('./position.js').Pos} pos
* @param {string} id
* @return {this}
*/
removeMark(pos: import("./position.js").Pos, id: string): this;
/**
* @param {number} len
* @param {Formats?} [format]
* @param {Attribution?} [attribution]
*/
retain(len: number, format?: Formats | null, attribution?: Attribution | null): this;
/**
* @param {number} len
*/
delete(len: number): this;
/**
* @template {Extract<keyof DeltaConfGetAllowedAttrs<Conf, FixedConf>,string|number>} Key
* @template {DeltaConfGetAllowedAttrs<Conf, FixedConf>[Key]} Val
* @param {Key} key
* @param {Val} val
* @param {Attribution?} [attribution] provenance for this attr (data: object or `null`/none)
* @return {DeltaBuilder<DeltaConfOverwrite<Conf,{attrs:AddToAttrs<DeltaConfGetAttrs<Conf>,Key,Val>}>, FixedConf>}
*/
setAttr<Key extends Extract<keyof DeltaConfGetAllowedAttrs<Conf, FixedConf>, string | number>, Val extends DeltaConfGetAllowedAttrs<Conf, FixedConf>[Key]>(key: Key, val: Val, attribution?: Attribution | null): DeltaBuilder<DeltaConfOverwrite<Conf, {
attrs: AddToAttrs<DeltaConfGetAttrs<Conf>, Key, Val>;
}>, FixedConf>;
/**
* @template {DeltaConfGetAllowedAttrs<Conf, FixedConf>} NewAttrs
* @param {NewAttrs} attrs
* @param {Attribution?} [attribution] provenance applied to each set attr (data: object or `null`/none)
* @return {DeltaBuilder<DeltaConfOverwrite<
* Conf,
* { attrs: MergeAttrs<DeltaConfGetAttrs<Conf>,NewAttrs> }
* >, FixedConf>
* }
*/
setAttrs<NewAttrs extends DeltaConfGetAllowedAttrs<Conf, FixedConf>>(attrs: NewAttrs, attribution?: Attribution | null): DeltaBuilder<DeltaConfOverwrite<Conf, {
attrs: MergeAttrs<DeltaConfGetAttrs<Conf>, NewAttrs>;
}>, FixedConf>;
/**
* @template {Extract<keyof DeltaConfGetAllowedAttrs<Conf, FixedConf>,string|number>} Key
* @param {Key} key
* @param {Attribution?} [attribution] provenance for the deletion (data: object or `null`/none)
* @return {DeltaBuilder<DeltaConfOverwrite<Conf, {
* attrs: AddToAttrs<DeltaConfGetAttrs<Conf>,Key,never>
* }>, FixedConf>}
*/
deleteAttr<Key extends Extract<keyof DeltaConfGetAllowedAttrs<Conf, FixedConf>, string | number>>(key: Key, attribution?: Attribution | null): DeltaBuilder<DeltaConfOverwrite<Conf, {
attrs: AddToAttrs<DeltaConfGetAttrs<Conf>, Key, never>;
}>, FixedConf>;
/**
* @template {DeltaConfGetAllowedAttrs<Conf, FixedConf> extends infer As ? { [K in keyof As]: Extract<As[K],DeltaAny> extends never ? never : K }[keyof As] : never} Key
* @template {Extract<DeltaConfGetAllowedAttrs<Conf, FixedConf>[Key],DeltaAny>} D
* @param {Key} key
* @param {D} modify
* @param {Attribution?} [attribution] tri-state instruction merged onto the target attr op: omit/`undefined` skip, `null` clear, `{k:v}`/`{k:null}` set/remove
* @return {DeltaBuilder<DeltaConfOverwrite<Conf,{attrs:AddToAttrs<DeltaConfGetAttrs<Conf>,Key,D>}>, FixedConf>}
*/
modifyAttr<Key extends DeltaConfGetAllowedAttrs<Conf, FixedConf> extends infer As ? { [K in keyof As]: Extract<As[K], DeltaAny> extends never ? never : K; }[keyof As] : never, D extends Extract<DeltaConfGetAllowedAttrs<Conf, FixedConf>[Key], DeltaAny>>(key: Key, modify: D, attribution?: Attribution | null): DeltaBuilder<DeltaConfOverwrite<Conf, {
attrs: AddToAttrs<DeltaConfGetAttrs<Conf>, Key, D>;
}>, FixedConf>;
/**
* Apply other delta on this op. The result is the merged op of both of them.
*
* a.apply(b.apply(c))
*
* is equivalent to
*
* a.apply(b).apply(c)
*
* If `final = true`, we consider this delta the final state and drop deleteAttrOps from
* attributes. (E.g. if `otherOp` deletes an attribute, this op will simply not have the
* attribute). Any kind of `delete` op might be considered a bug. A final delta is not idempotent.
*
* @param {Delta<Conf>?} other
* @param {{ final?: boolean, move?: boolean }} [opts] `move`: the caller donates `other` (it is not
* read again), so its content is consumed (shared mutable) rather than frozen-cloned — see {@link
* InsertOp#clone}. UNSAFE if the caller keeps using `other`.
* @return {DeltaBuilder<Conf>}
*/
apply(other: Delta<Conf> | null, { final, move }?: {
final?: boolean;
move?: boolean;
}): DeltaBuilder<Conf>;
/**
* Rebase this op against a concurrent op. We can apply this op on a doc that already applied
* `other` op.
*
* @param {DeltaAny} other
* @param {boolean} priority
*/
rebase(other: DeltaAny, priority: boolean): this;
/**
* Same as doing `delta.rebase(other.inverse())`, without creating a temporary delta.
*
* @param {DeltaAny} other
* @param {boolean} priority
*/
rebaseOnInverse(other: DeltaAny, priority: boolean): this;
/**
* Append child ops from one op to the other.
*
* delta.create().insert('a').append(delta.create().insert('b')) // => insert "ab"
*
* @template {DeltaConf} OtherDeltaConf
* @param {Delta<OtherDeltaConf>} other
* @return {DeltaBuilder<FixedConf extends true ? Conf : DeltaConfOverwrite<
* Conf,
* (DeltaConfGetChildren<OtherDeltaConf> extends never ? {} : { children: DeltaConfGetChildren<Conf> | DeltaConfGetChildren<OtherDeltaConf> })
* & (DeltaConfGetText<OtherDeltaConf> extends string ? { text: true } : never)
* >, FixedConf>}
*/
append<OtherDeltaConf extends DeltaConf>(other: Delta<OtherDeltaConf>): DeltaBuilder<FixedConf extends true ? Conf : DeltaConfOverwrite<Conf, (DeltaConfGetChildren<OtherDeltaConf> extends never ? {} : {
children: DeltaConfGetChildren<Conf> | DeltaConfGetChildren<OtherDeltaConf>;
}) & (DeltaConfGetText<OtherDeltaConf> extends string ? {
text: true;
} : never)>, FixedConf>;
}
export function remapRootMarks(node: DeltaAny, mapKey: (key: number | string) => number | string | null): void;
export function addRootMark(node: DeltaAny, mark: Mark): void;
export function deleteRootMark(node: DeltaAny, id: string): void;
export function mergeRootMarks(target: DeltaAny, source: DeltaAny, mapKey?: (key: number | string) => number | string | null): void;
/**
* @template {DeltaConf} Conf
* @extends {s.Schema<Delta<Conf>>}
* @internal use the {@link $delta} factory; this class is exported only for the `$$delta` predicate.
*/
export class $Delta<Conf extends DeltaConf> extends s.Schema<Delta<Conf>> {
/**
* @param {s.Schema<any>} $name
* @param {s.Schema<any>} $attrs
* @param {s.Schema<any>} $children
* @param {any} hasText
* @param {any} recursiveChildren
* @param {s.Schema<{[K:string]:any}>} $formats
*/
constructor($name: s.Schema<any>, $attrs: s.Schema<any>, $children: s.Schema<any>, hasText: any, recursiveChildren: any, $formats: s.Schema<{
[K: string]: any;
}>);
/**
* @type {{
* $name: s.Schema<DeltaConfGetName<Conf>>,
* $attrs: s.Schema<DeltaConfGetAttrs<Conf>>,
* $children: s.Schema<DeltaConfGetChildren<Conf>>,
* hasText: DeltaConfGetText<Conf>
* recursiveChildren: DeltaConfGetRecursiveChildren<Conf>,
* $formats: s.Schema<{[K:string]:any}>
* }}
*/
shape: {
$name: s.Schema<DeltaConfGetName<Conf>>;
$attrs: s.Schema<DeltaConfGetAttrs<Conf>>;
$children: s.Schema<DeltaConfGetChildren<Conf>>;
hasText: DeltaConfGetText<Conf>;
recursiveChildren: DeltaConfGetRecursiveChildren<Conf>;
$formats: s.Schema<{
[K: string]: any;
}>;
};
}
/**
* Name-first form: a string-literal `name` as the first argument is preserved as a literal type
* (generic argument inference), so callers don't need `s.$literal('x')` / `@type {const}` to keep the
* node name literal. The remaining options follow in `opts`.
*
* @template {string} Name
* @template {Omit<ReadableDeltaConf, 'name'>} [Opts={}]
* @overload
* @param {Name} name
* @param {Opts} [opts]
* @return {s.Schema<Delta<ReadDeltaConf<Opts & { name: Name }>>>}
*/
export function $delta<Name extends string, Opts extends Omit<ReadableDeltaConf, "name"> = {}>(name: Name, opts?: Opts | undefined): s.Schema<Delta<ReadDeltaConf<Opts & {
name: Name;
}>>>;
/**
* @template {ReadableDeltaConf} [Conf={}]
* @overload
* @param {Conf} opts
* @return {s.Schema<Delta<ReadDeltaConf<Conf>>>}
*/
export function $delta<Conf extends ReadableDeltaConf = {}>(opts: Conf): s.Schema<Delta<ReadDeltaConf<Conf>>>;
export const $$delta: s.Schema<$Delta<DeltaConf>>;
export const $deltaAny: s.Schema<Delta<any>>;
export const $deltaBuilderAny: s.Schema<DeltaBuilderAny>;
export function mergeAttributions<T extends {
[key: string]: any;
}>(a: T | null, b: T | null): T | null;
export function mergeFormats<T extends {
[key: string]: any;
}>(a: T | null, b: T | null): T | null;
export function mergeDeltas<D extends DeltaAny | null>(a: D, b: D): D;
export function random<Conf_1 extends DeltaConf>(gen: prng.PRNG, $d: s.Schema<Delta<Conf_1>>, conf?: {
source?: DeltaAny | null | undefined;
minChildOps?: number | undefined;
maxChildOps?: number | undefined;
attribution?: boolean | undefined;
}): DeltaBuilder<Conf_1>;
/**
* @overload
* @return {DeltaBuilder<{}>}
*/
export function create(): DeltaBuilder<{}>;
/**
* @template {string|null} NodeName
* @overload
* @param {NodeName} nodeName
* @return {DeltaBuilder<NodeName extends string ? { name: NodeName } : {}>}
*/
export function create<NodeName extends string | null>(nodeName: NodeName): DeltaBuilder<NodeName extends string ? {
name: NodeName;
} : {}>;
/**
* @template {string} NodeName
* @template {s.Schema<DeltaAny>} Schema
* @overload
* @param {NodeName} nodeName
* @param {Schema} schema
* @return {Schema extends s.Schema<Delta<infer Conf>> ? DeltaBuilder<Conf, true> : never}
*/
export function create<NodeName extends string | null, Schema extends s.Schema<DeltaAny>>(nodeName: NodeName, schema: Schema): Schema extends s.Schema<Delta<infer Conf_1>> ? DeltaBuilder<Conf_1, true> : never;
/**
* @template {s.Schema<DeltaAny>} Schema
* @overload
* @param {Schema} schema
* @return {Schema extends s.Schema<Delta<infer Conf>> ? DeltaBuilder<Conf, true> : never}
*/
export function create<Schema extends s.Schema<DeltaAny>>(schema: Schema): Schema extends s.Schema<Delta<infer Conf_1>> ? DeltaBuilder<Conf_1, true> : never;
/**
* @template {string|null} NodeName
* @template {{[k:string|number]:any}|null} Attrs
* @template {Array<any>|string} [Children=never]
* @overload
* @param {NodeName} nodeName
* @param {Attrs} attrs
* @param {Children} [children]
* @return {DeltaBuilder<CondensedDeltaConf<NodeName,Attrs,Children>>}
*/
export function create<NodeName extends string | null, Attrs extends {
[k: string | number]: any;
} | null, Children extends Array<any> | string = never>(nodeName: NodeName, attrs: Attrs, children?: Children | undefined): DeltaBuilder<CondensedDeltaConf<NodeName, Attrs, Children>>;
/**
* Build a delta from positional args: an optional node name, optional attrs, then any number of
* children (each either a string or an array of embeds) - see {@link create} for the fixed-arity
* condensed form.
*
* Typed as a set of call signatures instead of `@overload` tags, because a rest parameter can't be
* declared consistently in an `@overload` tag: the checker only turns `@param {...X} children`
* into `X[]` if the implementation's rest parameter has the same name, otherwise it takes `X` as
* the type of the whole rest array - while the declaration emit always writes `...children: X[]`.
* lib0's source check and the consumers of the emitted declarations hence saw different
* signatures. `Children` is the tuple of all children arguments, so that string and array children
* can be mixed (`Children[number]` is the union of them).
*
* @type {{
* <NodeName extends string|null, Children extends Array<Array<any>|string> = []>(nodeName: NodeName, ...children: Children): DeltaBuilder<CondensedDeltaConf<NodeName,null,Children[number]>>,
* <Children extends Array<Array<any>|string> = []>(...children: Children): DeltaBuilder<CondensedDeltaConf<null,null,Children[number]>>,
* <Attrs extends {[k:string|number]:any}|null, Children extends Array<Array<any>|string> = []>(attrs: Attrs, ...children: Children): DeltaBuilder<CondensedDeltaConf<null,Attrs,Children[number]>>,
* <NodeName extends string|null, Attrs extends {[k:string|number]:any}|null, Children extends Array<Array<any>|string> = []>(nodeName: NodeName, attrs: Attrs, ...children: Children): DeltaBuilder<CondensedDeltaConf<NodeName,Attrs,Children[number]>>
* }}
*/
export const from: {
<NodeName_1 extends string | null, Children_1 extends Array<Array<any> | string> = []>(nodeName: NodeName_1, ...children: Children_1): DeltaBuilder<CondensedDeltaConf<NodeName_1, null, Children_1[number]>>;
<Children_1 extends Array<Array<any> | string> = []>(...children: Children_1): DeltaBuilder<CondensedDeltaConf<null, null, Children_1[number]>>;
<Attrs_1 extends {
[k: string | number]: any;
} | null, Children_1 extends Array<Array<any> | string> = []>(attrs: Attrs_1, ...children: Children_1): DeltaBuilder<CondensedDeltaConf<null, Attrs_1, Children_1[number]>>;
<NodeName_1 extends string | null, Attrs_1 extends {
[k: string | number]: any;
} | null, Children_1 extends Array<Array<any> | string> = []>(nodeName: NodeName_1, attrs: Attrs_1, ...children: Children_1): DeltaBuilder<CondensedDeltaConf<NodeName_1, Attrs_1, Children_1[number]>>;
};
/**
* Shorthand for `delta.create().insert(..)` — see {@link DeltaBuilder#insert}.
*
* ## Builder shorthands
*
* A changeset is written as a chain (see the readme's "condensed vs. builder chain"), and the
* `create()` head of that chain carries no information. Every content/attr builder method is
* therefore also exported standalone — {@link insert}, {@link modify}, {@link retain},
* {@link delete_} (trailing underscore: `delete` is a reserved word),
* {@link setAttr}, {@link setAttrs}, {@link deleteAttr}, {@link modifyAttr} — each returning the very
* same {@link DeltaBuilder}, so the rest of the chain is unchanged:
*
* delta.retain(5).delete(6).insert('!') // ⇔ delta.create().retain(5).delete(6).insert('!')
* delta.delete_(6) // ⇔ delta.create().delete(6)
*
* There is deliberately no `format` shorthand: formatting is the second argument of
* `insert`/`retain`/`modify` (`delta.retain(5, { bold: true })`). The ambient-context setters
* (`useFormats` & co), the mark methods, `apply`/`append`/`rebase` and the terminal methods (`done`,
* `toJSON`, ..) are not mirrored — they either say nothing on an empty delta or don't build one.
*
* Each shorthand is typed by indexing the method off {@link DeltaBuilder}, pinned to `create()`'s
* zero-arg overload — so a shorthand and its `create()`-headed equivalent infer the identical conf,
* with no re-declared generics to drift. The type arguments must be written out
* (`DeltaBuilder<{}, false>['insert']`, not `DeltaBuilder['insert']`): a bare reference to a generic
* type in JSDoc resolves its parameters to `any` rather than to the declared defaults, and
* `FixedConf = any` satisfies both arms of `insert`'s `FixedConf extends true ? ..` branch, which
* collapses the accreted conf.
*
* @type {DeltaBuilder<{}, false>['insert']}
*/
export const insert: DeltaBuilder<{}, false>["insert"];
/**
* Shorthand for `delta.create().modify(..)` — see {@link DeltaBuilder#modify} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['modify']}
*/
export const modify: DeltaBuilder<{}, false>["modify"];
/**
* Shorthand for `delta.create().retain(..)` — see {@link DeltaBuilder#retain} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['retain']}
*/
export const retain: DeltaBuilder<{}, false>["retain"];
/**
* Shorthand for `delta.create().delete(..)` — see {@link DeltaBuilder}'s `delete` and {@link insert}.
*
* Trailing underscore because `delete` is a reserved word: `export const delete` is a syntax error,
* and the rename clause that would work at runtime (`export { _delete as delete }`) makes `tsc` 6
* emit a duplicated specifier into the `.d.ts` (`export { _delete as delete, _delete as delete }`),
* which then fails `npm run check-dist-types` with "Duplicate identifier". The bug is specific to
* declaration emit from a `.js` file — the same clause emits correctly from a `.ts` — so it cannot
* be worked around in source; re-test it when the TypeScript floor moves.
*
* @type {DeltaBuilder<{}, false>['delete']}
*/
export const delete_: DeltaBuilder<{}, false>["delete"];
/**
* Shorthand for `delta.create().setAttr(..)` — see {@link DeltaBuilder#setAttr} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['setAttr']}
*/
export const setAttr: DeltaBuilder<{}, false>["setAttr"];
/**
* Shorthand for `delta.create().setAttrs(..)` — see {@link DeltaBuilder#setAttrs} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['setAttrs']}
*/
export const setAttrs: DeltaBuilder<{}, false>["setAttrs"];
/**
* Shorthand for `delta.create().deleteAttr(..)` — see {@link DeltaBuilder#deleteAttr} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['deleteAttr']}
*/
export const deleteAttr: DeltaBuilder<{}, false>["deleteAttr"];
/**
* Shorthand for `delta.create().modifyAttr(..)` — see {@link DeltaBuilder#modifyAttr} and {@link insert}.
*
* @type {DeltaBuilder<{}, false>['modifyAttr']}
*/
export const modifyAttr: DeltaBuilder<{}, false>["modifyAttr"];
export function diff<Conf_1 extends DeltaConf>(d1: Delta<Conf_1>, d2: NoInfer<Delta<Conf_1>>, options?: DiffOptions): Delta<Conf_1>;
export function inverse<Conf_1 extends DeltaConf>(d: DeltaAny, base: Delta<Conf_1>): Delta<Conf_1>;
export function diffChangesetWithSeparator(changeset: Array<{
index: number;
remove: Array<any>;
insert: Array<any>;
}>, separator: RegExp, leftmostIndex?: number): any[];
/**
* Provenance metadata on a content/attr op: *who/what* inserted, deleted, or formatted it. The canonical
* shape below is a convention — apply/diff/equality treat attribution as an **opaque** object (never branching
* on these field names), so custom keys flow through — with ONE exception: the nested `format` key merges per
* inner key (one level), so applying `{format:{italic:[…]}}` *adds* italic while keeping a pre-existing
* `{format:{bold:[…]}}`, and `{format:{bold:null}}` removes just that inner key (an emptied `format` is
* dropped). Every other key is flat/wholesale. The `format`/`formatAt` part exists only on
* children (content ops), never on node attribute ops. As an *update value* on `retain`/`modify`/`*Attr`,
* attribution uses the same unified tri-state as {@link Formats} (`undefined` skip / `null`
* clear / `{k:v}` set / `{k:null}` remove) — see the delta `readme.md` "Formats & Attributions". The blanket
* `null`-clear channel caveat on {@link Formats} applies here too; note `rebase` does not
* reconcile attribution at all (concurrent attribution edits don't converge), so prefer deterministic
* attribution assignment outside of concurrent editing.
*/
export type Attribution = {
insert?: string[];
insertAt?: number;
delete?: string[];
deleteAt?: number;
format?: Record<string, string[]>;
formatAt?: number;
};
/**
* Rich-text formatting attributes (`{ bold: true, … }`). As an *update value* on `retain`/`modify` it is a
* unified tri-state (identical to {@link Attribution}): `undefined`/omitted = skip, `null` = clear all,
* `{k:v}` = set, `{k:null}` = remove key — see the delta `readme.md` "Formats & Attributions".
*
* ⚠️ **Blanket `null` clear is a local-only utility — never send it over a channel.** A `null` clear carries
* no key information, so it cannot be reconciled key-by-key under `rebase`: a clear *always wins* a concurrent
* edit (priority-independent — that is what makes it converge), which silently DROPS the other side's set. For
* collaborative / transmitted data, clear keys individually with `{k:null}` removals instead — those reconcile
* by priority and converge without data loss (this is what {@link diff} emits and what the rebase fuzz uses).
*/
export type Formats = {
[key: string]: any;
};
export type MarkJSON = {
id: string;
key: number | string;
assoc: 1 | -1;
attrs?: object;
transient?: boolean;
};
export type DeltaJSON = {
type: "delta";
name?: string;
attrs?: { [Key in string | number]: DeltaAttrOpJSON; };
children?: Array<DeltaListOpJSON>;
marks?: Array<MarkJSON>;
deleteMarks?: Array<string>;
};
export type DeltaListOpJSON = {
type: "insert";
insert: string | Array<any>;
format?: {
[key: string]: any;
};
attribution?: Attribution;
} | {
delete: number;
} | {
type: "retain";
retain: number;
format?: {
[key: string]: any;
} | null;
attribution?: Attribution | null;
} | {
type: "modify";
value: object;
format?: {
[key: string]: any;
} | null;
attribution?: Attribution | null;
};
export type DeltaAttrOpJSON = {
type: "insert";
value: any;
attribution?: Attribution;
} | {
type: "delete";
attribution?: Attribution;
} | {
type: "modify";
value: DeltaJSON;
attribution?: Attribution | null;
};
export type ChildrenOpAny = TextOp | InsertOp<any> | DeleteOp<any> | RetainOp | ModifyOp<any>;
export type AttrOpAny = SetAttrOp<any> | DeleteAttrOp<any> | ModifyAttrOp;
export type _OpAny = ChildrenOpAny | AttrOpAny;
export type AddToAttrs<Attrs_1 extends { [Key in string | number]: any; }, Key extends string | number, Val extends unknown> = { [K in (Key | keyof Attrs_1)]: (unknown extends Attrs_1[K] ? never : Attrs_1[K]) | (Key extends K ? Val : never); } & {};
export type MergeAttrs<Attrs_1 extends { [Key in string | number | symbol]: any; }, NewAttrs extends { [Key in string | number | symbol]: any; }> = { [K in (keyof NewAttrs | keyof Attrs_1)]: (unknown extends Attrs_1[K] ? never : Attrs_1[K]) | (unknown extends NewAttrs[K] ? never : NewAttrs[K]); };
export type DeltaAny = Delta<any>;
export type DeltaBuilderAny = DeltaBuilder<any>;
export type DeltaConf = {
name?: string | undefined;
children?: fingerprintTrait.Fingerprintable;
text?: boolean | undefined;
attrs?: {
[K: string]: fingerprintTrait.Fingerprintable;
[K: number]: fingerprintTrait.Fingerprintable;
} | undefined;
recursiveChildren?: boolean | undefined;
recursiveAttrs?: boolean | undefined;
};
/**
* Coerce a computed conf to provably satisfy the `DeltaConf` constraint. Declaration emit re-checks
* type arguments eagerly, so a deeply-computed conf (mapped/recursive) passed to `Delta<…>` /
* `Transformer<…>` must be wrapped here: the conditional exposes `DeltaConf` as its upper bound,
* letting the constraint resolve without forcing TS to expand the (self-referential) body.
*/
export type AsDeltaConf<T> = T extends infer DC extends DeltaConf ? DC : never;
export type DeltaConfGetName<Conf_1 extends DeltaConf> = Conf_1 extends {
name: infer Name_1;
} ? (unknown extends Name_1 ? any : (Exclude<Name_1, undefined>)) : any;
export type DeltaConfGetChildren<Conf_1 extends DeltaConf> = (Conf_1 extends {
children: infer Children_1;
} ? (unknown extends Children_1 ? any : Children_1) : never) | (Conf_1 extends {
recursiveChildren: true;
} ? Delta<Conf_1> : never);
export type DeltaConfGetAllowedChildren<Conf_1 extends DeltaConf, FixedConf extends boolean> = FixedConf extends true ? DeltaConfGetChildren<Conf_1> : any;
export type DeltaConfGetText<Conf_1 extends DeltaConf> = 0 extends (1 & Conf_1) ? string : (Conf_1 extends {
text: true;
} ? string : never);
export type DeltaConfGetAttrs<Conf_1 extends DeltaConf> = import("../ts.js").TypeIsAny<Conf_1, {
[K: string | number]: any;
}, (Conf_1 extends {
attrs: infer Attrs_1;
} ? (Attrs_1 extends undefined ? {} : Attrs_1) : {})>;
export type DeltaConfGetAllowedAttrs<Conf_1 extends DeltaConf, FixedConf extends boolean> = FixedConf extends true ? DeltaConfGetAttrs<Conf_1> : {
[K: string | number]: any;
};
export type DeltaConfGetRecursiveChildren<Conf_1 extends DeltaConf> = Conf_1 extends {
recursiveChildren: true;
} ? true : false;
export type DeltaConfigGetRecursiveAttrs<Conf_1 extends DeltaConf> = Conf_1 extends {
recursiveAttrs: true;
} ? true : false;
/**
* Transform Delta(Builder) to a normal delta: a `DeltaBuilder<Conf>` becomes `Delta<Conf>`, anything
* else passes through.
*
* Infers the conf from `DeltaBuilder` on purpose, not from `Delta<infer Conf>`. lib0's own source
* check never had a problem with the latter, but a consumer type-checks the emitted declaration
* files, and there matching a builder against `Delta<infer Conf>` is structural: TypeScript walks
* `Delta`'s members and recurses through {@link DeltaConfGetChildren}'s recursive branch until its
* instantiation-depth limit, so every nested condensed builder (for example
* `create().insert([create('c', {}, [create('p', {}, 'x')])])`) failed with TS2589 in
* y-prosemirror and yjs. The structural walk also leaked the grandchild conf into the child
* union; inferring from the builder keeps the nesting exact. dist-check/consumer.js pins both
* against dist.
*/
export type _SanifyDelta<V> = V extends never ? never : (import("../ts.js").TypeIsAny<V, any, V extends DeltaBuilder<infer Conf_1, any> ? Delta<Conf_1> : V>);
export type PrettifyDeltaConf<Conf_1 extends DeltaConf> = import("../ts.js").Prettify<{ [K in keyof Conf_1]: K extends "attrs" ? import("../ts.js").Prettify<{ [KA in keyof Conf_1[K]]: _SanifyDelta<Conf_1[K][KA]>; }, 1> : (K extends "children" ? _SanifyDelta<Conf_1[K]> : Conf_1[K]); }, 1>;
export type DeltaConfOverwrite<D1 extends DeltaConf, D2> = (import("../ts.js").TypeIsAny<D1, any, PrettifyDeltaConf<{ [K in (keyof D1 | keyof D2)]: K extends keyof D2 ? D2[K] : (K extends keyof D1 ? D1[K] : never); }>> & {}) extends infer DC extends DeltaConf ? DC : never;
export type ReadableDeltaConf = {
name?: s.Schema<string> | string | Array<string>;
attrs?: s.Schema<{
[key: string | number]: any;
}> | {
[key: string | number]: any;
};
children?: any;
text?: boolean;
recursiveChildren?: boolean;
formats?: {
[k: string]: any;
};
};
/**
* Transforms a ReadableDeltaConf (the input shape of `$delta(spec)`) to a DeltaConf.
*/
export type ReadDeltaConf<DConfSpec extends ReadableDeltaConf> = [DConfSpec extends {
name: infer N;
} ? s.ReadSchemaUnwrapped<N> : any, DConfSpec extends {
attrs: infer A;
} ? s.ReadSchemaUnwrapped<A> : {}, DConfSpec extends {
children: infer C;
} ? s.ReadSchemaUnwrapped<C> : never] extends [infer NodeName_1, infer Attrs_1, infer Children_1] ? AsDeltaConf<PrettifyDeltaConf<(import("../ts.js").TypeIsAny<NodeName_1, {}, {
name: NodeName_1;
}> & ([keyof Attrs_1] extends [never] ? {} : {
attrs: Attrs_1;
}) & ([Children_1] extends [never] ? {} : {
children: Children_1;
}) & (DConfSpec extends {
text: true;
} ? {
text: true;
} : {}) & (DConfSpec extends {
recursiveChildren: true;
} ? {
recursiveChildren: true;
} : {}))>> : never;
/**
* The conf produced by the condensed factories ({@link create}'s 3-arg form and {@link from}) -
* the whole node declared in one call instead of built up with chained `setAttr`/`insert`. Routed
* through {@link DeltaConfOverwrite} - and hence `PrettifyDeltaConf`/`_SanifyDelta` - so a condensed
* call yields exactly the conf its `create(name).setAttrs(attrs).insert(children)`
* equivalent would: delta-valued attrs/children normalize to `Delta<..>` (not `DeltaBuilder<..>`),
* and an unsupplied slot is omitted rather than declared as `children: never` / `text: false`.
*
* The `[X] extends [never]` bracketing is load-bearing: `Extract<never,Array<any>>` is `never`, and
* a bare `never extends Array<infer Ac>` matches with `Ac = never`.
*/
export type CondensedDeltaConf<NodeName_1 extends string | null, Attrs_1 extends {
[k: string | number]: any;
} | null, Children_1 extends Array<any> | string> = DeltaConfOverwrite<NodeName_1 extends string ? {
name: NodeName_1;
} : {}, (Attrs_1 extends null ? {} : {
attrs: Attrs_1;
}) & ([Extract<Children_1, Array<any>>] extends [never] ? {} : (Extract<Children_1, Array<any>> extends Array<infer Ac> ? (unknown extends Ac ? {} : {
children: Ac;
}) : {})) & ([Extract<Children_1, string>] extends [never] ? {} : {
text: true;
})>;
export type DiffOptions = {
/**
* Predicate deciding when two nodes
* are paired into a `modify` (vs. replaced wholesale). Defaults to comparing names
* (`(d1, d2) => d1.name === d2.name`). Called as `compare(fromNode, toNode)`.
*/
compare?: ((d1: DeltaAny, d2: DeltaAny) => boolean) | undefined;
/**
* By default `diff` does **not** produce a fully fresh delta: wherever
* it emits content from `d2` — a wholesale-inserted child node, or a delta-valued attribute — it *shares*
* that nested delta by reference, so the result aliases `d2`'s subtrees. Set `true` to
* {@link cloneDeep deep-clone} every such delta (children **and** attributes) as it is included in the
* output, yielding a result that shares no structure with `d2` (and is safe to hand to something that
* manipulates deltas in place, e.g. a transformer).
*/
clone?: boolean | undefined;
/**
* Where the change starts, as a position into `d1`: the
* `path`'s numbers are content offsets (the trailing number is the gap the change starts at, in pre-edit
* coordinates — the `from` of the editor transaction), string steps descend into attributes; `assoc` and
* `attrs` are ignored. Places the first edit there when the content allows it (a wrong hint only shifts
* placement, never correctness) — see "The hint" above.
*/
hint?: import("./position.js").Pos | undefined;
};
/**
* Where a lockstep walk of two states stands: the current op of each side and the units of it already
* consumed from the walked end.
*/
export type Cursors = {
a: ChildrenOpAny | null;
ai: number;
b: ChildrenOpAny | null;
bi: number;
};
import * as s from '../schema.js';
import * as list from '../list.js';
import * as equalityTrait from '../trait/equality.js';
import * as fingerprintTrait from '../trait/fingerprint.js';
/**
* @template {{[Key in string|number]: any}} Attrs
* @template {string|number} Key
* @template {any} Val
* @typedef {{ [K in (Key | keyof Attrs)]: (unknown extends Attrs[K] ? never : Attrs[K]) | (Key extends K ? Val : never) } & {}} AddToAttrs
*/
/**
* @template {{[Key in string|number|symbol]: any}} Attrs
* @template {{[Key in string|number|symbol]: any}} NewAttrs
* @typedef {{ [K in (keyof NewAttrs | keyof Attrs)]: (unknown extends Attrs[K] ? never : Attrs[K]) | (unknown extends NewAttrs[K] ? never : NewAttrs[K]) }} MergeAttrs
*/
/**
* A cursor/selection anchor stored inside a delta tree (see {@link import('./position.js').marksToPositions}).
*
* - `key` — the *terminal* step of the position: a content offset (number) or an attribute key
* (string) within the node that holds the mark.
* - `id` — a unique, user-defined identifier.
* - `assoc` — the gravity at a boundary (left `-1` / right `1`).
* - `attrs` — optional user-supplied data carried with the mark **by reference**: the same
* object is shared across the mark, its `copy`/`clone`s, `toJSON`, and every `MarkPos` from
* `marksToPositions`, so the caller must treat it as immutable (do not mutate it after attaching).
* - `transient` — the mark only rides through a mapping and must never be stored (see the field doc).
*
* A `Mark` is **immutable** — never mutate one in place; to "move" a mark, replace it with a fresh
* `Mark` via {@link Mark#copy} (the {@link Marks} set keys by id, so re-adding the same id replaces
* it). Immutability lets a `Mark` be shared freely across a delta and its clones. The class is not
* exported — construct via {@link createMark} and validate via {@link $mark}.
*/
declare class Mark {
/**
* @param {number|string} key
* @param {string} [id] unique id; defaults to a fresh GUID
* @param {1|-1} [assoc] gravity at a boundary; defaults to right (`1`)
* @param {object?} [attrs] optional user data, stored by reference; treat as immutable
* @param {boolean} [transient] the mark must never be stored; see the field doc
*/
constructor(key: number | string, id?: string, assoc?: 1 | -1, attrs?: object | null, transient?: boolean);
/**
* @readonly
* @type {number|string}
*/
readonly key: number | string;
/**
* @readonly
* @type {string}
*/
readonly id: string;
/**
* @readonly
* @type {1|-1}
*/
readonly assoc: 1 | -1;
/**
* @readonly
* @type {object?}
*/
readonly attrs: object | null;
/**
* A transient mark exists only to ride through a mapping (see
* {@link import('./position.js').mapPositionsA}) and must never be stored: a consumer that
* maintains persistent state (a document, a transformer's internal model of one) either filters
* transient marks before applying a change to that state, or removes them when found on
* final/settled state. How that is achieved is left to the implementation — the core does not
* enforce it (today nothing in lib0 stores marks outside a document, so nothing needs to).
*
* @readonly
* @type {boolean}
*/
readonly transient: boolean;
/**
* A copy of this mark, optionally at a different `key` (used to "move" an otherwise-immutable mark).
*
* @param {number|string} [key]
* @return {Mark}
*/
copy(key?: number | string): Mark;
/**
* @return {MarkJSON}
*/
toJSON(): MarkJSON;
$type: s.Schema<Mark>;
/**
* @param {Mark} other
*/
[equalityTrait.EqualityTraitSymbol](other: Mark): boolean;
}
/**
* @typedef {Delta<any>} DeltaAny
*/
/**
* @typedef {DeltaBuilder<any>} DeltaBuilderAny
*/
/**
* @typedef {object} DeltaConf
* @property {string} [DeltaConf.name]
* @property {fingerprintTrait.Fingerprintable} [DeltaConf.children=never]
* @property {boolean} [DeltaConf.text=never]
* @property {{[K:string|number]:fingerprintTrait.Fingerprintable}} [DeltaConf.attrs={}]
* @property {boolean} [DeltaConf.recursiveChildren=false]
* @property {boolean} [DeltaConf.recursiveAttrs=false]
*/
/**
* Coerce a computed conf to provably satisfy the `DeltaConf` constraint. Declaration emit re-checks
* type arguments eagerly, so a deeply-computed conf (mapped/recursive) passed to `Delta<…>` /
* `Transformer<…>` must be wrapped here: the conditional exposes `DeltaConf` as its upper bound,
* letting the constraint resolve without forcing TS to expand the (self-referential) body.
*
* @template T
* @typedef {T extends infer DC extends DeltaConf ? DC : never} AsDeltaConf
*/
/**
* @template {DeltaConf} Conf
* @typedef {Conf extends {name:infer Name} ? (unknown extends Name ? any : (Exclude<Name,undefined>)) : any} DeltaConfGetName
*/
/**
* @template {DeltaConf} Conf
* @typedef {(Conf extends {children:infer Children} ? (unknown extends Children ? any : Children) : never) | (Conf extends {recursiveChildren:true} ? Delta<Conf> : never)} DeltaConfGetChildren
*/
/**
* @template {DeltaConf} Conf
* @template {boolean} FixedConf
* @typedef {FixedConf extends true ? DeltaConfGetChildren<Conf> : any } DeltaConfGetAllowedChildren
*/
/**
* @template {DeltaConf} Conf
* @typedef {0 extends (1 & Conf) ? string : (Conf extends {text:true} ? string : never)} DeltaConfGetText
*/
/**
* @template {DeltaConf} Conf
* @typedef {import('../ts.js').TypeIsAny<Conf, {[K:string|number]:any}, (Conf extends {attrs:infer Attrs} ? (Attrs extends undefined ? {} : Attrs) : {})>} DeltaConfGetAttrs
*/
/**
* @template {DeltaConf} Conf
* @template {boolean} FixedConf
* @typedef {FixedConf extends true ? DeltaConfGetAttrs<Conf> : {[K:string|number]:any}} DeltaConfGetAllowedAttrs
*/
/**
* @template {DeltaConf} Conf
* @typedef {Conf extends {recursiveChildren:true} ? true : false} DeltaConfGetRecursiveChildren
*/
/**
* @template {DeltaConf} Conf
* @typedef {Conf extends {recursiveAttrs:true} ? true : false} DeltaConfigGetRecursiveAttrs
*/
/**
* Transform Delta(Builder) to a normal delta: a `DeltaBuilder<Conf>` becomes `Delta<Conf>`, anything
* else passes through.
*
* Infers the conf from `DeltaBuilder` on purpose, not from `Delta<infer Conf>`. lib0's own source
* check never had a problem with the latter, but a consumer type-checks the emitted declaration
* files, and there matching a builder against `Delta<infer Conf>` is structural: TypeScript walks
* `Delta`'s members and recurses through {@link DeltaConfGetChildren}'s recursive branch until its
* instantiation-depth limit, so every nested condensed builder (for example
* `create().insert([create('c', {}, [create('p', {}, 'x')])])`) failed with TS2589 in
* y-prosemirror and yjs. The structural walk also leaked the grandchild conf into the child
* union; inferring from the builder keeps the nesting exact. dist-check/consumer.js pins both
* against dist.
*
* @template V
* @typedef {V extends never ? never : (import('../ts.js').TypeIsAny<V,any,V extends DeltaBuilder<infer Conf, any> ? Delta<Conf> : V>)} _SanifyDelta
*/
/**
* @template {DeltaConf} Conf
* @typedef {import('../ts.js').Prettify<{[K in keyof Conf]: K extends 'attrs' ? import('../ts.js').Prettify<{ [KA in keyof Conf[K]]: _SanifyDelta<Conf[K][KA]> },1> : (K extends 'children' ? _SanifyDelta<Conf[K]> : Conf[K]) }, 1>} PrettifyDeltaConf
*/
/**
* @template {DeltaConf} D1
* @template D2
* @typedef {(import('../ts.js').TypeIsAny<D1, any, PrettifyDeltaConf<{[K in (keyof D1|keyof D2)]: K extends keyof D2 ? D2[K] : (K extends keyof D1 ? D1[K] : never)}>> & {}) extends infer DC extends DeltaConf ? DC : never} DeltaConfOverwrite
*/
/**
* @template {string} Name
* @template {{[K in string|number]:any}} Attrs
* @template Children
* @template {boolean} Text
*/
declare class DeltaData<Name extends string, Attrs extends { [K in string | number]: any; }, Children, Text extends boolean> {
/**
* @param {string?} name
* @param {s.Schema<Delta<any>>?} $schema
*/
constructor(name: string | null, $schema: s.Schema<Delta<any>> | null);
name: Name;
$schema: s.Schema<Delta<any>> | null;
/**
* @type {{ [K in keyof Attrs]?: K extends string|number ? (SetAttrOp<Attrs[K],K>|DeleteAttrOp<Attrs[K],K>|(Attrs[K] extends never ? never : (Delta<any> extends Attrs[K] ? ModifyAttrOp<Extract<Attrs[K],Delta<any>>,K> : never))) : never }
* & { [Symbol.iterator]: () => Iterator<{ [K in keyof Attrs]: K extends string|number ? (SetAttrOp<Attrs[K],K>|DeleteAttrOp<Attrs[K],K>|(Attrs[K] extends never ? never : (Delta<any> extends Attrs[K] ? ModifyAttrOp<Extract<Attrs[K],Delta<any>>,K> : never))) : never }[keyof Attrs]> }
* }
*/
attrs: { [K in keyof Attrs]?: K extends string | number ? (SetAttrOp<Attrs[K], K> | DeleteAttrOp<Attrs[K], K> | (Attrs[K] extends never ? never : (Delta<any> extends Attrs[K] ? ModifyAttrOp<Extract<Attrs[K], Delta<any>>, K> : never))) : never; } & {
[Symbol.iterator]: () => Iterator<{ [K in keyof Attrs]: K extends string | number ? (SetAttrOp<Attrs[K], K> | DeleteAttrOp<Attrs[K], K> | (Attrs[K] extends never ? never : (Delta<any> extends Attrs[K] ? ModifyAttrOp<Extract<Attrs[K], Delta<any>>, K> : never))) : never; }[keyof Attrs]>;
};
/**
* @type {list.List<
* | (Text extends true ? (RetainOp|TextOp|DeleteOp<any>) : never)
* | (RetainOp|InsertOp<Children>|DeleteOp<any>|(Delta<any> extends Children ? ModifyOp<Extract<Children,Delta<any>>> : never))
* >}
*/
children: list.List<(Text extends true ? (RetainOp | TextOp | DeleteOp<any>) : never) | (RetainOp | InsertOp<Children> | DeleteOp<any> | (Delta<any> extends Children ? ModifyOp<Extract<Children, Delta<any>>> : never))>;
/**
* All child-ops sizes combined. Note that delete-ops also have a length
*/
childCnt: number;
/**
* @type {any}
*/
origin: any;
/**
* @type {string|null}
*/
_fingerprint: string | null;
isDone: boolean;
/**
* Is the final document and does not contain delete, modify, or retain ops.
*/
isFinal: boolean;
/**
* Leaf {@link Mark marks} whose cursor sits in THIS node (in a settled delta), or the marks to ADD
* to the target node (in a change delta). Local/ephemeral cursor state — NOT part of the document
* fingerprint or equality. `null` when there are none. See {@link Marks}.
*
* @type {Marks?}
*/
marks: Marks | null;
/**
* Mark ids to DELETE (tombstones). Only present in a (non-settled) change delta — like a
* `DeleteAttrOp`, a deletion is dropped from a final delta (a materialized document carries none, at
* any depth). `null` when there are none. Marks follow *last-writer-wins*, treating each op as an
* absolute per-id assignment (present vs absent): adding a mark cancels a pending delete of the same
* id ({@link addMarkTo}) and a delete cancels a present add ({@link deleteMarkTo}), so a node never
* holds both an add and a delete for one id. {@link deleteMarkTo} is the sole writer of this set
* (and `addMarkTo`'s mirror); see {@link applyMarkOps}.
*
* @type {Set<string>?}
*/
deleteMarks: Set<string> | null;
/**
* Conservative "this subtree might hold a {@link Mark}" flag (own {@link DeltaData#marks} or any
* descendant's). Set `true` when a mark is introduced and OR-propagated up to every ancestor; it is
* **never** decremented (removal leaves it conservatively `true`). {@link
* import('./position.js').marksToPositions} is the sole resetter: it prunes subtrees where this is
* `false` (a guaranteed-empty subtree) and lazily clears a stale `true` to `false` when a descended
* subtree turns out to hold none. `false` therefore *guarantees* no marks; `true` only *maybe*.
*/
maybeHasMarks: boolean;
}
import * as prng from '../prng.js';
/**
* The set of leaf {@link Mark marks} on a single delta node, deduplicated by id (so adding the same id
* again replaces it). An internal data-shape class (never a public/`new`-from-outside class): every
* mutation goes through its methods, so a stored {@link Mark} is treated as immutable and is never
* manipulated in place — to "move" a mark you replace it with a fresh `Mark`. {@link clone}/{@link
* slice} copy the set so a `done` delta's marks are never mutated through a shared reference. Marks are
* local/ephemeral cursor state
* and not part of a delta's identity, so this set has no fingerprint/equality of its own.
*/
declare class Marks {
/**
* @type {Array<Mark>}
*/
_marks: Array<Mark>;
get size(): number;
/**
* Add or replace `mark` (by id). Returns `true` if it was added as a new mark, `false` if it
* replaced an existing one with the same id.
*
* @param {Mark} mark
* @return {boolean}
*/
add(mark: Mark): boolean;
/**
* Remove the mark with `id`. Returns `true` if a mark was present and removed, `false` if absent.
*
* @param {string} id
* @return {boolean}
*/
delete(id: string): boolean;
[Symbol.iterator](): ArrayIterator<Mark>;
}
export {};
//# sourceMappingURL=delta.d.ts.map