import type { Digest, ObservationProfile, PageRegion, Provenance, RawCapture, SubjectRef, Viewport, Wiring, Holding } from '@variance-authority/core/format'; import { type IgnoreSelector } from './ignore.js'; import { type StyleIndex } from './css.js'; import { type ConditionEnvironment } from './media.js'; export { detectProfile } from './profile.js'; /** * Extract a `RawCapture` from a live DOM. * * One implementation serves both observation profiles. The alternative — a JSDOM * collector and a Chromium collector — would mean two extraction paths that must * agree, maintained by discipline. Here the only difference is which dimensions * the profile declares observable, and the code reads that declaration rather * than branching on the host. * * The collector's job is *extraction*, not cleanup. Values leave here as * authored: generated ids intact, hashed class names intact, shorthands * unexpanded, cascade losers retained. Normalization is `core`'s, so that it is * versioned by the ruleset rather than by each collector (ADR-0001). * * The one exception is applicability pruning, which cannot be anywhere else: * deciding whether a rule applies requires asking a live DOM. */ /** * What a capture is told rather than reads. * * The region ({@link PageRegion}) is the one the driver opened the page in, * written to the environment key as given. It is passed in rather than read from * `Intl`: only the driver knows whether it chose the region or the host did, and * a timezone nobody chose belongs to the machine, not to the render. A jsdom * capture runs in its Node process's timezone. */ export interface CollectOptions extends PageRegion { readonly subject: SubjectRef; readonly viewport: Viewport; /** Engine identity for the environment key, e.g. `chromium@131.0.6778.33`. */ readonly engine: string; /** * Owner chain provider, usually `provenanceOf` from * `@variance-authority/react`. * * Injected rather than imported so the collector carries no framework * dependency — the same seam other frameworks arrive through later (spec §9). */ readonly provenanceOf?: (element: Element) => Provenance | undefined; /** * Framework wiring provider, usually `wiringOf` from * `@variance-authority/react`. * * A second injection point rather than a field on `provenanceOf`'s return, * because the two answer to different readers and a project may want either * without the other: provenance makes a diff carry a name, wiring is a * dimension of the subject. Absent leaves the band absent, which is what a * page with no framework adapter should look like (ADR-0002). */ readonly wiringOf?: (element: Element) => Wiring | undefined; /** * Held-state provider, usually `holdingOf` from `@variance-authority/react`. * * Opt-in separately from `wiringOf`, and that is the point rather than * symmetry with it. Wiring is a band every run wants; a holding is evidence, * it carries digests of application values, and a project should be able to * decide that question on its own — so it is a third injection and absent by * default. Absent leaves the snapshot exactly as it was before the field * existed, since nothing hashes it. */ readonly holdingOf?: (element: Element) => Holding | undefined; /** * Fonts in play, as `family/weight/style/contentHash`. * * Must be supplied by the caller. A page cannot read the bytes of a font it * was given, so the collector can observe that `Inter` is in use but not * *which* Inter — and a font substitution changes metrics, and therefore * geometry, without changing a line of code. Defaulting this would put a * confident-looking value in the environment key that guarantees nothing; * see the diagnostic emitted when it is omitted. */ readonly fonts?: readonly string[]; /** * Elements this subject renders through portals, usually `portalContentOf` * from `@variance-authority/react`. * * Without it a portalled subtree is invisible: the subject's own container is * byte-identical whether a modal is open or closed, so an opening dialog reads * as `unchanged`. Omitting this on a subject that uses portals is a silent * false negative, which is why the collector reports `portals-not-resolved` * when no provider is supplied (ADR-0007). */ readonly portalsOf?: (root: Element) => readonly Element[]; /** Extra media features to evaluate against, e.g. `prefers-reduced-motion`. */ readonly features?: Readonly>; /** Content hashes for external assets, keyed by request URL. */ readonly assets?: Readonly>; /** * Identity of the stabilization recipe this page was held still with, from * `stabilizeForObservation`. * * Passed in rather than detected, because the collector cannot tell the * difference between a page that was pinned and a page with nothing to pin — * both look like a document with no animation running. Omitting it on a page * that *was* stabilized is the dangerous direction: two recipes then share one * baseline and their disagreement is reported as a change with a component's * name on it. */ readonly stabilization?: Digest; /** * A style index already built for this document, from `indexStyleSheets`. * * Indexing walks every rule on the page; matching walks only the buckets this * subject's elements key into. Every subject in a session shares one document * and one set of sheets, so rebuilding the index per subject repeats the * expensive half until it is most of what a collection costs — and collecting * and acquiring the same subject pays for it twice. `AcquireOptions.index` * exists for this reason; this is the same seam on the comparison side. * * Reuse is opt-in because staleness is not detectable from here. A subject that * injects a stylesheet invalidates every later subject's index, and an index * that misses those rules prunes declarations that now apply — a false * `unchanged`, the failure this system exists to prevent. The holder must * therefore invalidate on the *content* of the sheets: a session already * fingerprints them on every probe, so the check is free there and no cheaper * signal (a sheet count, a run counter, a timestamp) is a substitute, since * rewriting a rule in place changes none of them. * * An index built for different conditions is refused rather than used; see * `StyleIndex.conditions`. */ readonly index?: StyleIndex; /** Defaults to `chromium` when the host has a layout engine, else `jsdom`. */ readonly profile?: ObservationProfile; /** * Subtrees the operator excluded, as `(rule id, selector)` pairs (spec 0024). * * Resolved here because running a selector needs a document and nothing above * this has one. What is produced is a *mark* — `RawNode.ignoredBy` — never a * deletion: an element removed from the capture would be absent from every * count downstream, and "absorbed by the `carousel` rule" and "was never * there" are the two states this whole mechanism exists to keep apart. * * Markup markers (`data-variance-ignore`) are honoured whether or not this is * supplied, because they are the operator's declaration too. Neither form * reaches a hash. */ readonly ignore?: readonly IgnoreSelector[]; } /** * The condition environment a capture of this document would be flattened * against. * * Exported because building a reusable index means building one for exactly the * conditions `collect` would have derived, and one of those inputs — the engine's * `@supports` probe — comes from the document's view rather than from the * viewport. A caller assembling a `ConditionEnvironment` by hand would omit it, * `collect` would refuse the index as built for a different environment, and the * reuse would silently never happen. Handing out the derivation is cheaper than * documenting it. */ export declare function conditionsFor(document: Document, viewport: Viewport, features?: Readonly>): ConditionEnvironment; export declare function collect(root: Element, options: CollectOptions): RawCapture; //# sourceMappingURL=collect.d.ts.map