ectrol 0.0.3 → 0.0.4

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/dist/index.d.mts CHANGED
@@ -88,9 +88,16 @@ declare class ElementHandle {
88
88
  * 填充输入框内容。
89
89
  * - 适用于 `<input>`、`<textarea>` 或 `contenteditable` 元素。
90
90
  * - 会触发 `input` 事件(冒泡)。
91
+ * - 支持自定义输入间隔, 'auto' 表示模拟自然输入节奏
92
+ * @example
93
+ * ```
94
+ * await element.fill('Hello, World!', { interval: 100 });
95
+ * ```
91
96
  */
92
97
  fill(value: string, options?: {
93
98
  timeout?: number;
99
+ interval?: number | 'auto';
100
+ append?: boolean;
94
101
  }): Promise<void>;
95
102
  /**
96
103
  * 在元素上发送按键事件。
@@ -237,6 +244,10 @@ declare class SessionStorage {
237
244
  removeItem(key: string): Promise<void>;
238
245
  }
239
246
  //#endregion
247
+ //#region src/utils.d.ts
248
+ declare function getHumanTypingDelay(index: number, text: string): number;
249
+ declare function sleep(ms: number): Promise<unknown>;
250
+ //#endregion
240
251
  //#region src/index.d.ts
241
252
  /**
242
253
  * Ectrol
@@ -261,4 +272,4 @@ declare class Ectrol {
261
272
  $(selector: string): ElementHandle;
262
273
  }
263
274
  //#endregion
264
- export { Ectrol, Ectrol as default, ElementHandle, IBoundingClientRect, ISize, IVector2D, LocalStorage, SessionStorage };
275
+ export { Ectrol, Ectrol as default, ElementHandle, IBoundingClientRect, ISize, IVector2D, LocalStorage, SessionStorage, getHumanTypingDelay, sleep };
package/dist/index.mjs CHANGED
@@ -1,3 +1,20 @@
1
+ //#region src/utils.ts
2
+ function getHumanTypingDelay(index, text) {
3
+ const char = text[index];
4
+ let delay = 90 + Math.random() * 60;
5
+ const progress = index / text.length;
6
+ if (progress < .15) delay *= 1.3;
7
+ else if (progress > .85) delay *= 1.25;
8
+ if (char === " ") delay += 40;
9
+ if (/[,.!?;:]/.test(char)) delay += 200 + Math.random() * 150;
10
+ if (Math.random() < .03) delay += 300 + Math.random() * 500;
11
+ return Math.max(40, Math.round(delay));
12
+ }
13
+ async function sleep(ms) {
14
+ return new Promise((resolve) => setTimeout(resolve, ms));
15
+ }
16
+
17
+ //#endregion
1
18
  //#region src/element.ts
2
19
  /**
3
20
  * ElementHandle
@@ -147,7 +164,7 @@ var ElementHandle = class {
147
164
  button: options?.button || "left",
148
165
  clickCount: 1
149
166
  });
150
- await new Promise((resolve) => setTimeout(resolve, options?.delay || 10));
167
+ await sleep(options?.delay || 10);
151
168
  this.contents.sendInputEvent({
152
169
  type: "mouseUp",
153
170
  x: rect.centerX,
@@ -198,22 +215,32 @@ var ElementHandle = class {
198
215
  * 填充输入框内容。
199
216
  * - 适用于 `<input>`、`<textarea>` 或 `contenteditable` 元素。
200
217
  * - 会触发 `input` 事件(冒泡)。
218
+ * - 支持自定义输入间隔, 'auto' 表示模拟自然输入节奏
219
+ * @example
220
+ * ```
221
+ * await element.fill('Hello, World!', { interval: 100 });
222
+ * ```
201
223
  */
202
224
  async fill(value, options) {
203
- await this.contents.executeJavaScript(`
225
+ await this.focus({ timeout: options?.timeout });
226
+ let interval;
227
+ if (typeof options?.interval === "number") interval = options?.interval;
228
+ if (!options?.append) await this.contents.executeJavaScript(`
204
229
  (function() {
205
230
  const target = ${this._getElement(options?.timeout)};
206
- if (!target) return null;
207
-
208
- // 验证输入框是否是文本类型
209
- if (target.element.tagName !== 'INPUT' && target.element.tagName !== 'TEXTAREA' && !target.element.isContentEditable) return null;
210
-
211
- target.element.focus();
212
-
213
- target.element.value = ${JSON.stringify(value)};
214
- target.element.dispatchEvent(new Event('input', { bubbles: true }));
231
+ if (target && target.element) {
232
+ if (target.element.tagName !== 'INPUT' && target.element.tagName !== 'TEXTAREA' && !target.element.isContentEditable) return null;
233
+ target.element.value = "";
234
+ }
215
235
  })()
216
236
  `);
237
+ for (let index = 0; index < value.length; index++) {
238
+ await sleep(interval || getHumanTypingDelay(index, value));
239
+ this.contents.sendInputEvent({
240
+ type: "char",
241
+ keyCode: value[index]
242
+ });
243
+ }
217
244
  }
218
245
  /**
219
246
  * 在元素上发送按键事件。
@@ -230,7 +257,7 @@ var ElementHandle = class {
230
257
  type: "keyDown",
231
258
  keyCode: key$1
232
259
  });
233
- await new Promise((resolve) => setTimeout(resolve, options?.delay || 10));
260
+ await sleep(options?.delay || 10);
234
261
  for (const key$1 of keys) this.contents.sendInputEvent({
235
262
  type: "keyUp",
236
263
  keyCode: key$1
@@ -587,4 +614,4 @@ var Ectrol = class {
587
614
  var src_default = Ectrol;
588
615
 
589
616
  //#endregion
590
- export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default };
617
+ export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default, getHumanTypingDelay, sleep };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ectrol",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.4",
5
5
  "description": "一个基于 Electron WebContents 的轻量级自动化助手,用于在你的应用内对网页内容进行交互(点击、输入、聚焦、键盘事件等)。",
6
6
  "author": "Cee Vee X <ceeveex@hotmail.com>",
7
7
  "license": "MIT",