@xbrowser/cli 1.22.0 → 1.23.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # xbrowser
2
2
 
3
- > **Browser automation CLI** for web scraping, headless browsing, SEO analysis, and AI agent workflows. 51 commands, 75 plugins. A command-line alternative to Playwright, Puppeteer, and Selenium — **no code required**.
3
+ > **Browser automation CLI** for web scraping, headless browsing, SEO analysis, and AI agent workflows. 57 commands, 132 plugins. A command-line alternative to Playwright, Puppeteer, and Selenium — **no code required**.
4
4
 
5
5
  [![CI Status](https://github.com/dyyz1993/xbrowser/workflows/CI/badge.svg)](https://github.com/dyyz1993/xbrowser/actions)
6
6
  [![codecov](https://codecov.io/gh/dyyz1993/xbrowser/branch/master/graph/badge.svg)](https://codecov.io/gh/dyyz1993/xbrowser)
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## 特性
11
11
 
12
- - **51 浏览器命令** — 导航、交互、查询、存储、截图,覆盖常见自动化场景
12
+ - **57 浏览器命令** — 导航、交互、查询、存储、截图,覆盖常见自动化场景
13
13
  - **命令链** — 用 `&&`、`,`、`+`、`->`、`;` 串联多个命令,一行搞定复杂流程
14
14
  - **管道 & Heredoc** — 支持 stdin 管道和 heredoc 批量执行
15
15
  - **录制 / 回放** — 录制浏览器操作为 YAML,随时回放,可转换为 JS/Python/Bash 脚本
@@ -57,6 +57,22 @@ xbrowser juejin publish --file article.md
57
57
  # (Each platform has its own plugin — run `xbrowser plugin list` to see available)
58
58
  ```
59
59
 
60
+ **Content Marketing — xbrowser promotes itself (dogfooding)**
61
+ ```bash
62
+ # Browse the built-in promo case library (self-healing replay, CLI for AI agents, stealth…)
63
+ xbrowser content cases
64
+
65
+ # Render a case into a platform-ready article (en/zh, {{VAR}} substituted)
66
+ xbrowser content draft --case self-healing-replay --lang zh
67
+
68
+ # Render an OG cover image with the browser itself — zero imaging libraries
69
+ xbrowser "set-viewport 1200 630 && content cover --title 'Self-Healing Replay' --output cover.png"
70
+
71
+ # Publish through any of the 18 platform plugins
72
+ xbrowser devto publish --file output/content/self-healing-replay-en.md --tags "typescript,automation"
73
+ ```
74
+ The full write → cover → publish loop that promotes xbrowser is itself built on xbrowser commands.
75
+
60
76
  ## 快速开始
61
77
 
62
78
  ### 安装
@@ -546,6 +562,7 @@ xbrowser 自带以下插件:
546
562
  | **douyin** | `ai-summary`, `user-info`, `video-info` | 抖音视频信息提取 |
547
563
  | **github** | `update-profile`, `add-social-link`, `create-gist`, `get-profile` | GitHub 个人资料管理 |
548
564
  | **web-automation** | `extract`, `paginate`, `fill-and-submit`, `screenshot` | 通用 Web 自动化工具 |
565
+ | **content** | `cases`, `draft`, `cover` | 内容营销:内置推广 case 渲染成文 + 浏览器自渲染封面 |
549
566
 
550
567
  使用插件命令:
551
568
 
@@ -884,7 +901,7 @@ xbrowser/
884
901
  | **Setup** | `npm i -g` — 0 config | Install + browser download | Install + browser download | Install + WebDriver + drivers |
885
902
  | **Web Scraping** | Built-in (`scrape`, `crawl`, `map`) | Write custom scripts | Write custom scripts | Write custom scripts |
886
903
  | **Search** | Built-in multi-engine (`search`) | No | No | No |
887
- | **Plugin Ecosystem** | 75 plugins | Limited | Limited | No |
904
+ | **Plugin Ecosystem** | 132 plugins | Limited | Limited | No |
888
905
  | **No Code Required** | ✅ CLI commands | ❌ Must write JS/TS | ❌ Must write JS/TS | ❌ Must write code |
889
906
  | **Headless Mode** | ✅ Default | ✅ | ✅ | ✅ |
890
907
  | **Record/Replay** | ✅ Built-in (`record`/`replay`) | ✅ Codegen | ❌ | ❌ |
@@ -95,7 +95,7 @@ import { join } from "path";
95
95
  import { execSync } from "child_process";
96
96
  var SHARED_PLUGIN_DEPENDENCIES = {
97
97
  "zod": "^3.24.0",
98
- "@dyyz1993/xcli-core": "^0.12.1"
98
+ "@dyyz1993/xcli-core": "^0.19.0"
99
99
  };
100
100
  function ensurePluginDependencies(pluginsDir) {
101
101
  const zodPath = join(pluginsDir, "node_modules", "zod");
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-HBMEFSTB.js";
5
5
 
6
6
  // src/human-interaction.ts
7
- import { execSync } from "child_process";
7
+ import { execFile } from "child_process";
8
8
 
9
9
  // src/captcha-detector.ts
10
10
  var CAPTCHA_SELECTORS = [
@@ -138,11 +138,6 @@ var WebhookNotifier = class {
138
138
  }
139
139
  };
140
140
 
141
- // src/utils/shell-escape.ts
142
- function shellEscape(value) {
143
- return `'${value.replace(/'/g, "'\\''")}'`;
144
- }
145
-
146
141
  // src/human-interaction.ts
147
142
  var HumanInteractionManager = class {
148
143
  wsServer;
@@ -171,8 +166,10 @@ var HumanInteractionManager = class {
171
166
  tryAutoOpen(previewUrl) {
172
167
  if (!this.autoOpen) return;
173
168
  try {
174
- const cmd = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "start";
175
- execSync(`${cmd} ${shellEscape(previewUrl)}`, { stdio: "ignore" });
169
+ const opener = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "cmd";
170
+ const args = process.platform === "win32" ? ["/c", "start", "", previewUrl] : [previewUrl];
171
+ execFile(opener, args, { timeout: 1e4 }, () => {
172
+ });
176
173
  } catch {
177
174
  }
178
175
  }
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-ZTHE5RBZ.js";
4
4
 
5
5
  // src/human-interaction.ts
6
- import { execSync } from "child_process";
6
+ import { execFile } from "child_process";
7
7
 
8
8
  // src/screencast.ts
9
9
  var ScreencastCapturer = class {
@@ -278,11 +278,6 @@ var WebhookNotifier = class {
278
278
  }
279
279
  };
280
280
 
281
- // src/utils/shell-escape.ts
282
- function shellEscape(value) {
283
- return `'${value.replace(/'/g, "'\\''")}'`;
284
- }
285
-
286
281
  // src/human-interaction.ts
287
282
  var HumanInteractionManager = class {
288
283
  wsServer;
@@ -311,8 +306,10 @@ var HumanInteractionManager = class {
311
306
  tryAutoOpen(previewUrl) {
312
307
  if (!this.autoOpen) return;
313
308
  try {
314
- const cmd = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "start";
315
- execSync(`${cmd} ${shellEscape(previewUrl)}`, { stdio: "ignore" });
309
+ const opener = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "cmd";
310
+ const args = process.platform === "win32" ? ["/c", "start", "", previewUrl] : [previewUrl];
311
+ execFile(opener, args, { timeout: 1e4 }, () => {
312
+ });
316
313
  } catch {
317
314
  }
318
315
  }
@@ -1,5 +1,5 @@
1
1
  // src/human-interaction.ts
2
- import { execSync } from "child_process";
2
+ import { execFile } from "child_process";
3
3
 
4
4
  // src/screencast.ts
5
5
  var ScreencastCapturer = class {
@@ -362,11 +362,6 @@ function resolveScreenshotsDir() {
362
362
  return join(tmpdir(), "xbrowser", "screenshots");
363
363
  }
364
364
 
365
- // src/utils/shell-escape.ts
366
- function shellEscape(value) {
367
- return `'${value.replace(/'/g, "'\\''")}'`;
368
- }
369
-
370
365
  // src/human-interaction.ts
371
366
  var HumanInteractionManager = class {
372
367
  wsServer;
@@ -395,8 +390,10 @@ var HumanInteractionManager = class {
395
390
  tryAutoOpen(previewUrl) {
396
391
  if (!this.autoOpen) return;
397
392
  try {
398
- const cmd = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "start";
399
- execSync(`${cmd} ${shellEscape(previewUrl)}`, { stdio: "ignore" });
393
+ const opener = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : "cmd";
394
+ const args = process.platform === "win32" ? ["/c", "start", "", previewUrl] : [previewUrl];
395
+ execFile(opener, args, { timeout: 1e4 }, () => {
396
+ });
400
397
  } catch {
401
398
  }
402
399
  }