recordable 0.2.0 → 0.4.0

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.
Files changed (88) hide show
  1. package/README.md +49 -18
  2. package/dist/actions.d.ts +4 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +7 -5
  5. package/dist/actions.js.map +1 -1
  6. package/dist/audio/track.d.ts.map +1 -1
  7. package/dist/audio/track.js.map +1 -1
  8. package/dist/browser/cursor.d.ts +6 -0
  9. package/dist/browser/cursor.d.ts.map +1 -1
  10. package/dist/browser/cursor.js +24 -6
  11. package/dist/browser/cursor.js.map +1 -1
  12. package/dist/browser/dom.d.ts +33 -13
  13. package/dist/browser/dom.d.ts.map +1 -1
  14. package/dist/browser/dom.js +158 -56
  15. package/dist/browser/dom.js.map +1 -1
  16. package/dist/browser/page-zoom.d.ts +11 -0
  17. package/dist/browser/page-zoom.d.ts.map +1 -0
  18. package/dist/browser/page-zoom.js +37 -0
  19. package/dist/browser/page-zoom.js.map +1 -0
  20. package/dist/browser/play-button.d.ts.map +1 -1
  21. package/dist/browser/play-button.js.map +1 -1
  22. package/dist/browser/runtime.d.ts +21 -1
  23. package/dist/browser/runtime.d.ts.map +1 -1
  24. package/dist/browser/runtime.js +91 -4
  25. package/dist/browser/runtime.js.map +1 -1
  26. package/dist/browser/targets.d.ts +17 -0
  27. package/dist/browser/targets.d.ts.map +1 -0
  28. package/dist/browser/targets.js +42 -0
  29. package/dist/browser/targets.js.map +1 -0
  30. package/dist/compose/mix.d.ts.map +1 -1
  31. package/dist/compose/mix.js +1 -1
  32. package/dist/compose/mix.js.map +1 -1
  33. package/dist/compose/recordable.d.ts +13 -7
  34. package/dist/compose/recordable.d.ts.map +1 -1
  35. package/dist/compose/recordable.js +28 -13
  36. package/dist/compose/recordable.js.map +1 -1
  37. package/dist/compose/session.d.ts +16 -1
  38. package/dist/compose/session.d.ts.map +1 -1
  39. package/dist/compose/session.js +76 -18
  40. package/dist/compose/session.js.map +1 -1
  41. package/dist/config.d.ts +9 -0
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/config.js +10 -0
  44. package/dist/config.js.map +1 -1
  45. package/dist/errors.d.ts +1 -1
  46. package/dist/errors.d.ts.map +1 -1
  47. package/dist/errors.js.map +1 -1
  48. package/dist/ffmpeg.d.ts +3 -0
  49. package/dist/ffmpeg.d.ts.map +1 -1
  50. package/dist/ffmpeg.js +14 -1
  51. package/dist/ffmpeg.js.map +1 -1
  52. package/dist/formats/markdown/method.d.ts.map +1 -1
  53. package/dist/formats/markdown/method.js +4 -3
  54. package/dist/formats/markdown/method.js.map +1 -1
  55. package/dist/formats/markdown/parse.d.ts.map +1 -1
  56. package/dist/formats/markdown/parse.js +11 -1
  57. package/dist/formats/markdown/parse.js.map +1 -1
  58. package/dist/logger.d.ts.map +1 -1
  59. package/dist/logger.js +3 -1
  60. package/dist/logger.js.map +1 -1
  61. package/dist/timing.d.ts +2 -0
  62. package/dist/timing.d.ts.map +1 -1
  63. package/dist/timing.js +10 -4
  64. package/dist/timing.js.map +1 -1
  65. package/dist/validate.d.ts.map +1 -1
  66. package/dist/validate.js +11 -10
  67. package/dist/validate.js.map +1 -1
  68. package/dist/video/recorder.d.ts +4 -1
  69. package/dist/video/recorder.d.ts.map +1 -1
  70. package/dist/video/recorder.js +20 -16
  71. package/dist/video/recorder.js.map +1 -1
  72. package/dist/video/stitch.js +3 -17
  73. package/dist/video/stitch.js.map +1 -1
  74. package/dist/voiceover/compile.d.ts.map +1 -1
  75. package/dist/voiceover/compile.js +42 -24
  76. package/dist/voiceover/compile.js.map +1 -1
  77. package/dist/voiceover/elevenlabs.d.ts.map +1 -1
  78. package/dist/voiceover/elevenlabs.js +41 -11
  79. package/dist/voiceover/elevenlabs.js.map +1 -1
  80. package/dist/voiceover/mock.d.ts.map +1 -1
  81. package/dist/voiceover/mock.js +38 -15
  82. package/dist/voiceover/mock.js.map +1 -1
  83. package/package.json +3 -1
  84. package/recordable.schema.json +12 -0
  85. package/dist/targets.d.ts +0 -6
  86. package/dist/targets.d.ts.map +0 -1
  87. package/dist/targets.js +0 -13
  88. package/dist/targets.js.map +0 -1
@@ -1,11 +1,34 @@
1
- import { isPositionValue, resolveTarget } from "../targets.js";
2
- /** Resolve a target and wait for the element to exist in the DOM, then return its handle. */
1
+ import { isPositionValue, resolveTarget } from "./targets.js";
2
+ import { RecordableError } from "../errors.js";
3
+ /** Jitter spread as a fraction of an element's dimension (±20% of each side). */
4
+ const JITTER_FRACTION = 0.4;
5
+ /** Frame interval in ms (≈ one 60fps frame). */
6
+ const FRAME_MS = 16;
7
+ /** Default viewport height (px) when the page has no viewport set. */
8
+ const DEFAULT_VIEWPORT_HEIGHT = 900;
9
+ /** Resolve a target and wait for the element to be *visible* in any frame, then
10
+ * return its handle.
11
+ *
12
+ * Two reasons this is more than a bare `page.locator(...).waitHandle()`:
13
+ * - Visibility (not mere existence): callers immediately read `boundingBox()`
14
+ * to click/scroll, but Puppeteer's default locator resolves the instant the
15
+ * node enters the DOM (`waitForSelector(..., {visible:false})`) — so an
16
+ * element inserted-but-not-yet-laid-out yields a null box. `setVisibility`
17
+ * makes it wait for a real layout box.
18
+ * - Frames: modal dialogs (e.g. APEX `apex.navigation.dialog`) render their
19
+ * content in an `<iframe>`. The top frame can hold a hidden placeholder with
20
+ * the same id, so we race every frame and take the first *visible* match.
21
+ * An iframe element's `boundingBox()` is reported in main-frame coordinates,
22
+ * so the coordinate-based click still lands correctly. */
3
23
  export async function getHandle(page, target) {
24
+ const selector = resolveTarget(target);
4
25
  try {
5
- return await page.locator(resolveTarget(target)).waitHandle();
26
+ return await Promise.any(page
27
+ .frames()
28
+ .map((f) => f.locator(selector).setVisibility("visible").waitHandle()));
6
29
  }
7
30
  catch {
8
- throw new Error(`Could not find target: "${target}"`);
31
+ throw new RecordableError("TARGET_NOT_FOUND", `Could not find target: "${target}"`);
9
32
  }
10
33
  }
11
34
  /** Centre coords of a target element, jittered up to 20% of each dimension. */
@@ -13,8 +36,8 @@ export async function getElementCenter(page, target) {
13
36
  const handle = await getHandle(page, target);
14
37
  const box = await handle.boundingBox();
15
38
  if (!box)
16
- throw new Error(`No bounding box for "${target}"`);
17
- const offset = (range) => (Math.random() - 0.5) * range * 0.4;
39
+ throw new RecordableError("TARGET_NOT_FOUND", `No bounding box for "${target}"`);
40
+ const offset = (range) => (Math.random() - 0.5) * range * JITTER_FRACTION;
18
41
  return {
19
42
  x: box.x + box.width / 2 + offset(box.width),
20
43
  y: box.y + box.height / 2 + offset(box.height),
@@ -54,81 +77,160 @@ export async function originToCoords(page, origin) {
54
77
  return { x: (vw * px) / 100, y: (vh * py) / 100 };
55
78
  }, origin);
56
79
  }
57
- /** Animate the page's scroll position to `targetY` over `duration` ms with an ease curve. */
58
- export async function smoothScroll(page, targetY, duration) {
59
- await page.evaluate(({ targetY, duration }) => {
80
+ /**
81
+ * Animate a scroller's vertical position to `targetTop` over `duration` ms with an
82
+ * ease curve. `container` null scrolls the window; a handle scrolls that element's
83
+ * `scrollTop`. The target is clamped to the scroller's range.
84
+ */
85
+ export async function smoothScroll(page, targetTop, duration, container = null) {
86
+ await page.evaluate(
87
+ // frameMs is passed in: a module-level const isn't visible inside this
88
+ // browser-context closure.
89
+ (el, { targetTop, duration, frameMs }) => {
60
90
  return new Promise((resolve) => {
61
- const startY = window.scrollY;
62
- const dist = targetY - startY;
63
- const frames = Math.ceil(duration / 16);
91
+ const max = el
92
+ ? el.scrollHeight - el.clientHeight
93
+ : document.documentElement.scrollHeight - window.innerHeight;
94
+ const end = Math.max(0, Math.min(targetTop, max));
95
+ const startY = el ? el.scrollTop : window.scrollY;
96
+ const dist = end - startY;
97
+ const frames = Math.ceil(duration / frameMs);
64
98
  let i = 0;
65
99
  const id = setInterval(() => {
66
100
  i++;
67
101
  const p = Math.min(i / frames, 1);
68
102
  const e = p < 0.5 ? 4 * p * p * p : (p - 1) * (2 * p - 2) * (2 * p - 2) + 1;
69
- window.scrollTo(0, startY + dist * e);
103
+ const y = startY + dist * e;
104
+ if (el)
105
+ el.scrollTop = y;
106
+ else
107
+ window.scrollTo(0, y);
70
108
  if (p >= 1) {
71
109
  clearInterval(id);
72
110
  resolve();
73
111
  }
74
- }, 16);
112
+ }, frameMs);
75
113
  });
76
- }, { targetY, duration });
114
+ }, container, { targetTop, duration, frameMs: FRAME_MS });
77
115
  }
78
116
  /**
79
- * Smooth-scroll to an element or position:
80
- * - `"top"` / `"bottom"` page extremes
81
- * - number absolute Y pixel position
82
- * - CSS selector or `text:` prefix element centred in the viewport
117
+ * Smooth-scroll to an element or position. Without `container` the window scrolls;
118
+ * with one, `target` is resolved against that scroll container instead:
119
+ * - `"top"` / `"bottom"` scroller extremes
120
+ * - numberabsolute scrollTop (px)
121
+ * - CSS selector or `text:` prefix → element centred within the scroller
83
122
  */
84
- export async function smoothScrollToTarget(page, target, duration) {
123
+ export async function smoothScrollToTarget(page, target, duration, container) {
124
+ const scroller = container ? await getHandle(page, container) : null;
85
125
  if (typeof target === "number")
86
- return smoothScroll(page, target, duration);
126
+ return smoothScroll(page, target, duration, scroller);
87
127
  if (target === "top")
88
- return smoothScroll(page, 0, duration);
128
+ return smoothScroll(page, 0, duration, scroller);
89
129
  if (target === "bottom") {
90
- const bottom = await page.evaluate(() => document.body.scrollHeight);
91
- return smoothScroll(page, bottom, duration);
130
+ const bottom = await page.evaluate((el) => (el ? el.scrollHeight : document.body.scrollHeight), scroller);
131
+ return smoothScroll(page, bottom, duration, scroller);
92
132
  }
93
133
  const handle = await getHandle(page, target);
94
- const y = await page.evaluate((el, vh) => {
134
+ const top = await page.evaluate((el, scrollEl, vh) => {
95
135
  const rect = el.getBoundingClientRect();
136
+ if (scrollEl) {
137
+ // Centre the child within the container's visible area.
138
+ const box = scrollEl.getBoundingClientRect();
139
+ return (scrollEl.scrollTop +
140
+ (rect.top - box.top) +
141
+ rect.height / 2 -
142
+ scrollEl.clientHeight / 2);
143
+ }
96
144
  return window.scrollY + rect.top + rect.height / 2 - vh / 2;
97
- }, handle, page.viewport()?.height ?? 900);
98
- return smoothScroll(page, y, duration);
145
+ }, handle, scroller, page.viewport()?.height ?? DEFAULT_VIEWPORT_HEIGHT);
146
+ return smoothScroll(page, top, duration, scroller);
147
+ }
148
+ /** The scrollTop that brings the element comfortably into the scroller's view, or
149
+ * null when it's already comfortably visible. Pure geometry, shared by the window
150
+ * and container passes so both reveal an element the same way. */
151
+ function comfortTarget(m, margin) {
152
+ const { relTop, height, vh, scrollTop } = m;
153
+ const relBottom = relTop + height;
154
+ const comfort = margin * 2;
155
+ if (relTop >= comfort && relBottom <= vh - comfort)
156
+ return null;
157
+ // Tall element: top-align with margin.
158
+ if (height > vh - margin * 2)
159
+ return scrollTop + relTop - margin;
160
+ // Below the bottom comfort zone: scroll just enough to show it fully (centring
161
+ // would often overshoot the scroller's max and leave it pinned to the edge).
162
+ if (relBottom > vh - margin)
163
+ return scrollTop + relBottom - (vh - margin);
164
+ // Above the top comfort zone: scroll to show the top.
165
+ if (relTop < margin)
166
+ return scrollTop + relTop - margin;
167
+ // Within the comfort band but not comfortable: centre it.
168
+ return scrollTop + relTop + height / 2 - vh / 2;
169
+ }
170
+ /** Read the target's position within `container` (an element scroller) or, when
171
+ * null, within the window. */
172
+ function readMetrics(page, handle, container) {
173
+ return page.evaluate((el, c) => {
174
+ const r = el.getBoundingClientRect();
175
+ if (c) {
176
+ const b = c.getBoundingClientRect();
177
+ return {
178
+ relTop: r.top - b.top,
179
+ height: r.height,
180
+ vh: c.clientHeight,
181
+ scrollTop: c.scrollTop,
182
+ };
183
+ }
184
+ return {
185
+ relTop: r.top,
186
+ height: r.height,
187
+ vh: window.innerHeight,
188
+ scrollTop: window.scrollY,
189
+ };
190
+ }, handle, container);
191
+ }
192
+ /** The nearest ancestor that actually scrolls vertically (overflow auto/scroll +
193
+ * overflowing content), or null if none short of the document — in which case the
194
+ * window is the scroller. */
195
+ async function nearestScrollableAncestor(handle) {
196
+ const h = await handle.evaluateHandle((el) => {
197
+ let p = el.parentElement;
198
+ while (p && p !== document.body && p !== document.documentElement) {
199
+ const oy = getComputedStyle(p).overflowY;
200
+ if ((oy === "auto" || oy === "scroll" || oy === "overlay") &&
201
+ p.scrollHeight > p.clientHeight)
202
+ return p;
203
+ p = p.parentElement;
204
+ }
205
+ return null;
206
+ });
207
+ const el = h.asElement();
208
+ if (!el)
209
+ await h.dispose();
210
+ return el;
99
211
  }
100
212
  /**
101
- * Scroll `target` into view if it lies outside the visible viewport (keeping
102
- * `margin` px clear on each side). No-op when the element is already fully
103
- * visible. `speed` (px/s) sets the scroll duration.
213
+ * Scroll `target` into view if it lies outside the visible area (keeping `margin`
214
+ * px clear on each side). No-op when already comfortably visible. `speed` (px/s)
215
+ * sets the scroll duration. Scrolls the target's nearest scrollable container
216
+ * first (so it's revealed inside a modal / sidebar / pane), then the window so the
217
+ * container itself is on screen.
104
218
  */
105
219
  export async function scrollIntoView(page, target, margin, speed) {
106
220
  const handle = await getHandle(page, target);
107
- const scrollY = await page.evaluate((el, margin) => {
108
- const rect = el.getBoundingClientRect();
109
- const vh = window.innerHeight;
110
- const comfort = margin * 2;
111
- if (rect.top >= comfort && rect.bottom <= vh - comfort)
112
- return null;
113
- // Tall element: top-align with margin
114
- if (rect.height > vh - margin * 2)
115
- return window.scrollY + rect.top - margin;
116
- // Element extends below the bottom comfort zone: scroll just enough to
117
- // show it fully, rather than trying to centre it (which often overshoots
118
- // the page's max scroll and leaves the element at the viewport edge).
119
- if (rect.bottom > vh - margin)
120
- return window.scrollY + rect.bottom - (vh - margin);
121
- // Element extends above the top comfort zone: scroll to show top
122
- if (rect.top < margin)
123
- return window.scrollY + rect.top - margin;
124
- // In view but within the comfort band: centre it
125
- return window.scrollY + rect.top + rect.height / 2 - vh / 2;
126
- }, handle, margin);
127
- if (scrollY === null)
128
- return;
129
- const currentY = await page.evaluate(() => window.scrollY);
130
- const dist = Math.abs(scrollY - currentY);
131
- const duration = Math.max(200, (dist / speed) * 1000);
132
- await smoothScroll(page, scrollY, duration);
221
+ const container = await nearestScrollableAncestor(handle);
222
+ const reveal = async (scroller) => {
223
+ const metrics = await readMetrics(page, handle, scroller);
224
+ const top = comfortTarget(metrics, margin);
225
+ if (top === null)
226
+ return;
227
+ const dist = Math.abs(top - metrics.scrollTop);
228
+ const duration = Math.max(200, (dist / speed) * 1000);
229
+ await smoothScroll(page, top, duration, scroller);
230
+ };
231
+ if (container)
232
+ await reveal(container);
233
+ await reveal(null);
234
+ await container?.dispose();
133
235
  }
134
236
  //# sourceMappingURL=dom.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/browser/dom.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/browser/dom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ZoomExtension {
2
+ /** Launch args that load the extension. */
3
+ args: string[];
4
+ /** Remove the generated temp directory. */
5
+ cleanup: () => void;
6
+ }
7
+ /** Generate the bundled page-zoom extension for `zoom` and return its launch args
8
+ * plus a cleanup. Caller adds `args` to `puppeteer.launch` and calls `cleanup`
9
+ * once the browser has closed. */
10
+ export declare function createZoomExtension(zoom: number): ZoomExtension;
11
+ //# sourceMappingURL=page-zoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-zoom.d.ts","sourceRoot":"","sources":["../../src/browser/page-zoom.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAiBD;;mCAEmC;AACnC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAkB/D"}
@@ -0,0 +1,37 @@
1
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+ // Registers its listeners synchronously at top level (MV3 requirement) and
5
+ // re-applies on create + every load — page zoom is per-origin persistent, so this
6
+ // covers same-origin navigations and any `followNewTab` tabs.
7
+ const background = (zoom) => `
8
+ const ZOOM = ${zoom};
9
+ const apply = (id) => chrome.tabs.setZoom(id, ZOOM).catch(() => {});
10
+ chrome.tabs.onCreated.addListener((t) => apply(t.id));
11
+ chrome.tabs.onUpdated.addListener((id, info) => {
12
+ if (info.status === "loading" || info.status === "complete") apply(id);
13
+ });
14
+ chrome.runtime.onInstalled.addListener(() =>
15
+ chrome.tabs.query({}, (tabs) => tabs.forEach((t) => apply(t.id))),
16
+ );
17
+ `;
18
+ /** Generate the bundled page-zoom extension for `zoom` and return its launch args
19
+ * plus a cleanup. Caller adds `args` to `puppeteer.launch` and calls `cleanup`
20
+ * once the browser has closed. */
21
+ export function createZoomExtension(zoom) {
22
+ const dir = mkdtempSync(join(tmpdir(), "recordable-zoom-"));
23
+ writeFileSync(join(dir, "manifest.json"), JSON.stringify({
24
+ manifest_version: 3,
25
+ name: "recordable-page-zoom",
26
+ version: "1.0",
27
+ permissions: ["tabs"],
28
+ host_permissions: ["<all_urls>"],
29
+ background: { service_worker: "bg.js" },
30
+ }));
31
+ writeFileSync(join(dir, "bg.js"), background(zoom));
32
+ return {
33
+ args: [`--disable-extensions-except=${dir}`, `--load-extension=${dir}`],
34
+ cleanup: () => rmSync(dir, { recursive: true, force: true }),
35
+ };
36
+ }
37
+ //# sourceMappingURL=page-zoom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-zoom.js","sourceRoot":"","sources":["../../src/browser/page-zoom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAwBjC,2EAA2E;AAC3E,kFAAkF;AAClF,8DAA8D;AAC9D,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;eACtB,IAAI;;;;;;;;;CASlB,CAAC;AAEF;;mCAEmC;AACnC,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC5D,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAC1B,IAAI,CAAC,SAAS,CAAC;QACb,gBAAgB,EAAE,CAAC;QACnB,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,CAAC,MAAM,CAAC;QACrB,gBAAgB,EAAE,CAAC,YAAY,CAAC;QAChC,UAAU,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE;KACxC,CAAC,CACH,CAAC;IACF,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,OAAO;QACL,IAAI,EAAE,CAAC,+BAA+B,GAAG,EAAE,EAAE,oBAAoB,GAAG,EAAE,CAAC;QACvE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"play-button.d.ts","sourceRoot":"","sources":["../../src/browser/play-button.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,wBAAwB,CAAC;AACpD,eAAO,MAAM,YAAY,uBAAuB,CAAC;AA0EjD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,MAAM,CAGR"}
1
+ {"version":3,"file":"play-button.d.ts","sourceRoot":"","sources":["../../src/browser/play-button.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,wBAAwB,CAAC;AACpD,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAsEjD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,MAAM,CAGR"}
@@ -1 +1 @@
1
- {"version":3,"file":"play-button.js","sourceRoot":"","sources":["../../src/browser/play-button.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC;AACpD,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,SAAS,gBAAgB,CACvB,OAAe,EACf,EAAU,EACV,OAAe;IAEf,wDAAwD;IACxD,IAAI,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO;IACrC,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAAE,OAAO;QACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG;YACnB,gBAAgB;YAChB,UAAU;YACV,2EAA2E;YAC3E,iEAAiE;YACjE,UAAU;YACV,4BAA4B;YAC5B,oBAAoB;YACpB,qBAAqB;YACrB,cAAc;YACd,oBAAoB;YACpB,UAAU;YACV,6BAA6B;YAC7B,gCAAgC;YAChC,YAAY;YACZ,qBAAqB;YACrB,uCAAuC;YACvC,yDAAyD;SAC1D,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG;YAClB,WAAW;YACX,gBAAgB;YAChB,qBAAqB;YACrB,oBAAoB;YACpB,wBAAwB;YACxB,YAAY;YACZ,aAAa;YACb,mBAAmB;YACnB,oBAAoB;YACpB,YAAY;YACZ,gBAAgB;SACjB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC;QACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC7C,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;QAC5B,KAAK,CAAC,KAAK,CAAC,OAAO;YACjB,gEAAgE,CAAC;QACnE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,KAAK;gBAAE,OAAO;YAClB,KAAK,GAAG,IAAI,CAAC;YACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,MAAM,EAAE,GAAI,MAAgD,CAAC,OAAO,CAAC,CAAC;YACtE,IAAI,OAAO,EAAE,KAAK,UAAU;gBAAE,EAAE,EAAE,CAAC;QACrC,CAAC,CAAC;QACF,sEAAsE;QACtE,iEAAiE;QACjE,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,IAAI,QAAQ,CAAC,IAAI;QAAE,KAAK,EAAE,CAAC;;QACtB,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,EAAU,EACV,OAAe;IAEf,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5E,OAAO,sCAAsC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,IAAI,SAAS,CAAC;AAC7F,CAAC"}
1
+ {"version":3,"file":"play-button.js","sourceRoot":"","sources":["../../src/browser/play-button.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC;AACpD,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAe,EAAE,EAAU,EAAE,OAAe;IACpE,wDAAwD;IACxD,IAAI,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO;IACrC,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAAE,OAAO;QACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG;YACnB,gBAAgB;YAChB,UAAU;YACV,2EAA2E;YAC3E,iEAAiE;YACjE,UAAU;YACV,4BAA4B;YAC5B,oBAAoB;YACpB,qBAAqB;YACrB,cAAc;YACd,oBAAoB;YACpB,UAAU;YACV,6BAA6B;YAC7B,gCAAgC;YAChC,YAAY;YACZ,qBAAqB;YACrB,uCAAuC;YACvC,yDAAyD;SAC1D,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG;YAClB,WAAW;YACX,gBAAgB;YAChB,qBAAqB;YACrB,oBAAoB;YACpB,wBAAwB;YACxB,YAAY;YACZ,aAAa;YACb,mBAAmB;YACnB,oBAAoB;YACpB,YAAY;YACZ,gBAAgB;SACjB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC;QACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC7C,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;QAC5B,KAAK,CAAC,KAAK,CAAC,OAAO;YACjB,gEAAgE,CAAC;QACnE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,KAAK;gBAAE,OAAO;YAClB,KAAK,GAAG,IAAI,CAAC;YACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,MAAM,EAAE,GAAI,MAAgD,CAAC,OAAO,CAAC,CAAC;YACtE,IAAI,OAAO,EAAE,KAAK,UAAU;gBAAE,EAAE,EAAE,CAAC;QACrC,CAAC,CAAC;QACF,sEAAsE;QACtE,iEAAiE;QACjE,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,IAAI,QAAQ,CAAC,IAAI;QAAE,KAAK,EAAE,CAAC;;QACtB,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,EAAU,EACV,OAAe;IAEf,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5E,OAAO,sCAAsC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,IAAI,SAAS,CAAC;AAC7F,CAAC"}
@@ -25,19 +25,34 @@ export declare class Runtime {
25
25
  restoreCursor(page: Page): Promise<void>;
26
26
  visit(page: Page, url: string, options?: GoToOptions): Promise<void>;
27
27
  waitFor(page: Page, target: string, options?: WaitForOptions): Promise<void>;
28
- click(page: Page, target: string, options?: ClickOptions): Promise<void>;
28
+ /** Click a target. Returns the new tab's `Page` when `followNewTab` is set and the
29
+ * click opened one — the session then switches recording to it. Otherwise void. */
30
+ click(page: Page, target: string, options?: ClickOptions): Promise<Page | void>;
31
+ /**
32
+ * Click a link that opens a new tab and resolve to the new `Page` (or warn and
33
+ * return void if none appears). The popup listener is armed *before* the click so a
34
+ * fast open can't be missed. The new tab is *not* waited on here — the session seals
35
+ * the current segment first, then waits for the load off-camera so it's trimmed.
36
+ */
37
+ private _clickNewTab;
38
+ /** Resolve to the next popup `page.once("popup")` opens, or null after `timeout`.
39
+ * A late timer after the popup resolves is a harmless no-op; unref it so it can't
40
+ * hold the process open. */
41
+ private _waitForPopup;
29
42
  hover(page: Page, target: string): Promise<void>;
30
43
  type(page: Page, target: string, text: string, options?: {
31
44
  duration?: number;
32
45
  }): Promise<void>;
33
46
  clear(page: Page, target: string): Promise<void>;
34
47
  select(page: Page, target: string, value: string): Promise<void>;
48
+ private _optionValue;
35
49
  key(page: Page, key: string): Promise<void>;
36
50
  mouse(page: Page, target: string | {
37
51
  x: number;
38
52
  y: number;
39
53
  }): Promise<void>;
40
54
  scroll(page: Page, target: string | number, options?: {
55
+ container?: string;
41
56
  duration?: number;
42
57
  }): Promise<void>;
43
58
  zoomTo(page: Page, level: number, options?: {
@@ -64,6 +79,11 @@ export declare class Runtime {
64
79
  private _moveTo;
65
80
  /** Scroll a target into view using the configured margin/speed. */
66
81
  private _scrollIntoView;
82
+ /** Fragile-selector lint: warn (once) when a target resolves to more than one
83
+ * element, then act on the first. Best-effort — it does not wait for the
84
+ * element, so it stays silent if the matches haven't rendered yet, and never
85
+ * throws (a genuine miss surfaces later at getHandle). */
86
+ private checkAmbiguous;
67
87
  /**
68
88
  * Block until the user resumes — by clicking the in-page ▶ Play button, or by
69
89
  * pressing Enter in the *terminal*. The in-page button is click-only so the live
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/browser/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/browser/runtime.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { sleep, truncate } from "../utils.js";
2
- import { resolveTarget } from "../targets.js";
3
- import { getElementCenter, originToCoords, scrollIntoView, smoothScrollToTarget, } from "./dom.js";
2
+ import { resolveTarget, parseOptionSpec } from "./targets.js";
3
+ import { RecordableError } from "../errors.js";
4
+ import { getElementCenter, getHandle, originToCoords, scrollIntoView, smoothScrollToTarget, } from "./dom.js";
4
5
  import { Cursor } from "./cursor.js";
5
6
  import { jitter, typingDuration, typingGaps, PRE_CLICK_MS } from "../timing.js";
6
7
  import { playButtonScript, PLAY_BINDING, PLAY_BUTTON_ID, } from "./play-button.js";
@@ -64,6 +65,7 @@ export class Runtime {
64
65
  async waitFor(page, target, options = {}) {
65
66
  const { state = "visible", timeout = this.getCfg().visitTimeout } = options;
66
67
  this.log("WaitFor", `${target} (${state})`);
68
+ await this.checkAmbiguous(page, target);
67
69
  await page.waitForSelector(resolveTarget(target), {
68
70
  timeout,
69
71
  visible: state === "visible",
@@ -72,12 +74,50 @@ export class Runtime {
72
74
  await this.injectCursor(page);
73
75
  }
74
76
  // ─── Interactions ──────────────────────────────────────────────────────────
77
+ /** Click a target. Returns the new tab's `Page` when `followNewTab` is set and the
78
+ * click opened one — the session then switches recording to it. Otherwise void. */
75
79
  async click(page, target, options = {}) {
76
80
  this.log("Click", target);
81
+ await this.checkAmbiguous(page, target);
82
+ if (options.followNewTab)
83
+ return this._clickNewTab(page, target, options);
77
84
  await this._click(page, target, options);
78
85
  }
86
+ /**
87
+ * Click a link that opens a new tab and resolve to the new `Page` (or warn and
88
+ * return void if none appears). The popup listener is armed *before* the click so a
89
+ * fast open can't be missed. The new tab is *not* waited on here — the session seals
90
+ * the current segment first, then waits for the load off-camera so it's trimmed.
91
+ */
92
+ async _clickNewTab(page, target, options) {
93
+ const timeout = options.timeout ?? this.getCfg().visitTimeout;
94
+ const popup = this._waitForPopup(page, timeout);
95
+ // The nav happens in the new tab, so don't wait for a same-tab navigation here.
96
+ await this._click(page, target, { ...options, waitForNav: false });
97
+ const newPage = await popup;
98
+ if (!newPage) {
99
+ this.log.warn(`click: no new tab opened for "${target}" — staying on the current tab`);
100
+ return;
101
+ }
102
+ return newPage;
103
+ }
104
+ /** Resolve to the next popup `page.once("popup")` opens, or null after `timeout`.
105
+ * A late timer after the popup resolves is a harmless no-op; unref it so it can't
106
+ * hold the process open. */
107
+ _waitForPopup(page, timeout) {
108
+ return new Promise((resolve) => {
109
+ const onPopup = (p) => resolve(p ?? null);
110
+ page.once("popup", onPopup);
111
+ const timer = setTimeout(() => {
112
+ page.off("popup", onPopup);
113
+ resolve(null);
114
+ }, timeout);
115
+ timer.unref?.();
116
+ });
117
+ }
79
118
  async hover(page, target) {
80
119
  this.log("Hover", target);
120
+ await this.checkAmbiguous(page, target);
81
121
  if (this.getCfg().autoScroll)
82
122
  await this._scrollIntoView(page, target);
83
123
  const { x, y } = await getElementCenter(page, target);
@@ -85,6 +125,7 @@ export class Runtime {
85
125
  }
86
126
  async type(page, target, text, options = {}) {
87
127
  this.log("Type", `${target} "${truncate(text)}"`);
128
+ await this.checkAmbiguous(page, target);
88
129
  await this._click(page, target);
89
130
  const total = options.duration ?? typingDuration(text, this.getCfg().typingSpeed);
90
131
  const gaps = typingGaps(text, this.getCfg().typingSpeed, total);
@@ -99,6 +140,7 @@ export class Runtime {
99
140
  }
100
141
  async clear(page, target) {
101
142
  this.log("Clear", target);
143
+ await this.checkAmbiguous(page, target);
102
144
  await this._click(page, target);
103
145
  const mod = process.platform === "darwin" ? "Meta" : "Control";
104
146
  await page.keyboard.down(mod);
@@ -108,6 +150,7 @@ export class Runtime {
108
150
  }
109
151
  async select(page, target, value) {
110
152
  this.log("Select", `${target} ${value}`);
153
+ await this.checkAmbiguous(page, target);
111
154
  if (this.getCfg().autoScroll)
112
155
  await this._scrollIntoView(page, target);
113
156
  const { x, y } = await getElementCenter(page, target);
@@ -116,13 +159,38 @@ export class Runtime {
116
159
  await sleep(jitter(PRE_CLICK_MS));
117
160
  await this.cursor.clickEffect(page);
118
161
  }
119
- await page.select(target, value);
162
+ // Resolve the handle through getHandle (frame-aware) and act on it directly —
163
+ // page.select() / page.$eval() only see the main frame, so a <select> inside
164
+ // an iframe (e.g. a dialog) would miss it or hit a same-id placeholder.
165
+ const el = await getHandle(page, target);
166
+ await el.select(await this._optionValue(el, target, value));
167
+ }
168
+ // Map a select value-spec to the concrete option `value` Puppeteer expects.
169
+ // Literal values pass through; `:option-index/-label(...)` read the live
170
+ // `<select>` via the element's own frame.
171
+ async _optionValue(el, target, value) {
172
+ const spec = parseOptionSpec(value);
173
+ if (!spec)
174
+ return value;
175
+ const resolved = await el.evaluate((node, spec) => {
176
+ const opts = [...node.options];
177
+ const hit = "index" in spec
178
+ ? opts[spec.index - 1]
179
+ : opts.find((o) => o.textContent?.trim() === spec.label);
180
+ return hit?.value;
181
+ }, spec);
182
+ if (resolved == null) {
183
+ throw new RecordableError("CONFIG_INVALID", `select("${target}", "${value}"): no matching <option>.`);
184
+ }
185
+ return resolved;
120
186
  }
121
187
  async key(page, key) {
122
188
  this.log("Key", key);
123
189
  await page.keyboard.press(key);
124
190
  }
125
191
  async mouse(page, target) {
192
+ if (typeof target === "string")
193
+ await this.checkAmbiguous(page, target);
126
194
  const { x, y } = typeof target === "string"
127
195
  ? await getElementCenter(page, target)
128
196
  : target;
@@ -132,7 +200,11 @@ export class Runtime {
132
200
  // ─── Scrolling ─────────────────────────────────────────────────────────────
133
201
  async scroll(page, target, options = {}) {
134
202
  this.log("Scroll", String(target));
135
- await smoothScrollToTarget(page, target, options.duration ?? this.getCfg().scrollDuration);
203
+ if (typeof target === "string" && target !== "top" && target !== "bottom")
204
+ await this.checkAmbiguous(page, target);
205
+ if (options.container)
206
+ await this.checkAmbiguous(page, options.container);
207
+ await smoothScrollToTarget(page, target, options.duration ?? this.getCfg().scrollDuration, options.container);
136
208
  }
137
209
  // ─── Zoom ──────────────────────────────────────────────────────────────────
138
210
  async zoomTo(page, level, options = {}) {
@@ -217,6 +289,21 @@ export class Runtime {
217
289
  const cfg = this.getCfg();
218
290
  return scrollIntoView(page, target, cfg.scrollMargin, cfg.scrollSpeed);
219
291
  }
292
+ /** Fragile-selector lint: warn (once) when a target resolves to more than one
293
+ * element, then act on the first. Best-effort — it does not wait for the
294
+ * element, so it stays silent if the matches haven't rendered yet, and never
295
+ * throws (a genuine miss surfaces later at getHandle). */
296
+ async checkAmbiguous(page, target) {
297
+ try {
298
+ const matches = await page.$$(resolveTarget(target));
299
+ if (matches.length > 1)
300
+ this.log.warn(`"${target}" matched ${matches.length} elements; using the first`);
301
+ await Promise.all(matches.map((m) => m.dispose()));
302
+ }
303
+ catch {
304
+ // ignore: resolution failures are reported where the element is fetched
305
+ }
306
+ }
220
307
  // ─── Resume gate (▶ Play button) ─────────────────────────────────────────────
221
308
  /**
222
309
  * Block until the user resumes — by clicking the in-page ▶ Play button, or by