import { ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js'; /** * Re-measure a paragraph block to fit within a specified maximum width. * * This function performs fast, canvas-based text measurement and line breaking for * paragraphs that need to be reflowed due to column width changes (e.g., when a * document transitions from single-column to multi-column layout, or when floating * images reduce available width). It implements a greedy line-breaking algorithm * with support for tab stops, indentation, and word wrapping. * * Why remeasurement is needed: * - Paragraphs are initially measured at document load for the widest column width * - When placed in narrower columns, text must reflow to fit the reduced width * - Floating images can further reduce available width, requiring dynamic remeasurement * - Remeasurement is expensive, so it's only performed when necessary (width changes) * * Measurement approach: * - Uses HTML5 Canvas API for accurate text width measurement (same as initial measurement) * - Performs greedy word-based line breaking (breaks at whitespace when text exceeds maxWidth) * - Respects paragraph indents (left, right, firstLine, hanging) * - Processes tab stops using OOXML tab stop resolution algorithm * - Falls back to estimated widths if canvas context is unavailable (server-side rendering) * * Limitations: * - Does NOT perform full typography measurement (ascent, descent, font metrics) * - Line height is estimated based on max font size (fontSize * 1.2) * - Does NOT handle complex features like drop caps, justified alignment compression, or bidirectional text * - Intended as a fast path for width-constrained remeasurement, not full initial measurement * * @param block - The paragraph block to measure, containing runs of text/tabs/images and formatting attributes. * Must have a valid runs array with text runs that have fontSize and fontFamily properties. * @param maxWidth - Maximum available width in pixels for the paragraph content. * This should be the column width minus left and right indents, adjusted for any floating images. * Must be a positive number for meaningful line breaking. * @param firstLineIndent - Additional indent to apply to the first line in pixels (default: 0). * Used for in-flow list markers in firstLineIndentMode where the marker consumes horizontal space * on the first line. For standard hanging indent lists, this should be 0 as the marker is positioned * absolutely outside the text flow. * @returns A ParagraphMeasure object containing: * - kind: 'paragraph' (discriminator for measure type) * - lines: Array of Line objects with fromRun/toRun/fromChar/toChar boundaries, width, and lineHeight * - totalHeight: Sum of all line heights in pixels * Note: Does NOT include full typography metrics (ascent, descent) - these are computed by the full measurer * * @throws Does not throw exceptions, but will produce degraded output if: * - maxWidth is zero or negative (lines will be very narrow or degenerate) * - block.runs is empty or invalid (will produce empty or minimal measure) * - Canvas context is unavailable (will use fallback width estimation) * * @example * ```typescript * const block: ParagraphBlock = { * kind: 'paragraph', * id: 'p1', * runs: [ * { text: 'Hello world', fontFamily: 'Arial', fontSize: 16 } * ], * attrs: { * indent: { left: 20, right: 20, firstLine: 0, hanging: 0 } * } * }; * * // Remeasure for a narrower column width * const measure = remeasureParagraph(block, 200); * // Returns: { kind: 'paragraph', lines: [...], totalHeight: 38.4 } * // (text breaks into 2 lines of ~19.2px each) * * // Remeasure with first line indent for list marker * const measureWithIndent = remeasureParagraph(block, 200, 30); * // First line has only 170px available (200 - 30), subsequent lines have full 200px * ``` */ export declare function remeasureParagraph(block: ParagraphBlock, maxWidth: number, firstLineIndent?: number): ParagraphMeasure; //# sourceMappingURL=remeasure.d.ts.map