import type { Element, ElementContent, Parent, Root, RootContent, Text } from "hast"; import type { Transformer } from "unified"; import { type TransformOptions } from "./transform-options.js"; import { type ProsePass, type ProseView } from "./prose-view.js"; export type ElementPredicate = (node: Element) => boolean; /** Per-text-node skip predicate, called after element-level `shouldSkip`. */ export type TextNodeSkipPredicate = (textNode: Text, ancestors: readonly Element[]) => boolean; export interface ElementTransformOptions { /** * Optional per-text-node skip predicate. When it returns `true` for a * given text node, that node is excluded from the flattened output, is * not passed to the transform function, and its `.value` is left * untouched. Applied after element-level `shouldSkip`. */ shouldSkipText?: TextNodeSkipPredicate; } export interface RehypePunctilioOptions extends TransformOptions, ElementTransformOptions { /** * HTML tag names to skip when applying transformations. * Content inside these elements won't have formatting improvements applied. * * Default: ["code", "pre", "script", "style", "kbd", "var", "samp", "template", "math", "svg"] */ skipTags?: string[]; /** * CSS class names that indicate content should skip formatting. * Elements with any of these classes (or descendants of such elements) * will be skipped. * * Default: [] */ skipClasses?: string[]; /** * Invert the element model: transform text inside every element except the * skip-list (`skipTags`/`skipClasses`) plus `textarea`/`input`/`select`, * whose text is a literal form-control value rather than prose. The default * (`false`) keeps the `TRANSFORMABLE_ELEMENTS` allowlist, transforming only * known prose-bearing tags (and custom elements). * * Default: false */ transformAllElements?: boolean; } /** Option keys handled by `rehypePunctilio` itself rather than `transform()`. */ export declare const REHYPE_ONLY_OPTION_KEYS: readonly string[]; /** Runtime list of valid `rehypePunctilio` option keys. */ export declare const REHYPE_OPTION_KEYS: readonly string[]; /** Flattened text nodes plus the opaque gaps that fell between adjacent ones. */ export interface FlattenedProse { nodes: Text[]; /** Indices into `nodes` (1..n-1) with removed opaque content immediately before them. */ opaqueBefore: Set; } /** Flattens an element's transformable text nodes, tracking opaque gaps. */ export declare function flattenProse(node: Element | ElementContent, shouldSkip: ElementPredicate, options?: ElementTransformOptions): FlattenedProse; export declare function flattenTextNodes(node: Element | ElementContent, shouldSkip: ElementPredicate, options?: ElementTransformOptions): Text[]; export declare function getTextContent(node: Element, shouldSkip?: ElementPredicate): string; export declare function getFirstTextNode(node: Parent | RootContent, depth?: number): Text | null; export declare function assertSmartQuotesMatch(input: string): void; export interface ProseViewOfOptions extends ElementTransformOptions { /** Element-level skip predicate; skipped subtrees contribute no text nodes. */ shouldSkip?: ElementPredicate; } /** * Builds a single ProseView over the element's transformable text nodes, * honoring the element-level `shouldSkip` and per-text-node `shouldSkipText` * predicates. Returns null when the element holds no transformable text. This * view spans opaque gaps; the transform pipeline uses {@link proseViewsOf}, * which splits on them so no pass rewrites across removed atomic content. */ export declare function proseViewOf(element: Element, options?: ProseViewOfOptions): ProseView | null; /** * Builds one ProseView per opaque-delimited segment of the element's text. * Splitting at opaque gaps (removed skipped elements, images, and other atomic * inline content) keeps their surrounding text in separate views, so a pass can * never treat text as adjacent across content that visually separates it. */ export declare function proseViewsOf(element: Element, options?: ProseViewOfOptions): ProseView[]; /** * One entry in an `applyPasses` sequence: a bare pass, or a pass with its own * skip predicates layered on top of the base options (the per-transform * skip-set case, e.g. a fractions pass that additionally skips ``). */ export type PassEntry = ProsePass | { pass: ProsePass; shouldSkip?: ElementPredicate; shouldSkipText?: TextNodeSkipPredicate; }; /** * Runs `passes` in order over `element`'s transformable text, owning the * ProseView lifecycle so callers never touch a view directly. Each pass * commits its edits before the next runs, so passes see each other's * committed output — the same sequencing `transform()`'s pipeline uses. * * Entries whose predicates match the previous entry's share one view; * an entry with different `shouldSkip`/`shouldSkipText` predicates gets a * fresh view (built after the previous pass committed) over the text nodes * that survive both the base `options` predicates and its own. * * The view is a single spanning view (over the whole element, or a run's loose * inline children), with a boundary recorded at every opaque gap (removed * skipped element, image, …). Caller passes stay boundary-aware via * `view.hasBoundary`, so each pass decides for itself whether to act across a * gap — spacing a slash between two skipped `` runs, gluing a dash after a * skipped element — rather than being blocked wholesale. Passes that must not * cross a gap consult the same boundary marks; use {@link proseViewsOf} directly * for hard per-segment views. * * Accepts a bare element (formatted whole) or a {@link ProseUnit} from * {@link collectProseUnits}; a "run" unit formats a container's loose inline * text without pulling in its block children. */ export declare function applyPasses(target: Element | ProseUnit, passes: readonly PassEntry[], options?: ProseViewOfOptions): void; export interface CollectProseBlocksOptions { /** * HTML tag names to skip. Default: the plugin's default skip list * ("code", "pre", "script", ...). */ skipTags?: string[]; /** CSS class names whose elements (and their subtrees) are skipped. Default: [] */ skipClasses?: string[]; /** Additional element-level skip predicate, OR-ed with the tag/class skips. */ shouldSkip?: ElementPredicate; /** Invert the element model as in {@link RehypePunctilioOptions.transformAllElements}. Default: false */ transformAllElements?: boolean; } export type ProseUnit = { kind: "element"; element: Element; } | { kind: "run"; container: Element; children: ElementContent[]; }; /** * Collects the leaf elements under `root` (inclusive) whose text should be * transformed as one prose block: transformable elements with direct text or * inline-only text descendants. Elements with block-level children recurse so * each block transforms independently. Loose inline text mixed among block * children is NOT represented here — use {@link collectProseUnits} to reach it. */ export declare function collectProseBlocks(root: Element, options?: CollectProseBlocksOptions): Element[]; /** * Like {@link collectProseBlocks}, but also returns "run" units — maximal groups * of loose inline siblings sitting beside block children (e.g. the bare text in * `

loose text
`). A consumer that walks elements * cannot otherwise reach that text (it belongs to no element of its own); pass * each unit to {@link applyPasses}, which formats a run without merging its * container's block children. */ export declare function collectProseUnits(root: Element, options?: CollectProseBlocksOptions): ProseUnit[]; export declare function rehypePunctilio(options?: RehypePunctilioOptions): Transformer; export default rehypePunctilio; //# sourceMappingURL=rehype.d.ts.map