@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
132 lines • 6.86 kB
text/typescript
export interface Position {
position: number;
extent: number;
content: string;
line: number;
/**
* Set only when this position originates from an undo/redo navigation, naming
* the direction. On `'undo'` the caret is the PRE-edit position (it did not
* move as forward typing would), so derived state (e.g. the comment/highlight
* map) must reverse the edit rather than assume a post-edit caret. Absent for
* a fresh edit.
*/
history?: 'undo' | 'redo';
/**
* On an `'undo'`, the 0-indexed line the reversed edit was anchored at — its
* POST-edit caret line, which can differ from this (destination) caret when
* the edit ran over a selection that didn't start at the caret (e.g. Select
* All). Lets derived state reverse the edit at the exact line the forward
* edit pivoted on instead of guessing from the destination caret.
*/
historyPivotLine?: number;
/**
* Set when the edit removed whole lines starting at the very beginning of a
* line (a selection delete whose start was at column 0). The post-edit caret
* then sits on the line that shifted up from BELOW the deletion, so the edit's
* anchor is one line higher than the caret implies. Derived state (comment
* map) must drop its anchor by one or markers on the deleted first line are
* stranded. Rides through undo as well so the reversal anchors identically.
*/
deletedFromLineStart?: boolean;
/**
* Set when the tracked selection is a BACKWARD range — its focus (the moving
* end) sits at the range START, above/before the anchor. `position`/`extent`
* only describe the range's extent, not which end is the focus, so a backward
* Shift+Arrow selection that survives a host re-render would otherwise be
* rebuilt as a forward range (focus flipped to the bottom), making the next
* Shift+Arrow extend from the wrong end. The restore honors this flag by
* collapsing to the anchor then extending back to the focus. Absent for a
* collapsed caret or a forward selection.
*/
backward?: boolean;
}
export declare const getCurrentRange: () => Range;
export declare const setCurrentRange: (range: Range) => void;
/**
* Narrow a `Node | null` to `Element | null` using a runtime check so
* downstream code can reason about element-only APIs without a cast.
*/
export declare const asElement: (node: Node | null | undefined) => Element | null;
/**
* Pull the next element out of a `SHOW_ELEMENT` `TreeWalker` with a
* runtime check rather than a type cast. Tree walkers configured for
* `SHOW_ELEMENT` only emit elements in practice, but the DOM type
* exposes `Node | null`.
*/
export declare const nextElement: (walker: TreeWalker) => Element | null;
export declare const isUndoRedoKey: (event: KeyboardEvent) => boolean;
export declare const isPlaintextInputKey: (event: KeyboardEvent) => boolean;
export declare const toString: (element: HTMLElement) => string;
export interface LineInfo {
/** Full text of the requested line. */
currentLine: string;
/** Full text of `lineIndex - 1`. Empty when `lineIndex <= 0`. */
prevLine: string;
/** Full text of `lineIndex + 1`. Empty when there is no next line. */
nextLine: string;
/**
* True when a real line follows `currentLine` — including a blank
* line. False when the document ends at `currentLine` (matching the
* old `toString(element).split('\n').slice(0, -1)` semantics where
* the phantom empty entry after the trailing `\n` does not count as
* a next line).
*/
hasNextLine: boolean;
}
/**
* Walk text nodes to extract the requested line plus its immediate
* neighbors without materializing the full document text or splitting
* it into a per-line array. Used by per-keystroke handlers (arrow keys,
* Backspace, gutter snapping) so they stay O(chars-on-touched-lines)
* instead of O(document-length) on every event.
*
* Walks each text node in document order and slices contiguous segments
* directly into the relevant accumulator (`prevLine` / `currentLine` /
* `nextLine`). Skips chunks belonging to lines we don't care about and
* exits as soon as the trailing `\n` of `lineIndex + 1` is consumed.
*
* Mirrors `toString(element).split('\n').slice(0, -1)` semantics:
*
* - `hasNextLine` is `true` whenever a real line follows `currentLine`,
* even if that line is blank — `"a\n\nb\n"` reports a next line for
* row 0. The phantom empty entry that `split` produces after the
* document's trailing `\n` is intentionally ignored.
* - The implicit trailing newline that `toString` appends when the DOM
* doesn't end with one has no effect: we walk raw text content.
*/
export declare const getLineInfo: (element: HTMLElement, lineIndex: number) => LineInfo;
/**
* Convert a `(row, column)` coordinate into an absolute character offset
* by counting newlines through the editable's text nodes, exiting the
* moment we land on the requested row. Avoids the
* `toString(element).split('\n').slice(0, row).join('\n').length`
* round-trip — that pattern allocates the full document string and a
* full per-line array on every `edit.move({row, column})` call.
*
* If the row is past the end of the document, returns the document
* length plus `column` so the eventual `makeRange` clamps gracefully.
*/
export declare const getOffsetAtLineColumn: (element: HTMLElement, row: number, column: number) => number;
export declare const repairUnexpectedLineMerge: (newContent: string, previousContent: string | null, position: Position) => string;
export declare const getPosition: (element: HTMLElement) => Position;
export declare const makeRange: (element: HTMLElement, start: number, end?: number) => Range;
/**
* After makeRange positions a collapsed cursor at a newline boundary via
* setStartAfter(textNode), the cursor ends up inside the *previous* line span
* (after the '\n'). This adjusts the range forward to offset 0 of the
* next text node so the cursor renders on the correct visual line.
*/
export declare const adjustCursorAtNewlineBoundary: (range: Range) => void;
/**
* Rebuild the browser selection from a tracked {@link Position} after a host
* re-render. Recreates the `[position, position + extent]` range (collapsed when
* `extent` is 0) and applies the newline-boundary nudge.
*
* When `position.backward` is set, the range is restored as a BACKWARD selection
* — anchor at the range end, focus at the range start — by collapsing to the end
* and extending back to the start. A range added via `Selection.addRange` is
* always forward, so without this a backward Shift+Arrow selection would have its
* focus flipped to the bottom end on every restore. Forward and collapsed
* positions take the plain `addRange` path unchanged.
*/
export declare const restoreSelection: (element: HTMLElement, position: Position) => void;