/**
 * linearText — trims that cost one pass, where the regex they replace costs a
 * pass PER STARTING POSITION.
 *
 * Pattern: leaf utility (imports nothing).
 * Role:    asked wherever a run of characters is trimmed from text the library
 *          did not write — base URLs and prefixes from configuration, tokens
 *          and replies from a model, words from a person. It lives here so
 *          those doors share one implementation and one test.
 * Emits:   N/A.
 *
 * ── Why these exist ─────────────────────────────────────────────────────────
 * `s.replace(/\/+$/, '')` reads as "drop the trailing slashes", but a
 * backtracking engine runs it as "at every position, take the slashes that
 * start there and see whether the string ends after them". On `'/' * n + 'x'`
 * that is n attempts of up to n steps each: 16,000 slashes take ~90 ms in V8,
 * a million take minutes, and the event loop is blocked the whole time. Any
 * `X+$` (or `[set]+$`) without a `^` has that shape. These functions walk in
 * from the end once instead — the work is the length of the run they remove,
 * plus one.
 *
 * ── The one rule ────────────────────────────────────────────────────────────
 * Each function returns EXACTLY what the regex in its comment returns, for
 * every input; only the cost differs. The equivalence and the work bound are
 * both pinned by `test/security/linear-text.test.ts`.
 *
 * ```ts
 * import { isSlash, trimTrailing } from '../lib/linearText.js';
 *
 * trimTrailing('https://api.example.com///', isSlash); // 'https://api.example.com'
 * ```
 */
/** Whether one UTF-16 code unit belongs to the run being trimmed. */
export type CharTest = (code: number) => boolean;
/** `/` — base URLs, object-key prefixes and paths. */
export declare const isSlash: CharTest;
/** `-` — slugs. */
export declare const isHyphen: CharTest;
/**
 * Exactly the code units `\s` matches in a JavaScript regular expression:
 * WhiteSpace (tab, vertical tab, form feed, space, no-break space, the
 * byte-order mark and every Unicode `Zs` space) plus LineTerminator (LF, CR,
 * U+2028, U+2029).
 */
export declare const isRegExpWhitespace: CharTest;
/**
 * What a regex `.` does not match — and where `^` and `$` see a line end under
 * the `m` flag: LF, CR, U+2028, U+2029. A scanner that stands in for a regex
 * reads lines by this, never by `\n` alone.
 */
export declare const isLineBreak: CharTest;
/** A test for any one of `chars` — a regex character class with no ranges. */
export declare function anyOf(chars: string): CharTest;
/** Either test — `[ab]` built from `a` and `b`. */
export declare function either(a: CharTest, b: CharTest): CharTest;
/** `s.replace(/^[run]+/, '')`, walking forward once. */
export declare function trimLeading(s: string, drop: CharTest): string;
/** `s.replace(/[run]+$/, '')`, walking back from the end once. */
export declare function trimTrailing(s: string, drop: CharTest): string;
/** `s.replace(/^[run]+|[run]+$/g, '')` — both ends, each walked once. */
export declare function trimBoth(s: string, drop: CharTest): string;
