/** * Declarative option selection for DOCX templates. * * Handles radio-button `( )` and checkbox `[ ]` option groups in table cells. * A per-template `selections.json` config defines groups, and this module * deletes unselected options + their sub-clauses from the DOCX XML before filling. */ import { z } from 'zod'; export declare const SelectionsConfigSchema: z.ZodObject<{ groups: z.ZodArray; standalone: z.ZodOptional; markerless: z.ZodOptional; inline: z.ZodOptional; cellContext: z.ZodOptional; subClauseStopPatterns: z.ZodOptional>; applies_when: z.ZodOptional; }, z.core.$strict>>; options: z.ZodArray; marker: z.ZodString; trigger: z.ZodUnion, z.ZodObject<{ field: z.ZodString; equals: z.ZodUnion; }, z.core.$strict>, z.ZodObject<{ field: z.ZodString; }, z.core.$strict>]>; replaceWith: z.ZodOptional; selectedAction: z.ZodOptional>; removal: z.ZodOptional; anchor: z.ZodString; removeAdjacentBlankParagraphs: z.ZodOptional; }, z.core.$strict>, z.ZodObject<{ kind: z.ZodLiteral<"section">; startAnchor: z.ZodString; endAnchor: z.ZodString; removeAdjacentBlankParagraphs: z.ZodOptional; }, z.core.$strict>, z.ZodObject<{ kind: z.ZodLiteral<"paragraph">; anchor: z.ZodString; match: z.ZodDefault>; expectedMatches: z.ZodLiteral<1>; within: z.ZodOptional>; expectedMatches: z.ZodLiteral<1>; }, z.core.$strict>>; removeAdjacentBlankParagraphs: z.ZodOptional; }, z.core.$strict>], "kind">>; }, z.core.$strict>>; }, z.core.$strict>>; }, z.core.$strict>; export type SelectionsConfig = z.infer; export declare function loadSelectionsConfig(path: string): SelectionsConfig; /** * How many paragraphs one option's marker matched, and whether the option was * selected. Counts are summed across every text part of the document * (document.xml plus headers/footers), because an option legitimately lives in * exactly one of them. */ export interface SelectionOptionReport { groupId: string; optionIndex: number; marker: string; /** True when the option's trigger fired (or it is the default fallback). */ selected: boolean; /** Paragraphs whose text contained the option marker, summed across parts. */ matchCount: number; /** * Paragraphs this option's own removal / replacement / marking logic actually * ACTED ON, summed across parts. * * This is not the same as `matchCount`, and the gap is where the silent * failures live. An option can match paragraphs and still be acted on zero * times: a cell-based group whose options turn out to live in DIFFERENT table * cells resolves no qualifying cell, returns without touching anything, and * leaves every alternative in place — with a non-zero match count for each. * The inline markerless path can likewise match a paragraph and then fail to * splice it. Both leave a document carrying both alternatives, so the * classification below keys the dangerous case on this field, not on * `matchCount`. * * A SELECTED option is normally acted on zero times in the markerless paths * (it is kept as-is), so a zero here is only meaningful for an UNSELECTED * option. */ appliedCount: number; } export interface SelectionsResult { outputPath: string; /** One entry per (group, option), in config order. */ options: SelectionOptionReport[]; } /** * Classification of zero-match options. * * A group is "engaged" when at least one of its options matched at least one * paragraph: the document demonstrably contains this group's alternatives. * That distinction is what makes the dangerous case separable from the benign * one — see `unselectedZeroMatchInEngagedGroup` below. */ export interface SelectionAnomalies { /** * The dangerous case (#720). The option was NOT selected — the intent was * "remove this alternative" — yet nothing was removed for it, while a sibling * option in the same group DID match. The group is demonstrably present in * the document, so its alternative is still there and the filled document * keeps BOTH alternatives. * * Two distinct faults land here: a marker that drifted away from source prose * that is still present (zero matches), and a group that matched but resolved * no location to act on (matches, zero applied — e.g. a cell-based group * whose options sit in different table cells). */ unremovedInEngagedGroup: SelectionOptionReport[]; /** * Nothing in the whole group matched. Either the group does not apply to this * document (partial fixtures, variant sources) or the entire clause moved. * Nothing was left half-removed, so this is advisory. */ unremovedInInertGroup: SelectionOptionReport[]; /** * The option WAS selected but matched nothing, so the alternative meant to be * kept is absent. Suspicious, but it fails visibly (a missing clause) rather * than silently, so it is reported as a warning. */ selectedZeroMatch: SelectionOptionReport[]; } /** Human-readable identifier for one option in a diagnostic message. */ export declare function describeSelectionOption(o: SelectionOptionReport): string; /** Split a selections run's per-option counts into the three anomaly classes. */ export declare function classifySelectionMatches(result: SelectionsResult): SelectionAnomalies; /** * Apply option selections to a DOCX buffer and return the modified buffer. * * For each group in the config: * 1. Find option paragraphs by marker text + radio/checkbox prefix * 2. Verify they share the same table cell * 3. Classify paragraphs as header, option, or sub-clause * 4. Evaluate triggers to determine selected options * 5. Remove unselected options + sub-clauses * 6. Mark selected options as checked */ export declare function applySelections(inputPath: string, outputPath: string, config: SelectionsConfig, data: Record): Promise; //# sourceMappingURL=selector.d.ts.map