import type { VerifyResult } from './types.js'; import { type CleanConfig } from '../metadata.js'; import type { ReplacementValue } from './replacement-keys.js'; /** * Normalize text for value comparison: * - Convert non-breaking spaces to regular spaces * - Normalize smart quotes to straight quotes * - Collapse runs of spaces/tabs to single space (preserve newlines) * - Trim */ export declare function normalizeText(text: string): string; /** * Verify a filled fieldSelector output DOCX: * - All context values appear in the document text * - No unrendered {template_tags} remain * - No leftover [bracketed placeholders] from the replacement map remain * - No doubled currency or percent sigils from a value that already carried the * sign the source supplies * - Footnotes removed (if clean config specified) * - Drafting note paragraphs removed (if clean config specified) */ export declare function verifyOutput(outputPath: string, values: Record, replacements: Record, cleanConfig?: CleanConfig, cleanedSourcePath?: string): Promise; /** * Return actionable diagnostics for malformed complex Word fields and REF * instructions whose bookmark target is absent. Both atomic `w:fldSimple` * fields and complex begin/instrText/separate/end fields are supported; field * instructions may be split across any number of runs. */ export declare function validateWordFields(docxPath: string): string[]; /** * Whether the first block-level element of is a paragraph with no * visible content (no text and no drawing/picture/object). */ export declare function isFirstBodyParagraphEmpty(docxPath: string): boolean; /** * A textless leading paragraph is common Word scaffolding and is not itself a * blank page. Warn only when it also carries explicit page-advancing structure. */ export declare function hasLeadingBlankPageRisk(docxPath: string): boolean; export declare function findRenderedTextArtifacts(docxPath: string): string[]; /** * Find leftover source placeholders from the replacement map that survive in the * filled output. * * Known limitation (deliberate tradeoff): the count baseline treats ANY * reduction of a context key's token as success, so it cannot distinguish an * occurrence a selector deliberately retains (e.g. the two documented `[___]` in * series_designation) from an unexpected extra occurrence of the same token that * failed to fill — the two are textually identical. Fully distinguishing them * would require machine-readable retained-occurrence metadata in the field * contract (fields/.json), which is out of scope here. Two existing * mechanisms cover the realistic paths this check cannot: (a) an unexpected * extra token means the source changed, which the source_sha256 pin / source * drift canary flags before fill; (b) a DECLARED selector occurrence that fails * to resolve surfaces an `unresolved` selector warning. * * Two key shapes are handled differently, matching how the patcher targets them: * * - Simple keys ("[Company Name]") replace every occurrence, so any surviving * occurrence anywhere in the document is reported. * * - Context-qualified keys ("context > placeholder") target one placeholder per * context, so a bare token may legitimately remain elsewhere (an unrelated * context) or be deliberately retained (a selector field that fills only its * declared occurrences). These are handled by comparing the placeholder's * count against the cleaned source: * - With a source baseline, a context key is reported only when the fill * reduced NOTHING (output count >= source count) — i.e. the mapping was * entirely unhandled (a genuine defect, e.g. a caption the patcher/ * selector never touched), as opposed to a partial reduction that leaves * deliberately-retained or selector-verified occurrences behind. This is * the same deterministic baseline-against-source technique used for * formatting anomalies. Counting is done on the flattened text (the same * text the patcher's replacements ultimately land in) so a context that * is unmatchable due to intra-paragraph line breaks — the #607 caption — * is still caught. * - Without a baseline, the key is reported only if an unfilled placeholder * survives at its qualified location — so an intentional occurrence of the * same token in an unrelated context (e.g. "[s]" in "Management Rights * Letter[s]" while the mapped "Closing > [s]" was filled) is not reported. * * Returns the offending key labels (simple keys as their search text; context * keys as their full "context > placeholder" label). */ export declare function findLeftoverPlaceholders(docxPath: string, replacements: Record, cleanedSourcePath?: string): string[]; /** * Count formatting anomalies: single-character underlined runs adjacent to * non-underlined runs. This pattern is the hallmark of quota-based text * redistribution corrupting run-level formatting. */ export declare function countFormattingAnomalies(docxPath: string): number; /** * Extract all text from general OOXML text parts (document, headers, footers, endnotes). */ /** * Extract footnote paragraph text, which `extractAllText()` deliberately omits. * * `getGeneralTextPartNames()` excludes `word/footnotes.xml` because the cleaner * has to special-case its separator paragraphs. That constraint is about * mutation; the sigil-doubling checks only read, and a footnote rendering * `8%%` is a corrupt executed document that must not verify clean. */ export declare function extractFootnoteText(docxPath: string): string; export declare function extractAllText(docxPath: string): string; //# sourceMappingURL=verifier.d.ts.map