donobu 5.21.5 → 5.21.6

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.
@@ -31,6 +31,11 @@ export declare class InputTextTool extends ReplayableInteraction<typeof InputTex
31
31
  target: ElementHandle<HTMLElement | SVGElement>;
32
32
  label?: ElementHandle<HTMLElement | SVGElement>;
33
33
  }): Promise<string>;
34
+ /**
35
+ * Returns true when the segment is a single character that Playwright's
36
+ * keyboard.press() can handle: printable ASCII (space through tilde).
37
+ */
38
+ private static isKeyboardPressable;
34
39
  private clearField;
35
40
  }
36
41
  //# sourceMappingURL=InputTextTool.d.ts.map
@@ -43,10 +43,24 @@ class InputTextTool extends ReplayableInteraction_1.ReplayableInteraction {
43
43
  await element.focus();
44
44
  const page = (0, TargetUtils_1.webPage)(context);
45
45
  await context.interactionVisualizer.pointAt(page, element);
46
- for (const char of parameters.text) {
47
- await page.keyboard.press(char, {
48
- delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(char),
49
- });
46
+ // Segment into grapheme clusters so that composite characters (e.g. ZWJ
47
+ // emoji sequences like 👨‍👩‍👧, flags, skin-tone variants) are kept intact.
48
+ const segmenter = new Intl.Segmenter(undefined, {
49
+ granularity: 'grapheme',
50
+ });
51
+ for (const { segment } of segmenter.segment(parameters.text)) {
52
+ if (InputTextTool.isKeyboardPressable(segment)) {
53
+ // Single typeable character — use press() for realistic keydown/keyup.
54
+ await page.keyboard.press(segment, {
55
+ delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(segment),
56
+ });
57
+ }
58
+ else {
59
+ // Multi-code-point cluster or character Playwright can't press (e.g.
60
+ // em-dash, smart quotes, emojis). Insert directly, mimicking a
61
+ // virtual keyboard or input method.
62
+ await page.keyboard.insertText(segment);
63
+ }
50
64
  }
51
65
  // Submit if requested
52
66
  if (parameters.finalizeWithSubmit) {
@@ -57,6 +71,13 @@ class InputTextTool extends ReplayableInteraction_1.ReplayableInteraction {
57
71
  }
58
72
  return `Inputted text '${parameters.text}' into: `;
59
73
  }
74
+ /**
75
+ * Returns true when the segment is a single character that Playwright's
76
+ * keyboard.press() can handle: printable ASCII (space through tilde).
77
+ */
78
+ static isKeyboardPressable(segment) {
79
+ return segment.length === 1 && segment >= ' ' && segment <= '~';
80
+ }
60
81
  async clearField(element) {
61
82
  try {
62
83
  const value = await element.inputValue();
@@ -31,6 +31,11 @@ export declare class InputTextTool extends ReplayableInteraction<typeof InputTex
31
31
  target: ElementHandle<HTMLElement | SVGElement>;
32
32
  label?: ElementHandle<HTMLElement | SVGElement>;
33
33
  }): Promise<string>;
34
+ /**
35
+ * Returns true when the segment is a single character that Playwright's
36
+ * keyboard.press() can handle: printable ASCII (space through tilde).
37
+ */
38
+ private static isKeyboardPressable;
34
39
  private clearField;
35
40
  }
36
41
  //# sourceMappingURL=InputTextTool.d.ts.map
@@ -43,10 +43,24 @@ class InputTextTool extends ReplayableInteraction_1.ReplayableInteraction {
43
43
  await element.focus();
44
44
  const page = (0, TargetUtils_1.webPage)(context);
45
45
  await context.interactionVisualizer.pointAt(page, element);
46
- for (const char of parameters.text) {
47
- await page.keyboard.press(char, {
48
- delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(char),
49
- });
46
+ // Segment into grapheme clusters so that composite characters (e.g. ZWJ
47
+ // emoji sequences like 👨‍👩‍👧, flags, skin-tone variants) are kept intact.
48
+ const segmenter = new Intl.Segmenter(undefined, {
49
+ granularity: 'grapheme',
50
+ });
51
+ for (const { segment } of segmenter.segment(parameters.text)) {
52
+ if (InputTextTool.isKeyboardPressable(segment)) {
53
+ // Single typeable character — use press() for realistic keydown/keyup.
54
+ await page.keyboard.press(segment, {
55
+ delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(segment),
56
+ });
57
+ }
58
+ else {
59
+ // Multi-code-point cluster or character Playwright can't press (e.g.
60
+ // em-dash, smart quotes, emojis). Insert directly, mimicking a
61
+ // virtual keyboard or input method.
62
+ await page.keyboard.insertText(segment);
63
+ }
50
64
  }
51
65
  // Submit if requested
52
66
  if (parameters.finalizeWithSubmit) {
@@ -57,6 +71,13 @@ class InputTextTool extends ReplayableInteraction_1.ReplayableInteraction {
57
71
  }
58
72
  return `Inputted text '${parameters.text}' into: `;
59
73
  }
74
+ /**
75
+ * Returns true when the segment is a single character that Playwright's
76
+ * keyboard.press() can handle: printable ASCII (space through tilde).
77
+ */
78
+ static isKeyboardPressable(segment) {
79
+ return segment.length === 1 && segment >= ' ' && segment <= '~';
80
+ }
60
81
  async clearField(element) {
61
82
  try {
62
83
  const value = await element.inputValue();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donobu",
3
- "version": "5.21.5",
3
+ "version": "5.21.6",
4
4
  "description": "Create browser automations with an LLM agent and replay them as Playwright scripts.",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/esm/main.js",