fastbrowser_cli 1.0.31 → 1.0.35

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 (60) hide show
  1. package/README.md +1 -2
  2. package/dist/fastbrowser_cli/fastbrowser_cli.js +11 -19
  3. package/dist/fastbrowser_cli/fastbrowser_cli.js.map +1 -1
  4. package/dist/fastbrowser_cli/libs/query-builder.d.ts +2 -0
  5. package/dist/fastbrowser_cli/libs/query-builder.d.ts.map +1 -1
  6. package/dist/fastbrowser_cli/libs/query-builder.js +4 -0
  7. package/dist/fastbrowser_cli/libs/query-builder.js.map +1 -1
  8. package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts +2 -0
  9. package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts.map +1 -1
  10. package/dist/fastbrowser_mcp/fastbrowser_mcp.js +193 -32
  11. package/dist/fastbrowser_mcp/fastbrowser_mcp.js.map +1 -1
  12. package/dist/fastbrowser_mcp/libs/mcp_my_client.d.ts.map +1 -1
  13. package/dist/fastbrowser_mcp/libs/mcp_my_client.js +8 -0
  14. package/dist/fastbrowser_mcp/libs/mcp_my_client.js.map +1 -1
  15. package/dist/fastbrowser_mcp/libs/mcp_target_helper.d.ts.map +1 -1
  16. package/dist/fastbrowser_mcp/libs/mcp_target_helper.js +15 -2
  17. package/dist/fastbrowser_mcp/libs/mcp_target_helper.js.map +1 -1
  18. package/dist/fastbrowser_mcp/libs/playwright_a11y_helper.d.ts +1 -0
  19. package/dist/fastbrowser_mcp/libs/playwright_a11y_helper.d.ts.map +1 -1
  20. package/dist/fastbrowser_mcp/libs/playwright_a11y_helper.js +33 -1
  21. package/dist/fastbrowser_mcp/libs/playwright_a11y_helper.js.map +1 -1
  22. package/dist/fastbrowser_mcp/libs/schemas.d.ts +4 -0
  23. package/dist/fastbrowser_mcp/libs/schemas.d.ts.map +1 -1
  24. package/dist/fastbrowser_mcp/libs/schemas.js +6 -0
  25. package/dist/fastbrowser_mcp/libs/schemas.js.map +1 -1
  26. package/dist/shared/logger.d.ts +86 -0
  27. package/dist/shared/logger.d.ts.map +1 -0
  28. package/dist/shared/logger.js +269 -0
  29. package/dist/shared/logger.js.map +1 -0
  30. package/docs/brainstorm_scrap_by_ai.md +1 -1
  31. package/docs/feature_support_cli.md +7 -8
  32. package/docs/target_tools/target_tools_chrome_devtools.md +963 -0
  33. package/docs/target_tools/target_tools_playwright.md +763 -0
  34. package/examples/linkedin_cli/linked_dm.sh +19 -0
  35. package/examples/linkedin_cli/linked_post.sh +13 -0
  36. package/examples/linkedin_cli/linkedin.snapshot.txt +1245 -0
  37. package/examples/todomvc/todomvc.a11y.txt +44 -0
  38. package/examples/todomvc/todomvc.sh +11 -0
  39. package/examples/wttj_cli/fastbrowser_helper.ts +39 -0
  40. package/examples/wttj_cli/wttf_job-original.a11y.txt +652 -0
  41. package/examples/wttj_cli/wttf_job.a11y.txt +317 -0
  42. package/examples/{welcometothejungle/wttj-job.ts → wttj_cli/wttj_job copy.ts } +60 -11
  43. package/examples/wttj_cli/wttj_job.ts +179 -0
  44. package/examples/wttj_cli/wttj_search.ts +162 -0
  45. package/package.json +10 -3
  46. package/skills/fastbrowser/SKILL.md +10 -11
  47. package/skills/fastbrowser-script/SKILL.md +4 -4
  48. package/src/fastbrowser_cli/fastbrowser_cli.ts +14 -25
  49. package/src/fastbrowser_cli/libs/query-builder.ts +6 -0
  50. package/src/fastbrowser_mcp/fastbrowser_mcp.ts +231 -36
  51. package/src/fastbrowser_mcp/libs/mcp_my_client.ts +17 -0
  52. package/src/fastbrowser_mcp/libs/mcp_target_helper.ts +15 -2
  53. package/src/fastbrowser_mcp/libs/playwright_a11y_helper.ts +33 -1
  54. package/src/fastbrowser_mcp/libs/schemas.ts +6 -0
  55. package/src/shared/logger.ts +317 -0
  56. package/test.a11y.txt +828 -0
  57. package/tests/query-builder.test.ts +51 -11
  58. package/examples/welcometothejungle/fastbrowser_helper.ts +0 -39
  59. package/examples/welcometothejungle/wttj-search.ts +0 -82
  60. /package/examples/{post-to-x.sh → twitter_cli/twitter_post.sh} +0 -0
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env npx tsx
2
+
3
+ // npm imports
4
+ import * as Commander from 'commander';
5
+ import { FastBrowserHelper } from './fastbrowser_helper.js';
6
+ import { A11yTree } from 'a11y_parse';
7
+
8
+ type JobSearchResult = {
9
+ title: string;
10
+ url: string;
11
+ };
12
+
13
+ ///////////////////////////////////////////////////////////////////////////////
14
+ ///////////////////////////////////////////////////////////////////////////////
15
+ //
16
+ ///////////////////////////////////////////////////////////////////////////////
17
+ ///////////////////////////////////////////////////////////////////////////////
18
+
19
+ class WttjSearch {
20
+
21
+ static async outputJson(jobs: Array<JobSearchResult>): Promise<void> {
22
+ console.log(JSON.stringify(jobs, null, 2));
23
+ }
24
+
25
+ static async outputMarkdown(jobs: Array<JobSearchResult>): Promise<void> {
26
+ console.log('| # | Title | URL |');
27
+ console.log('|---|-------|-----|');
28
+ for (const [i, job] of jobs.entries()) {
29
+ const url = job.url !== '' ? `[link](${job.url})` : '';
30
+ console.log(`| ${i + 1} | ${job.title} | ${url} |`);
31
+ }
32
+ }
33
+
34
+ ///////////////////////////////////////////////////////////////////////////////
35
+ ///////////////////////////////////////////////////////////////////////////////
36
+ //
37
+ ///////////////////////////////////////////////////////////////////////////////
38
+ ///////////////////////////////////////////////////////////////////////////////
39
+
40
+ private static parseJobTitles(output: string): Array<JobSearchResult> {
41
+ const results: Array<JobSearchResult> = [];
42
+ const headingRe = /heading "(.+?)" level/g;
43
+ const urlRe = /url="([^"]+)"/;
44
+ for (const line of output.split('\n')) {
45
+ const headingMatch = headingRe.exec(line);
46
+ if (headingMatch === null) continue;
47
+ const urlMatch = urlRe.exec(line);
48
+ results.push({
49
+ title: headingMatch[1],
50
+ url: urlMatch !== null ? urlMatch[1] : '',
51
+ });
52
+ headingRe.lastIndex = 0;
53
+ }
54
+ return results;
55
+ }
56
+
57
+ static async collectOnePageResults(): Promise<Array<JobSearchResult>> {
58
+ const searchResults: Array<JobSearchResult> = [];
59
+ const a11ySelector = 'link[url^="/fr/companies/"]';
60
+ let outputStr: string = await FastBrowserHelper.querySelectorsAll(a11ySelector, 0);
61
+ // trim output to avoid issues with trailing newlines
62
+ outputStr = outputStr.trim();
63
+ // split output into lines and remove the first line which is a header
64
+ const outputLines = outputStr.split('\n');
65
+ // remove the first line which is a header
66
+ outputLines.shift();
67
+
68
+ // parse each line as an axNode and extract the job title and url
69
+ for (const outputLine of outputLines) {
70
+ const axNode = A11yTree.parse(outputLine);
71
+ // sanity check - the axNode should have a 'name' and a 'url' attribute
72
+ if (axNode.name === undefined) {
73
+ throw new Error(`Expected axNode.name to be defined for selector: ${a11ySelector} line: ${outputLine}`);
74
+ }
75
+ if (axNode.attributes['url'] === undefined) {
76
+ throw new Error(`Expected axNode.url to be defined for selector: ${a11ySelector} line: ${outputLine}`);
77
+ }
78
+ // Build the search result object and add it to the results array
79
+ const searchResult: JobSearchResult = {
80
+ title: axNode.name!,
81
+ url: `https://www.welcometothejungle.com${axNode.attributes['url']!}`,
82
+ };
83
+ searchResults.push(searchResult);
84
+ }
85
+
86
+ // return the search results
87
+ return searchResults
88
+ }
89
+
90
+ static async runSearch(query: string, pageIndexLimit: number = 1, pageIndexOffset: number = 0): Promise<Array<JobSearchResult>> {
91
+ const searchResults: Array<JobSearchResult> = [];
92
+ for (let pageIndex = pageIndexOffset; pageIndex < pageIndexOffset + pageIndexLimit; pageIndex++) {
93
+ // load the page
94
+ const pageUrl = `https://www.welcometothejungle.com/fr/jobs-matches?page=${pageIndex + 1}`;
95
+ FastBrowserHelper.navigatePage(pageUrl);
96
+
97
+ // collect results for the current page
98
+ const newSearchResults = await this.collectOnePageResults();
99
+ searchResults.push(...newSearchResults);
100
+ }
101
+ return searchResults;
102
+ }
103
+ }
104
+
105
+ ///////////////////////////////////////////////////////////////////////////////
106
+ ///////////////////////////////////////////////////////////////////////////////
107
+ //
108
+ ///////////////////////////////////////////////////////////////////////////////
109
+ ///////////////////////////////////////////////////////////////////////////////
110
+
111
+
112
+ async function main() {
113
+ ///////////////////////////////////////////////////////////////////////////////
114
+ ///////////////////////////////////////////////////////////////////////////////
115
+ //
116
+ ///////////////////////////////////////////////////////////////////////////////
117
+ ///////////////////////////////////////////////////////////////////////////////
118
+
119
+ const program = new Commander.Command();
120
+ program
121
+ .argument('[query]', 'job search query', 'machine learning')
122
+ .option('-l, --page-limit <number>', 'number of pages to fetch', '1')
123
+ .option('-o, --page-offset <number>', 'first page to scrape', '0')
124
+ .addOption(new Commander.Option('-f, --format <format>', 'output format: json or markdown').choices(['json', 'markdown']).default('markdown'))
125
+ .parse();
126
+
127
+ type CliOptions = {
128
+ pageLimit: string;
129
+ pageOffset: string;
130
+ format: 'json' | 'markdown';
131
+ };
132
+ const options: CliOptions = program.opts<CliOptions>();
133
+
134
+ ///////////////////////////////////////////////////////////////////////////////
135
+ ///////////////////////////////////////////////////////////////////////////////
136
+ //
137
+ ///////////////////////////////////////////////////////////////////////////////
138
+ ///////////////////////////////////////////////////////////////////////////////
139
+
140
+ // run the search and get results
141
+ const query = program.args[0]
142
+ const limit = Number(options.pageLimit);
143
+ const offset = Number(options.pageOffset);
144
+ const searchResults: Array<JobSearchResult> = await WttjSearch.runSearch(query, limit, offset);
145
+
146
+ // Output results in the specified format
147
+ if (options.format === 'json') {
148
+ await WttjSearch.outputJson(searchResults);
149
+ } else if (options.format === 'markdown') {
150
+ await WttjSearch.outputMarkdown(searchResults);
151
+ } else {
152
+ throw new Error(`Unsupported output format: ${options.format}`);
153
+ }
154
+ }
155
+
156
+ ///////////////////////////////////////////////////////////////////////////////
157
+ ///////////////////////////////////////////////////////////////////////////////
158
+ // Entry point
159
+ ///////////////////////////////////////////////////////////////////////////////
160
+ ///////////////////////////////////////////////////////////////////////////////
161
+
162
+ void main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastbrowser_cli",
3
- "version": "1.0.31",
3
+ "version": "1.0.35",
4
4
  "description": "A CLI tool for FastBrowser, providing commands to interact with the FastBrowser MCP (Model Context Protocol) server and perform various browser automation tasks.",
5
5
  "main": "dist/fastbrowser_cli/fastbrowser_cli.js",
6
6
  "bin": {
@@ -12,14 +12,20 @@
12
12
  "license": "MIT",
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "https://github.com/jeromeetienne/skillmd_collecetion.git"
15
+ "url": "git+https://github.com/jeromeetienne/skillmd_collection.git",
16
+ "directory": "packages/fastbrowser_cli"
17
+ },
18
+ "homepage": "https://github.com/jeromeetienne/skillmd_collection/tree/main/packages/fastbrowser_cli#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/jeromeetienne/skillmd_collection/issues"
16
21
  },
17
- "homepage": "https://github.com/jeromeetienne/skillmd_collection/packages/fastbrowser_cli#readme",
18
22
  "type": "module",
19
23
  "dependencies": {
20
24
  "@modelcontextprotocol/sdk": "^1.29.0",
25
+ "chalk": "^5.6.2",
21
26
  "commander": "^12.1.0",
22
27
  "express": "^4.21.2",
28
+ "minimatch": "^10.2.5",
23
29
  "string-argv": "^0.3.2",
24
30
  "typescript": "^6.0.3",
25
31
  "zod": "^4.3.6",
@@ -45,6 +51,7 @@
45
51
  "prepublish:check": "test -z \"$(git status --porcelain)\" || (echo 'Working tree dirty — commit or stash first' && exit 1)",
46
52
  "version:bump": "npm version patch --no-git-tag-version && git add package.json && git commit -m \"feat: bump version in fastbrowser_cli package.json\"",
47
53
  "publish:all": "pnpm run prepublish:check && pnpm run build && pnpm run version:bump && pnpm publish --access public",
54
+ "clean:output:log": "rm -f outputs/*.log",
48
55
  "typecheck": "tsc -p tsconfig.json --noEmit",
49
56
  "test": "npx tsx --test 'tests/**/*.test.ts'"
50
57
  }
@@ -20,7 +20,7 @@ npx fastbrowser_cli <command> [flags]
20
20
 
21
21
  ## Typical Workflow
22
22
 
23
- 1. **Query** the accessibility tree for specific nodes: `query_selectors` (first match per selector) or `query_selectors_all` (every match per selector).
23
+ 1. **Query** the accessibility tree for specific nodes with `query_selectors` (first match per selector by default; pass `-a, --all` for every match).
24
24
  2. **Act** on an element by its accessibility selector: `click`, `fill_form`, `press_keys`. The selector can be a direct uid reference (e.g. `#1_42`, fastest path) or any CSS-like selector (e.g. `button[name="Submit"]`), which is resolved to a uid internally.
25
25
 
26
26
  Snapshot output looks like:
@@ -145,8 +145,8 @@ Example queries on it:
145
145
 
146
146
  ## Inspection
147
147
 
148
- - `query_selectors` and `query_selectors_all` are the most efficient way to get specific elements or data from the page. Use them instead of `take_snapshot` whenever possible.
149
- - Prefer `query_selectors` when you only need the first match per selector (cheaper, less output); use `query_selectors_all` when you need every match or want to cap with `--limit`.
148
+ - `query_selectors` is the most efficient way to get specific elements or data from the page. Use it instead of `take_snapshot` whenever possible.
149
+ - By default, `query_selectors` returns the first match per selector (cheaper, less output). Pass `-a, --all` when you need every match pair it with `--limit` to cap results per selector.
150
150
 
151
151
  ```bash
152
152
  # Query the accessibility tree returning the FIRST match per selector (--selector is repeatable)
@@ -159,14 +159,14 @@ npx fastbrowser_cli query_selectors --selector 'heading[level="1"]' --no-with-an
159
159
  npx fastbrowser_cli query_selectors \
160
160
  --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
161
161
 
162
- # Query the accessibility tree returning ALL matches per selector (--selector is repeatable)
163
- npx fastbrowser_cli query_selectors_all --selector "button" --selector "link" --limit 5
162
+ # Pass --all to return every match per selector; --limit caps results per selector (0 = unlimited)
163
+ npx fastbrowser_cli query_selectors --all --selector "button" --selector "link" --limit 5
164
164
 
165
165
  # Exclude ancestor nodes from the result
166
- npx fastbrowser_cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
166
+ npx fastbrowser_cli query_selectors --all --selector 'heading[level="1"]' --no-with-ancestors
167
167
 
168
- # Per-selector control over limit / withAncestors via JSON
169
- npx fastbrowser_cli query_selectors_all \
168
+ # Per-selector control over limit / withAncestors via JSON (with --all)
169
+ npx fastbrowser_cli query_selectors --all \
170
170
  --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
171
171
 
172
172
  # Take an accessibility-tree full page snapshot of the current page - very expensive, prefer targeted queries when possible
@@ -233,9 +233,8 @@ press_keys --keys "Tab, Enter"
233
233
  | `new_page` | Open a new page at a URL | `--url` |
234
234
  | `close_page` | Close a page by id | `--page-id` |
235
235
  | `navigate_page` | Navigate current page to a URL | `--url` |
236
- | `take_snapshot` | Dump the accessibility tree of the whole page - very expensive, prefer targeted queries (`query_selectors` / `query_selectors_all`) when possible | — |
237
- | `query_selectors` | Query a11y tree by CSS-like selector, returning the first match per selector | `--selector` or `--selectors-json` |
238
- | `query_selectors_all` | Query a11y tree by CSS-like selector, returning every match per selector | `--selector` or `--selectors-json` |
236
+ | `take_snapshot` | Dump the accessibility tree of the whole page - very expensive, prefer targeted queries (`query_selectors`) when possible | — |
237
+ | `query_selectors` | Query a11y tree by CSS-like selector (first match per selector by default; pass `-a, --all` for every match, with optional `--limit`) | `--selector` or `--selectors-json` |
239
238
  | `click` | Click an element by accessibility selector | `--selector` / `-s` |
240
239
  | `fill_form` | Fill a form field by accessibility selector | `--selector` / `-s`, `--value` |
241
240
  | `press_keys` | Press a comma-separated key sequence | `--keys` |
@@ -30,7 +30,7 @@ Always follow this order — guessing selectors without checking the page wastes
30
30
  the user wants to parameterize (query, message, page count), and output format (stdout text,
31
31
  JSON, Markdown, file).
32
32
  2. **Probe the live page.** Open it and find selectors that actually match. Prefer
33
- `query_selectors` / `query_selectors_all` over `take_snapshot` (cheaper, less noise).
33
+ `query_selectors` (use `-a, --all` to get every match) over `take_snapshot` (cheaper, less noise).
34
34
  ```bash
35
35
  npx fastbrowser_cli new_page --url https://example.com
36
36
  npx fastbrowser_cli query_selectors -s 'searchbox' -s 'button[name*="Search"]'
@@ -72,12 +72,12 @@ Hard-coded selectors are the fragile part of any scraper — choose stable ones.
72
72
  - Use **scoping** when a role is ambiguous: `dialog textbox`, `navigation > link`.
73
73
  - **Never** use uid selectors (`#1_42`, `#4`) in a script. They are session-local and change on
74
74
  every page rebuild. See the hard rule at the top.
75
- - If you need every match (e.g. a list of results), use `query_selectors_all --limit N` with a
76
- reasonable cap; the default returns everything and is expensive.
75
+ - If you need every match (e.g. a list of results), use `query_selectors --all --limit N` with a
76
+ reasonable cap; without `--limit` it returns everything and is expensive.
77
77
 
78
78
  ## Output parsing
79
79
 
80
- `query_selectors` / `query_selectors_all` print one indented line per node:
80
+ `query_selectors` prints one indented line per node:
81
81
 
82
82
  ```
83
83
  uid=1_12 heading "Welcome" level="1"
@@ -299,42 +299,31 @@ async function main(): Promise<void> {
299
299
  });
300
300
  });
301
301
 
302
- program
303
- .command('query_selectors_all')
304
- .description('Query the accessibility tree with CSS-like selectors')
305
- .option('-s, --selector <selector>', 'CSS-like selector (repeatable)', (value: string, prev: string[] = []) => {
306
- prev.push(value);
307
- return prev;
308
- })
309
- .option('--limit <number>', 'Max nodes per selector (0 = unlimited)', '0')
310
- .option('--with-ancestors', 'Include ancestor nodes', false)
311
- .option('--no-with-ancestors', 'Exclude ancestor nodes')
312
- .option('--selectors-json <json>', 'JSON array of {selector,limit,withAncestors} for per-selector control')
313
- .action(async (opts: {
314
- selector?: string[];
315
- limit?: string;
316
- withAncestors?: boolean;
317
- selectorsJson?: string;
318
- }, cmd: Command) => {
319
- const body = QueryBuilder.buildQuerySelectorsBody(opts);
320
- await MainHelper.runTool(cmd, 'query_selectors_all', body);
321
- });
322
-
323
302
  program
324
303
  .command('query_selectors')
325
- .description('Query the accessibility tree with CSS-like selectors and, for each, return the first matching node')
304
+ .description('Query the accessibility tree with CSS-like selectors. By default returns the first match per selector; use --all to return every match.')
326
305
  .option('-s, --selector <selector>', 'CSS-like selector (repeatable)', (value: string, prev: string[] = []) => {
327
306
  prev.push(value);
328
307
  return prev;
329
308
  })
330
- .option('--with-ancestors', 'Include ancestor nodes', false)
331
- .option('--no-with-ancestors', 'Exclude ancestor nodes')
332
- .option('--selectors-json <json>', 'JSON array of {selector,withAncestors} for per-selector control')
309
+ .option('-a, --all', 'Return all matches per selector (default: first match only)', false)
310
+ .option('--limit <number>', 'Max nodes per selector when --all is set (0 = unlimited)', '0')
311
+ .option('--wa, --with-ancestors', 'Include ancestor nodes', false)
312
+ .option('--wc, --with-children', 'Include descendant nodes (subtree) of each matched node', false)
313
+ .option('--selectors-json <json>', 'JSON array of {selector,limit?,withAncestors,withChildren} for per-selector control')
333
314
  .action(async (opts: {
334
315
  selector?: string[];
316
+ all?: boolean;
317
+ limit?: string;
335
318
  withAncestors?: boolean;
319
+ withChildren?: boolean;
336
320
  selectorsJson?: string;
337
321
  }, cmd: Command) => {
322
+ if (opts.all === true) {
323
+ const body = QueryBuilder.buildQuerySelectorsBody(opts);
324
+ await MainHelper.runTool(cmd, 'query_selectors_all', body);
325
+ return;
326
+ }
338
327
  const body = QueryBuilder.buildQuerySelectorFirstBody(opts);
339
328
  await MainHelper.runTool(cmd, 'query_selectors', body);
340
329
  });
@@ -16,12 +16,14 @@ export type BuildQuerySelectorsAllOpts = {
16
16
  selector?: string[];
17
17
  limit?: string;
18
18
  withAncestors?: boolean;
19
+ withChildren?: boolean;
19
20
  selectorsJson?: string;
20
21
  };
21
22
 
22
23
  export type BuildQuerySelectorFirstOpts = {
23
24
  selector?: string[];
24
25
  withAncestors?: boolean;
26
+ withChildren?: boolean;
25
27
  selectorsJson?: string;
26
28
  };
27
29
 
@@ -50,11 +52,13 @@ export class QueryBuilder {
50
52
  throw new Error(`Invalid --limit: ${opts.limit}`);
51
53
  }
52
54
  const withAncestors = opts.withAncestors !== false;
55
+ const withChildren = opts.withChildren === true;
53
56
 
54
57
  const selectors: QuerySelectorInput[] = selectorList.map((selector) => ({
55
58
  selector,
56
59
  limit,
57
60
  withAncestors,
61
+ withChildren,
58
62
  }));
59
63
  return { selectors };
60
64
  }
@@ -79,10 +83,12 @@ export class QueryBuilder {
79
83
  }
80
84
 
81
85
  const withAncestors = opts.withAncestors !== false;
86
+ const withChildren = opts.withChildren === true;
82
87
 
83
88
  const selectors: QuerySelectorFirstInput[] = selectorList.map((selector) => ({
84
89
  selector,
85
90
  withAncestors,
91
+ withChildren,
86
92
  }));
87
93
  return { selectors };
88
94
  }