import type { Browser, Page } from '@playwright/test'; import { type SetupStep } from './crawl-surfaces.js'; /** * One-shot capture of a single URL's computed-style map — no spec, no config, * no git. `defineStyleMapCapture` is the right tool when the surfaces live in * your own app and you want the coverage guard, the map store, and record/replay. * This is the tool for a page you just want to point at: a deployed URL, a * static export, or a standalone HTML mockup. Capture it into a directory of * `@.json.gz` maps (+ `.png`) that {@link diffStyleMapDirs} — i.e. * `styleproof-diff ` — compares like any other capture. * * The output is deliberately the same shape a surface capture writes, so a * mockup's map and your app's committed map are directly diffable: capture the * design once, then diff each build against it to measure how close the * implementation is (a diff that shrinks toward zero as it converges). */ /** Raised for bad CLI usage so the bin can print help and exit 2. */ export declare class UsageError extends Error { } export type CaptureUrlOptions = { /** Page to capture. */ url: string; /** Capture file name prefix (`@.json.gz`); default `page`. */ key: string; /** * Viewport widths to sweep, one per @media band. Empty = auto-detect from the * loaded CSSOM (fails loudly on a cross-origin/unreadable stylesheet — pass * widths explicitly for a page whose CSS can't be read, e.g. a cross-origin * font stylesheet). */ widths: number[]; /** Output directory for the maps (+ screenshots). */ out: string; /** Selectors for nondeterministic regions to skip (passed through to capture). */ ignore: string[]; /** Wait for this selector to be visible before capturing (reach the intended state). */ waitSelector?: string; /** Viewport height (default 800). */ height: number; /** Also write a full-page `.png` per capture (default true). */ screenshots: boolean; /** * Crawl the URL's whole interactive surface instead of capturing one state: * drive every non-destructive control, recurse into what opens, capture each * discovered surface under a derived key. See {@link crawlAndCapture}. */ crawl: boolean; /** crawl: recursion depth into opened surfaces (default 16). */ maxDepth: number; /** crawl: fresh controls driven per state (default: unbounded — try them all). */ maxActionsPerState: number; /** crawl: safety backstop on total surfaces (default: unbounded — exhaustive). */ maxStates: number; /** crawl: clear storage on each reset so replay is deterministic (default true). */ resetStorage: boolean; /** crawl: exit non-zero unless every class the page's stylesheets define was * rendered in at least one captured surface (default false — report only). */ requireFullCoverage: boolean; /** crawl: stop as soon as coverage is complete (every defined class seen) or * has converged (no new class for a plateau of surfaces). Turns the crawl * into a FAST coverage check that stops once it has seen everything, instead * of enumerating every combinatorial surface. Default false (exhaustive). */ untilCovered: boolean; /** crawl: JSON file of deterministic setup steps (login, unlock, seed input) * run after every fresh navigation. See {@link loadSetupSteps}. */ setupFile?: string; /** Loaded setup steps (set by the CLI from `setupFile`); applied after every * navigation in BOTH modes, so a gated page's single state is capturable too. */ setup?: SetupStep[]; /** crawl: also capture automatic `loading`/`error` data states of the entry * page (default true). */ dataStates: boolean; /** crawl: concurrent sweep workers (default 4). 1 = byte-stable key attribution. */ workers: number; /** crawl: also crawl every same-origin page the nav links to (default true). * Off = the entry page's interactive surface only. */ followLinks: boolean; /** crawl: JSON file of auth-boundary exclusions (`key → non-empty reason`). */ authBoundaryExcludeFile?: string; /** Loaded auth-boundary exclusions (set by the CLI from the file). */ authBoundaryExclude?: Record; }; /** * Parse `styleproof-capture` argv into options. Pure and throwing so the CLI * flow (help/exit codes) and this parse are testable without a browser. */ export declare function parseCaptureUrlArgs(argv: string[]): CaptureUrlOptions; /** Written artifacts for one width. */ export type CaptureUrlResult = { width: number; map: string; screenshot?: string; }; /** * Capture `opts.url` at each width using an already-open {@link Page}, writing * `/@.json.gz` (+ `.png`). Re-navigates per width so * width-dependent rendering (media queries, `matchMedia`) is captured fresh, and * arms the in-flight request tracker before each navigation so the page's own * load fetches count toward the network-aware settle — same contract as a * surface capture. Returns the files written. */ export declare function captureUrlToDir(page: Page, opts: CaptureUrlOptions): Promise; /** Launch Chromium, capture the URL, and close — the whole bin body given parsed options. */ export declare function runCaptureUrl(opts: CaptureUrlOptions, launch: () => Promise): Promise; /** * Load and validate a `--setup` steps file, interpolating `${ENV_VAR}` in every * `value` and `url` from the environment — so credentials for an input-gated * page live in env vars, never in the file, the shell history, or the maps. * Throws {@link UsageError} on a malformed file or a missing variable. */ export declare function loadSetupSteps(file: string, env?: NodeJS.ProcessEnv): SetupStep[]; /** * Load a `--auth-boundary-exclude` JSON object (`key → reason`). Every reason * must be a non-empty string — empty reasons are rejected so silence cannot * clear a fail-closed authentication boundary. */ export declare function loadAuthBoundaryExclude(file: string): Record;