/** * Editor-neutral list counter manager. Keeps word-layout marker text stable for * abstract-id shared counters and `w:lvlOverride/@w:startOverride` scoping. * * Behavior: * - counters are tracked per abstractId so multiple concrete `numId`s sharing * the same abstract definition continue numbering across the document * - a per-`(numId, level)` `startOverridden` flag scopes counters back to the * single concrete `numId` when an `lvlOverride/startOverride` is in play * - cache mode keeps the fast `lastSeen*` lookup path used by runtime adapters */ type NumId = string | number; type Level = number; type Position = number; type CounterValue = number; type CounterLevelMap = Record; type CounterMap = Record>; type StartSettings = { start: number; restart?: number; startOverridden?: boolean; }; type StartsMap = Record>; type LastSeenMap = Record>; /** * Opaque, same-realm numbering cursor. Its payload is one immutable persistent * state root, so capture and restore are O(1); unchanged numbering scopes are * structurally shared across every retained cursor. Restore is valid only * within the JS realm that captured it and only in compact mode. */ export interface NumberingCursor { readonly __wordLayoutNumberingCursor: true; } export interface NumberingManager { setStartSettings(numId: NumId, level: number, startValue: number, restartValue?: number, startOverridden?: boolean): void; ensureStartSettings(numId: NumId, level: number, startValue: number, restartValue?: number, startOverridden?: boolean): void; setCounter(numId: NumId, level: number, pos: number, value: number, abstractId?: string | number): void; getCounter(numId: NumId, level: number, pos: number): number | null; calculateCounter(numId: NumId, level: number, pos: number, abstractId?: string | number): number; getAncestorsPath(numId: NumId, level: number, pos: number): number[]; calculatePath(numId: NumId, level: number, pos: number): number[]; getCountersMap(): CounterMap; exportSnapshot(): NumberingManagerSnapshot; restoreSnapshot(snapshot: NumberingManagerSnapshot | null): void; /** * Capture a compact, same-realm cursor of current numbering state in O(1). * The returned token is opaque and non-serializable by contract: passing it * through `structuredClone` or a worker boundary strips its brand and * `restoreCursor` rejects it. Throws unless compact mode is enabled. */ captureCursor(): NumberingCursor; /** * Restore state in O(1) from a cursor produced in the same realm. Throws on a * foreign/serialized cursor or when compact mode is not enabled; `null` * resets to the empty state. */ restoreCursor(cursor: NumberingCursor | null): void; _clearCache(): void; enableCache(): void; disableCache(): void; /** * Enable compact (cursor-timeline) mode: the cache-fast lookup path PLUS * suppression of the historical per-position counter maps and the * position-keyed path cache. Sequential queries are served from last-seen * facts. Current state is linear in active scopes, while retained cursors add * only fixed-depth structurally shared transitions. Arbitrary past-position * `getCounter` queries are not answerable in this mode; callers needing them * must use the default (non-compact) mode. */ enableCompactMode(): void; clearAllState(): void; } export interface NumberingManagerSnapshot { startsMap: StartsMap; countersMap: CounterMap; abstractCountersMap: CounterMap; abstractIdMap: Record; lastSeenByAbstractIdMap: LastSeenMap; lastSeenByNumIdMap: LastSeenMap; } export declare function createNumberingManager(): NumberingManager; export {};