@ultimat3/scraping 20.1.6 → 20.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/page.ts CHANGED
@@ -13,7 +13,7 @@ import type { CaptureFraming } from './capture-clip';
13
13
  import type { ColorScheme } from './color-scheme';
14
14
  import type { ConsoleLine, NetworkEntry, PageError } from './rings';
15
15
  import type { SessionSnapshot } from './session-state';
16
- import type { ElementSnapshot, ScrapeCookie, ScrapeDownloadFile } from './target';
16
+ import type { AxNode, ElementSnapshot, ScrapeCookie, ScrapeDownloadFile } from './target';
17
17
 
18
18
  export interface WaitOptions {
19
19
  readonly state?: ActionabilityState | undefined;
@@ -21,6 +21,13 @@ export interface WaitOptions {
21
21
  readonly timeout?: number | undefined;
22
22
  }
23
23
 
24
+ /** How many matches `accessibility()` describes. A bound, because each match is a round trip. */
25
+ export interface AccessibilityOptions {
26
+ readonly max?: number | undefined;
27
+ }
28
+
29
+ export const DEFAULT_ACCESSIBILITY_MAX = 25;
30
+
24
31
  export interface ElementValue {
25
32
  readonly tag: string;
26
33
  readonly text: string;
@@ -49,6 +56,28 @@ export interface ScrapeFrame {
49
56
  /** Clears first, then types — the spelling a login form wants. */
50
57
  fill(selector: string, text: string | Secret, options?: WaitOptions): Promise<void>;
51
58
  select(selector: string, values: readonly string[], options?: WaitOptions): Promise<void>;
59
+ /**
60
+ * Waits for the element to be actionable, then moves focus to it — the setup for a `press()`,
61
+ * and the half of keyboard navigation a click cannot stand in for.
62
+ */
63
+ focus(selector: string, options?: WaitOptions): Promise<void>;
64
+ /**
65
+ * A key chord on whatever holds focus: `'Meta+K'`, `'Escape'`, `'Shift+Tab'`, `'Enter'`.
66
+ * Modifiers are `Meta`, `Control`, `Alt`, `Shift`, in the browser's own spelling — `'Ctrl+K'`
67
+ * is `X_SCRAPE_KEY_INVALID` on every driver, offline included, because the parse is the one
68
+ * thing an offline driver can be wrong about. The browser has ONE keyboard, so a chord pressed
69
+ * through a frame handle reaches whichever element that frame's `focus()` put focus on.
70
+ */
71
+ press(chord: string): Promise<void>;
72
+ /**
73
+ * What a screen reader is told about each match — the browser's computed role and name, after
74
+ * ARIA and label association, which `query()` cannot answer from attributes. At most
75
+ * `options.max` (default `DEFAULT_ACCESSIBILITY_MAX`) nodes, in document order. Refused with
76
+ * `X_NOT_IMPLEMENTED` on a driver with no accessibility engine — an offline driver, or a frame
77
+ * of the real one — never answered from the markup: a `<div onclick>` computing no role IS the
78
+ * finding, and a fake reading `role=` off the tag would hide it.
79
+ */
80
+ accessibility(selector: string, options?: AccessibilityOptions): Promise<readonly AxNode[]>;
52
81
  /**
53
82
  * Every match, as SNAPSHOTS — `visible`, `enabled` and (on a driver with a layout engine) the
54
83
  * box and hit-target, which `values()` projects away.
@@ -125,6 +154,18 @@ export interface ScrapePage extends ScrapeFrame {
125
154
  * method, which is a fact about the build rather than about the driver.
126
155
  */
127
156
  colorScheme(scheme: ColorScheme): Promise<void>;
157
+ /**
158
+ * A script the browser runs in EVERY document this page navigates to, BEFORE the document's
159
+ * own scripts — the one moment that beats an inlined boot script. Call it before `goto()`: what
160
+ * it seeds (a `localStorage` key a boot reads, a flag a component checks) is then in place for
161
+ * the first script the page executes, where an `evaluate()` after navigation is one boot too
162
+ * late. Same string discipline as `evaluate()`: an expression, never a closure.
163
+ *
164
+ * ACCEPTED on every driver, for `colorScheme()`'s reason: the offline drivers run no scripts,
165
+ * so nothing there could be wrong about it. `X_NOT_IMPLEMENTED` is reserved for a LAUNCHER
166
+ * that lacks the method, which is a fact about the build rather than about the driver.
167
+ */
168
+ prepare(expression: string): Promise<void>;
128
169
  /**
129
170
  * The handoff, made explicit: what the HTTP leg will send, as a value an author can inspect and
130
171
  * a fixture can assert on. `http` uses it automatically — this is for seeing what carried over.
package/src/target.ts CHANGED
@@ -47,6 +47,24 @@ export interface ElementSnapshot {
47
47
  readonly hitTarget?: boolean | undefined;
48
48
  }
49
49
 
50
+ /**
51
+ * One node of the browser's accessibility tree, as of one observation — what a screen reader is
52
+ * told about an element, which is a different fact from what `ElementSnapshot` says about its
53
+ * markup. `role` and `name` are always answered, `''` when the browser computed nothing: absent is
54
+ * a real answer for a `<div>`, and a fabricated `generic` would hide the elements a reader cannot
55
+ * name. A VALUE, like `ElementSnapshot`: it cannot go stale behind the caller's back, only old.
56
+ */
57
+ export interface AxNode {
58
+ readonly role: string;
59
+ readonly name: string;
60
+ readonly description?: string | undefined;
61
+ readonly value?: string | undefined;
62
+ readonly focused?: boolean | undefined;
63
+ readonly disabled?: boolean | undefined;
64
+ /** Pruned from the tree a reader walks — `aria-hidden`, or a wrapper with nothing to say. */
65
+ readonly ignored: boolean;
66
+ }
67
+
50
68
  export interface ScrapeCookie {
51
69
  readonly name: string;
52
70
  readonly value: string;
@@ -133,6 +151,25 @@ export interface ScrapeTarget {
133
151
  select(selector: string, values: readonly string[]): Promise<void>;
134
152
  /** The expression runs in the page. The result is `unknown` and is parsed by the caller. */
135
153
  evaluate(expression: string): Promise<unknown>;
154
+ /**
155
+ * A key chord — `'Meta+K'`, `'Escape'`, `'Shift+Tab'` — pressed on whatever holds focus. The
156
+ * PAGE's keyboard, on a frame target too: a browser has one keyboard, and the focused element
157
+ * is what decides which document hears it. REQUIRED here where `CdpPageLike.keyboard` is
158
+ * optional, for `setOfflineMode`'s reason: the asymmetry is the enforcement. A driver with no
159
+ * keyboard still PARSES the chord (`key-chord.ts`) and then resolves — the refusal an offline
160
+ * driver can give is the one it does give.
161
+ */
162
+ press(chord: string): Promise<void>;
163
+ /** Moves focus to the first match. Refused when nothing matches. */
164
+ focus(selector: string): Promise<void>;
165
+ /**
166
+ * The accessibility node of every match, bounded by `max` — the browser's own computed role and
167
+ * name, which no HTML parse can reproduce. REQUIRED for `press`'s reason, and a driver with no
168
+ * accessibility engine answers `X_NOT_IMPLEMENTED`, never an invented role: a fake that read
169
+ * `role="button"` off the markup would pass a test against a `<div onclick>` a reader cannot
170
+ * reach, which is the exact defect this read exists to catch.
171
+ */
172
+ accessibility(selector: string, max: number): Promise<readonly AxNode[]>;
136
173
  /**
137
174
  * The browser goes offline, or comes back. REQUIRED on this port where it is optional on
138
175
  * `CdpPageLike`, and the asymmetry is the enforcement: a driver author gets a type error naming
@@ -164,6 +201,20 @@ export interface ScrapeTarget {
164
201
  * so a driver that dropped the preference fails a test rather than passing every one.
165
202
  */
166
203
  setColorScheme(scheme: ColorScheme): Promise<void>;
204
+ /**
205
+ * A script every document this target navigates to runs BEFORE its own — the browser's
206
+ * `evaluateOnNewDocument`. REQUIRED here where `CdpPageLike.evaluateOnNewDocument` is optional,
207
+ * for `setOfflineMode`'s reason: the asymmetry is the enforcement, and a launcher without the
208
+ * method is `X_NOT_IMPLEMENTED`.
209
+ *
210
+ * A DRIVER WITH NO JS ENGINE ACCEPTS IT, for `setColorScheme`'s reason and not
211
+ * `setOfflineMode`'s: the offline drivers execute nothing, so there is no document script for
212
+ * the expression to run ahead of and no assertion a resolved promise could let through — a
213
+ * seeded `localStorage` key is the INPUT to a boot script this driver never runs. Refusing
214
+ * would make `x shot` and every `ui.*` tool untestable on a machine with no Chrome, and the
215
+ * outcome it would protect does not exist here. The call is still checked for a closed target.
216
+ */
217
+ prepare(expression: string): Promise<void>;
167
218
  screenshot(options: CaptureOptions): Promise<Uint8Array>;
168
219
  pdf(options: CaptureOptions): Promise<Uint8Array>;
169
220
  cookies(): Promise<readonly ScrapeCookie[]>;