/** * The `table` component, resolved down to plain numbers and colours. * * A table's authoring surface is layered: a value may come from the cell, the * column, the table's header defaults, the table's cell defaults, the table's * own border settings, or the built-in defaults — and borders, sizes and * padding each cascade *per side*, so a cell can take its left border from one * layer and its top from another. Getting that cascade right is the whole job, * and it has nothing to do with any renderer. * * So it lives here, once. Both the pre-IR writer (`createTable`) and the DocxIR * compiler resolve a table through this module and then only translate the * result into their own vocabulary. Two copies of these rules would drift, and * the drift would be invisible until a border quietly changed colour. * * Two rules keep a stated border side authoritative: * * - A side named in a per-side `borderColor`/`borderSize` object on the cell * or its column is *explicit*. `hideBorders` silences only inherited * table-level borders; an explicit side keeps its border. A scalar * `borderColor`/`borderSize` restyles without claiming any side. * - Every interior edge is adjudicated: when the two facing cell sides * disagree, one winner is chosen — an explicit side beats an inherited one, * equals fall to OOXML's own weight rules — and mirrored onto both cells. * The emitted package then never contains a contested edge, so Word and * LibreOffice (which resolve conflicts differently) draw the same table. * * Everything returned is resolved: colours are 6-digit hex without `#`, border * sizes are points, padding and heights are points. Nothing here loads content * or touches the filesystem. */ import type { LineSpacing } from '@json-to-office/shared-docx'; import type { ComponentDefinition } from '../types'; import type { ThemeConfig } from '../styles'; export type TableCellContent = string | ComponentDefinition; export type TableFontConfig = { family?: string; size?: number; bold?: boolean; fontWeight?: number; italic?: boolean; underline?: boolean; /** Line spacing of the cell's paragraph; overrides the theme's tableCell style. */ lineSpacing?: LineSpacing; }; export type BorderColor = string | { bottom?: string; top?: string; right?: string; left?: string; }; export type BorderSize = number | { bottom?: number; top?: number; right?: number; left?: number; }; export type Padding = number | { bottom?: number; top?: number; right?: number; left?: number; }; export type CellDefaults = { color?: string; backgroundColor?: string; horizontalAlignment?: 'left' | 'center' | 'right' | 'justify'; verticalAlignment?: 'top' | 'middle' | 'bottom'; font?: TableFontConfig; borderColor?: BorderColor; borderSize?: BorderSize; padding?: Padding; height?: number; }; export type HideBorders = boolean | { top?: boolean; right?: boolean; bottom?: boolean; left?: boolean; insideHorizontal?: boolean; insideVertical?: boolean; }; /** A cell as written, plus the annotations that ride along with it. */ export type TableCellSource = CellDefaults & { comment?: TComment; revision?: TRevision; content?: TableCellContent; }; export type TableColumnSource = { /** Width in points (number) or as a percentage string, e.g. `"40%"`. */ width?: number | string; cellDefaults?: CellDefaults; header?: TableCellSource; cells?: TableCellSource[]; }; export type TableSource = { borderColor?: BorderColor; borderSize?: BorderSize; hideBorders?: HideBorders; cellDefaults?: CellDefaults; headerCellDefaults?: CellDefaults; width?: number; columns: TableColumnSource[]; /** Row-parallel properties, indexed like `columns[].cells`. */ rows?: { revision?: TRowRevision; cantSplit?: boolean; tableHeader?: boolean; }[]; keepInOnePage?: boolean; keepNext?: boolean; repeatHeaderOnPageBreak?: boolean; }; export interface ResolvedSides { top: T; right: T; bottom: T; left: T; } /** One side of a cell's border, after the cascade and the hide rules. */ export interface ResolvedBorder { /** Points. Zero means no border. */ size: number; /** 6-digit hex, no `#`. */ color: string; /** True when `hideBorders` suppressed this side for this cell. */ hidden: boolean; /** * True when the cell or its column named this side in a per-side * `borderColor`/`borderSize` object. An explicit side keeps its border * where `hideBorders` would have suppressed it, and wins its interior edge * against a side that merely inherited — see `adjudicateInteriorEdges`. */ explicit: boolean; } export interface ResolvedCell { content?: TableCellContent; comment?: TComment; revision?: TRevision; /** Text colour: hex, `auto`, or undefined to inherit the table style. */ color?: string; /** Fill: hex, `auto`, or the `transparent` sentinel meaning "no shading". */ backgroundColor?: string; horizontalAlignment: 'left' | 'center' | 'right' | 'justify'; verticalAlignment: 'top' | 'middle' | 'bottom'; font: TableFontConfig; borders: ResolvedSides; /** Points, per side. Absent when no layer asked for padding. */ padding?: ResolvedSides; /** * A cell the source never wrote, kept only so the grid stays rectangular. * * It draws its borders and nothing else — no fill, no padding, no content — * which is what tells a renderer to leave it empty rather than style it. */ missing?: boolean; } export interface ResolvedRow { cells: ResolvedCell[]; /** Points; the tallest height any cell in the row asked for. */ height?: number; isHeader: boolean; /** Set only when the source stated it. */ tableHeader?: boolean; cantSplit?: boolean; revision?: TRowRevision; /** Every cell paragraph in the row keeps with the next one. */ keepNext: boolean; } /** * The table's column grid. * * `twips` is the real OOXML unit. `percent` is what the pipeline has always * written when no column states a width — the grid then carries a percentage * per column rather than a width, which Word tolerates because the table * itself is sized in percent. */ export interface ResolvedColumnGrid { unit: 'twips' | 'percent'; values: number[]; } export interface ResolvedTable { columnGrid: ResolvedColumnGrid; width: { size: number; unit: 'twips' | 'percent'; }; header?: ResolvedRow; rows: ResolvedRow[]; /** Headers repeat across page breaks unless the source disabled it. */ repeatHeader: boolean; /** Emitted when the column widths cannot fit the page. */ overflow?: { totalTwips: number; availableTwips: number; }; } export interface TableModelOptions { /** Reports a value that could not be used. Deduplicated by the caller. */ onWarning?: (code: string, message: string) => void; } /** * Resolve a whole table. * * The generic parameters keep the annotation types (`comment`, `revision`) out * of this module: it carries them through untouched, so neither the pre-IR * writer's docx-shaped types nor the IR's own have to be known here. */ export declare function resolveTableModel(source: TableSource, theme: ThemeConfig, themeName: string, options?: TableModelOptions): ResolvedTable; //# sourceMappingURL=tableModel.d.ts.map