/** * Windowing helpers for the paper editor's highlight overlay and gutter. * Rendering every token span and gutter row of a multi-thousand-line * `main.tex` on each keystroke is the editor's dominant cost, so the overlay * mounts only the lines around the textarea's viewport and pads the rest * with fixed-height spacers (the editor forbids soft wrap, so every logical * line is exactly {@link EDITOR_LINE_HEIGHT_PX} tall). All functions here are * pure; the component owns the scroll state. * @module dsh-client-ui-mimir/client/highlight-window */ import type { LatexToken } from './latex-highlight.ts'; /** Editor line height in px; keep in sync with `.editor` in the module CSS. */ export declare const EDITOR_LINE_HEIGHT_PX = 19; /** Extra lines mounted above/below the viewport so small scrolls reuse the DOM. */ export declare const HIGHLIGHT_OVERSCAN_LINES = 20; /** A half-open line window: `start` inclusive, `end` exclusive, both 0-based. */ export interface LineRange { readonly start: number; readonly end: number; } /** * Convert a scroll position into the line window to mount, clamped to * `[0, lineCount]` and widened by the overscan on both sides. * @param scrollTop - the textarea's vertical scroll offset in px. * @param viewportHeight - the textarea's visible height in px (0 when hidden). * @param lineCount - total logical lines of the source. * @param lineHeight - the fixed editor line height in px. * @param overscan - extra lines mounted on each side of the viewport. * @returns the clamped half-open line window. */ export declare function visibleLineRange(scrollTop: number, viewportHeight: number, lineCount: number, lineHeight?: number, overscan?: number): LineRange; /** * Split a flat token list into one token list per logical line. Newlines are * consumed by the split, so the concatenation of `lines[i]` equals * `content.split('\n')[i]`; a token spanning lines (only `$$...$$` math and * `plain` runs can) is divided at the line boundary with its type preserved. * @param tokens - the full-document tokens from `tokenizeLatex`. * @returns per-line token lists; `lines.length` is the source's line count. */ export declare function splitTokensByLine(tokens: readonly LatexToken[]): LatexToken[][]; /** * Display width of one line in monospace columns: a tab advances to the next * multiple of `tabSize`, East-Asian wide code points count double, everything * else counts one. Heuristic by design — it only picks the sizer line that * keeps the overlay's scrollable width in step with the textarea's. * @param line - one logical source line (no trailing newline). * @param tabSize - the editor's tab stop (CSS `tab-size`). * @returns the line's width in `ch` columns. */ export declare function displayColumns(line: string, tabSize?: number): number; /** * Pick the widest line by {@link displayColumns}. The overlay renders it in a * zero-height hidden sizer so its scrollable width matches the textarea's * even though only a window of lines is mounted (the browser measures the * glyphs itself, so tabs and wide chars expand exactly as in the textarea). * @param lines - the source split into logical lines. * @param tabSize - the editor's tab stop (CSS `tab-size`). * @returns the widest line's text, or `''` for an empty source. */ export declare function widestLine(lines: readonly string[], tabSize?: number): string; //# sourceMappingURL=highlight-window.d.ts.map