import type { Block, Document, Inline, Text } from '@contentful/rich-text-types'; export declare class RichTextReplaceError extends Error { constructor(message: string); } export type ReplaceRtfPlainTextMode = 'all' | 'exactlyOne'; export interface ReplaceRtfPlainTextOptions { find: string; mode: ReplaceRtfPlainTextMode; /** * Inline-only Markdown (same as `cms-edit rtf` inline syntax: **bold**, links, etc.). * Omit if {@link replacePlain} is set. */ replaceMarkdown?: string; /** * Literal replacement text (no Markdown). Use for tokens containing `*` so * `*` is not parsed as italic. */ replacePlain?: string; /** * Inline HTML only (no block tags). Parsed to rich-text inline nodes. */ replaceHtml?: string; /** * JSON array of inline rich-text nodes (e.g. `[{"nodeType":"text","value":"x","marks":[],"data":{}}]`). */ replaceJson?: string; /** * When true, match `find` across adjacent sibling text nodes in the same block * (e.g. `**Annual fee: **$95` split across bold + plain nodes). Replacement is * inserted at the match site; surrounding text retains its original marks. * Matches cannot cross inline node boundaries (e.g. hyperlinks). */ ignoreMarks?: boolean; /** * Restrict search-and-replace to table cells in this column (1-indexed). * Non-table content is always included. Omit to search all columns. */ tableCol?: number; /** * Restrict search-and-replace to table cells in this row (1-indexed; row 1 = header row). * Non-table content is always included. Omit to search all rows. */ tableRow?: number; /** * Restrict search-and-replace to table rows where any cell contains this literal text. * Case-sensitive substring match. Non-table content is always included. */ inRowContaining?: string; /** * Restrict search-and-replace to the table column whose header cell (row 1) contains * this literal text. Case-sensitive substring match. Resolved to a column index before * searching; throws {@link RichTextReplaceError} if no header cell matches. * If combined with an explicit {@link tableCol}, both must resolve to the same column or * an error is thrown. */ inColContaining?: string; /** * Scope replacements to blocks under the heading whose plain-text matches this string. * Leading/trailing whitespace in headings is ignored during comparison. * Blocks before the heading or after the next heading of equal/higher level are excluded. * Throws {@link RichTextReplaceError} if no heading matches (error includes available headings). */ section?: string; /** * When multiple headings share the same text, select which occurrence to use (1-indexed). * Defaults to 1 (first match). Only meaningful when {@link section} is also set. * Throws {@link RichTextReplaceError} if the Nth occurrence does not exist. */ sectionNth?: number; /** * A regex string that defines "protected spans" in text nodes. Matches whose range falls * strictly inside a protected span are skipped (the span itself can still be found/replaced). * Example: `'\\{\\*[^{}]*\\*\\}'` to protect `{*...*}` tokens. * When omitted, no span protection is applied. */ protectPattern?: string; /** * When true, count matches and return positions but do not write replacements. * The returned `document` is unchanged. `matchCount` and `matchPositions` are still populated. */ dryRun?: boolean; } export interface ReplaceRtfPlainTextResult { document: Document; /** Number of non-overlapping occurrences of `find` that were replaced (0 if none). */ matchCount: number; /** * Block indices (into `document.content`) that contain at least one match. * Populated for all modes; useful for dry-run previews and exactlyOne diagnostics. */ matchPositions: number[]; } export declare function isHeadingBlock(block: Block): boolean; export declare function getHeadingLevel(block: Block): number; export declare function extractBlockPlainText(block: Block): string; /** * Replaces plain-text occurrences in a Contentful rich-text document. * * **Matching:** By default, search runs only inside individual `text` node `value` strings. * Use `ignoreMarks: true` to match across adjacent sibling text nodes in the same block * (e.g. `**Annual fee: **$95` split by bold). * * **Protected spans:** Pass `protectPattern` (a regex string) to skip matches that fall inside * an existing token matching that pattern. The token itself can still be found/replaced; only * shorter matches landing strictly inside it are skipped. * * **Modes:** `all` replaces every non-overlapping occurrence. `exactlyOne` requires exactly * one occurrence in the entire document or throws {@link RichTextReplaceError} with diagnostics. * * **Dry run:** Pass `dryRun: true` to count and locate matches without writing changes. * * @returns A deep-cloned document with replacements applied (input is not mutated), * plus `matchCount` and `matchPositions` (block indices where matches were found). */ export declare function replaceRtfPlainText(document: Document, options: ReplaceRtfPlainTextOptions): ReplaceRtfPlainTextResult; export declare function walkTextNodes(inlines: (Text | Inline)[], fn: (parent: (Text | Inline)[], index: number, text: Text) => void): void; //# sourceMappingURL=replacePlainText.d.ts.map