import type { FactExtractor } from './extractor.js';
/**
 * `text.match(/\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})\b/)?.[1]`,
 * with ONE attempt per `@` instead of one per position.
 *
 * Unanchored, that pattern starts an attempt at every word boundary, and each
 * one walks the whole run of local-part characters after it looking for an
 * `@`; on `'a.'` repeated with no `@` at all, every attempt walks to the end
 * (16,000 pairs take ~0.5 s in V8). But an attempt can only succeed from
 * inside the run that ends at an `@` (`@` is not a local-part character, so
 * nothing before that run reaches it), the first attempt inside the run is at
 * its leftmost word boundary, and every later one in the same run reaches the
 * same `@` and the same domain — so it succeeds or fails with the first.
 * Runs before different `@`s do not overlap, nor do the domains after them,
 * so the whole search is one pass.
 */
export declare function firstEmail(text: string): string | undefined;
/**
 * Trim trailing punctuation / whitespace from an extracted value — walked in
 * from the end, not `/[…]+$/`: the value is a person's words, and that regex
 * retries from every position of a long whitespace run
 * (`lib/linearText.ts` · "Why these exist").
 */
export declare function cleanValue(s: string): string;
export declare function patternFactExtractor(): FactExtractor;
