@xbrowser/cli 1.8.7 → 1.9.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.
@@ -2,7 +2,7 @@ import {
2
2
  extractAndSave,
3
3
  extractRecording,
4
4
  printExtractSummary
5
- } from "./chunk-MJFYLKGL.js";
5
+ } from "./chunk-X46HDAOT.js";
6
6
  import "./chunk-KFQGP6VL.js";
7
7
  export {
8
8
  extractAndSave,
@@ -4,9 +4,33 @@ import "./chunk-KFQGP6VL.js";
4
4
  import * as fs from "fs";
5
5
  import * as yaml from "yaml";
6
6
  function extractRecording(filePath) {
7
- const content = fs.readFileSync(filePath, "utf-8");
8
- const recording = yaml.parse(content);
9
- const events = recording.actions || recording.events || [];
7
+ let recording;
8
+ try {
9
+ const content = fs.readFileSync(filePath, "utf-8");
10
+ recording = yaml.parse(content);
11
+ } catch (e) {
12
+ throw new Error(`Failed to read "${filePath}": ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`);
13
+ }
14
+ if (recording === null || typeof recording !== "object" || Array.isArray(recording)) {
15
+ throw new Error(`"${filePath}" does not contain a valid recording (expected a YAML object with events or actions).`);
16
+ }
17
+ let rawEvents = recording.events ?? [];
18
+ const rawActions = recording.actions;
19
+ if (Array.isArray(rawActions) && rawEvents.length === 0) {
20
+ rawEvents = rawActions.map((a) => {
21
+ const action = a;
22
+ const element = action.element ?? {};
23
+ return {
24
+ type: action.type,
25
+ selector: element.selector ?? action.selector,
26
+ tagName: element.tag ?? action.tagName,
27
+ data: { ...action.data, value: action.value, key: action.key },
28
+ timestamp: action.timestamp,
29
+ pageState: action.pageState
30
+ };
31
+ });
32
+ }
33
+ const events = rawEvents;
10
34
  const keyEvents = [];
11
35
  const eventTypes = {};
12
36
  for (const event of events) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  filterRecording,
3
3
  parseExcludeTypes
4
- } from "./chunk-GJAV3QGG.js";
4
+ } from "./chunk-ANVL2ID2.js";
5
5
  import "./chunk-KFQGP6VL.js";
6
6
  export {
7
7
  filterRecording,
@@ -24,9 +24,33 @@ var DEFAULT_EXCLUDE_TYPES = [
24
24
  "mousedown"
25
25
  ];
26
26
  function filterRecording(inputPath, outputPath, excludeTypes) {
27
- const content = fs.readFileSync(inputPath, "utf-8");
28
- const recording = yaml.parse(content);
29
- const events = recording.actions || recording.events || [];
27
+ let recording;
28
+ try {
29
+ const content = fs.readFileSync(inputPath, "utf-8");
30
+ recording = yaml.parse(content);
31
+ } catch (e) {
32
+ throw new Error(`Failed to read "${inputPath}": ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`);
33
+ }
34
+ if (recording === null || typeof recording !== "object" || Array.isArray(recording)) {
35
+ throw new Error(`"${inputPath}" does not contain a valid recording (expected a YAML object with events or actions).`);
36
+ }
37
+ let rawEvents = recording.events ?? [];
38
+ const rawActions = recording.actions;
39
+ if (Array.isArray(rawActions) && rawEvents.length === 0) {
40
+ rawEvents = rawActions.map((a) => {
41
+ const action = a;
42
+ const element = action.element ?? {};
43
+ return {
44
+ type: action.type,
45
+ selector: element.selector ?? action.selector,
46
+ data: { ...action.data, value: action.value, key: action.key },
47
+ scrollX: action.scrollX,
48
+ scrollY: action.scrollY
49
+ };
50
+ });
51
+ delete recording.actions;
52
+ }
53
+ const events = rawEvents;
30
54
  const originalCount = events.length;
31
55
  const exclude = excludeTypes || DEFAULT_EXCLUDE_TYPES;
32
56
  const filteredEvents = events.filter((event) => {
package/dist/index.d.ts CHANGED
@@ -1737,6 +1737,8 @@ interface UserAction {
1737
1737
  distance: number;
1738
1738
  duration: number;
1739
1739
  };
1740
+ /** Base64-encoded PNG screenshot of the target element (captured on key actions) */
1741
+ elementScreenshot?: string;
1740
1742
  }
1741
1743
  interface NetworkEntry {
1742
1744
  id: number;
@@ -1854,7 +1856,7 @@ declare class SessionRecorder {
1854
1856
  value?: string;
1855
1857
  url?: string;
1856
1858
  element?: UserAction['element'];
1857
- }): void;
1859
+ }): Promise<void>;
1858
1860
  get networkCount(): number;
1859
1861
  getLiveData(): RecordingData;
1860
1862
  addManualCheckpoint(type: string, hint: string, selector?: string): CheckpointEntry;
@@ -1884,6 +1886,14 @@ declare class SessionRecorder {
1884
1886
  private handleFileChooser;
1885
1887
  private pollActions;
1886
1888
  private flushPendingActions;
1889
+ /**
1890
+ * Capture a screenshot of the target element for key action types.
1891
+ * Returns a base64-encoded PNG string, or undefined if the element has no
1892
+ * selector or the screenshot fails (non-critical — never blocks recording).
1893
+ *
1894
+ * Only captures for: click, input, change, dblclick, and their CDP counterparts.
1895
+ */
1896
+ private captureElementScreenshot;
1887
1897
  /**
1888
1898
  * After a click, wait 300ms then scan for popover/dropdown/menu elements
1889
1899
  * near the click position. This runs server-side to avoid race conditions