portadom 1.0.4 → 2.0.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 +83 -213
- package/dist/{cjs/dom → dom}/dom.d.ts +10 -9
- package/dist/{cjs/dom → dom}/domUtils.d.ts +11 -10
- package/dist/dom/types.d.ts +360 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1216 -0
- package/dist/index.js.map +1 -0
- package/dist/{cjs/page → page}/page.d.ts +3 -3
- package/dist/{cjs/page → page}/pageUtils.d.ts +2 -2
- package/dist/{cjs/page → page}/types.d.ts +1 -1
- package/dist/utils/async.d.ts +8 -0
- package/dist/utils/error.d.ts +1 -0
- package/dist/{cjs/utils → utils}/types.d.ts +2 -0
- package/package.json +42 -37
- package/dist/cjs/dom/dom.js +0 -809
- package/dist/cjs/dom/dom.js.map +0 -1
- package/dist/cjs/dom/domUtils.js +0 -126
- package/dist/cjs/dom/domUtils.js.map +0 -1
- package/dist/cjs/dom/types.d.ts +0 -419
- package/dist/cjs/dom/types.js +0 -248
- package/dist/cjs/dom/types.js.map +0 -1
- package/dist/cjs/index.d.ts +0 -6
- package/dist/cjs/index.js +0 -22
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/page/page.js +0 -105
- package/dist/cjs/page/page.js.map +0 -1
- package/dist/cjs/page/pageUtils.js +0 -116
- package/dist/cjs/page/pageUtils.js.map +0 -1
- package/dist/cjs/page/types.js +0 -3
- package/dist/cjs/page/types.js.map +0 -1
- package/dist/cjs/utils/async.d.ts +0 -23
- package/dist/cjs/utils/async.js +0 -99
- package/dist/cjs/utils/async.js.map +0 -1
- package/dist/cjs/utils/error.d.ts +0 -1
- package/dist/cjs/utils/error.js +0 -10
- package/dist/cjs/utils/error.js.map +0 -1
- package/dist/cjs/utils/format.js +0 -19
- package/dist/cjs/utils/format.js.map +0 -1
- package/dist/cjs/utils/types.js +0 -3
- package/dist/cjs/utils/types.js.map +0 -1
- package/dist/cjs/utils/url.js +0 -21
- package/dist/cjs/utils/url.js.map +0 -1
- /package/dist/{cjs/utils → utils}/format.d.ts +0 -0
- /package/dist/{cjs/utils → utils}/url.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,264 +1,134 @@
|
|
|
1
|
-
#
|
|
1
|
+
# portadom
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**One DOM interface. Any engine.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Download the HTML and feed into JSDOM or Cheerio.
|
|
7
|
-
- Through browser automation like Playwright, Puppeteer, or Selenium.
|
|
8
|
-
- Or right from inside the DevTools console, if you need to test something out.
|
|
5
|
+
Write scraping and extraction logic once. Run it on Cheerio, Playwright, or the Browser API. Swap engines when requirements change -- no rewrite needed.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
2. Check if the HTML data can be extracted statically, just from the HTML (no JS).
|
|
13
|
-
3. If static HTML is enough, then migrate vanilla JS to JSDOM or Cheerio.
|
|
14
|
-
4. If I need JS runtime, migrate the vanilla JS to Playwright or other browser automation tool.
|
|
15
|
-
|
|
16
|
-
Migrating from one to another can be prone to errors, and you may miss some features.
|
|
17
|
-
|
|
18
|
-
Portadom takes care of this. Here's how you can move the same DOM manipulation logic from Cheerio to Playwright:
|
|
19
|
-
|
|
20
|
-
Before:
|
|
21
|
-
|
|
22
|
-
```js
|
|
23
|
-
import { load as loadCheerio } from 'cheerio';
|
|
24
|
-
import { cheerioPortadom } from 'portadom';
|
|
25
|
-
|
|
26
|
-
// Loading step changes
|
|
27
|
-
const html = `<div>
|
|
28
|
-
<a href="#">Click Me!</a>
|
|
29
|
-
</div>`;
|
|
30
|
-
const $ = loadCheerio(html);
|
|
31
|
-
const dom = cheerioPortadom($.root(), url);
|
|
32
|
-
|
|
33
|
-
// DOM manipulation remains the same
|
|
34
|
-
const btn = dom.findOne('a');
|
|
35
|
-
const btnText = await btn.text();
|
|
36
|
-
// btnText == "Click Me!"
|
|
7
|
+
```bash
|
|
8
|
+
npm install portadom
|
|
37
9
|
```
|
|
38
10
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
import { playwrightLocatorPortadom } from 'portadom';
|
|
11
|
+
## Quick start
|
|
43
12
|
|
|
44
|
-
|
|
45
|
-
const page = await somehowLoadPage();
|
|
46
|
-
const bodyLoc = page.locator('body');
|
|
47
|
-
const dom = playwrightLocatorPortadom(bodyLoc, page);
|
|
13
|
+
Wrap any DOM engine in a `Portadom` instance, then use the same API everywhere:
|
|
48
14
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// btnText == "Click Me!"
|
|
53
|
-
```
|
|
15
|
+
```typescript
|
|
16
|
+
import * as cheerio from 'cheerio';
|
|
17
|
+
import { cheerioPortadom } from 'portadom';
|
|
54
18
|
|
|
55
|
-
|
|
19
|
+
// 1. Create a Portadom instance from a Cheerio root
|
|
20
|
+
const $ = cheerio.load('<h1>Hello</h1><a href="/about">About</a>');
|
|
21
|
+
const dom = cheerioPortadom($.root(), 'https://example.com');
|
|
56
22
|
|
|
57
|
-
|
|
58
|
-
|
|
23
|
+
// 2. Use the engine-agnostic API
|
|
24
|
+
await dom.findOne('h1').text(); // "Hello"
|
|
25
|
+
await dom.findOne('a').href(); // "https://example.com/about"
|
|
26
|
+
await dom.findMany('li').map((el) => el.text()); // ["Item 1", "Item 2", ...]
|
|
59
27
|
```
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
### Minimal example
|
|
29
|
+
Switch engines by changing only the setup -- the extraction logic stays identical:
|
|
64
30
|
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
<a href="#">Click Me!</a>
|
|
68
|
-
</div>`;
|
|
69
|
-
const $ = loadCheerio(html);
|
|
70
|
-
const dom = cheerioPortadom($.root(), url);
|
|
71
|
-
|
|
72
|
-
const btn = dom.findOne('a');
|
|
73
|
-
const btnText = await btn.text();
|
|
74
|
-
// btnText == "Click Me!"
|
|
31
|
+
```typescript
|
|
32
|
+
import { playwrightLocatorPortadom } from 'portadom';
|
|
75
33
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```
|
|
34
|
+
// 1. Create a Portadom instance from a Playwright locator
|
|
35
|
+
const dom = playwrightLocatorPortadom(page.locator('body'), page);
|
|
79
36
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const $ = loadCheerio(html);
|
|
84
|
-
const dom = cheerioPortadom($.root(), url);
|
|
85
|
-
// ...
|
|
86
|
-
const rootEl = dom.root();
|
|
87
|
-
const url = await dom.url();
|
|
88
|
-
|
|
89
|
-
// Find and extract data
|
|
90
|
-
const entries = await rootEl.findMany('.list-row:not(.native-agent):not(.reach-list)')
|
|
91
|
-
.mapAsyncSerial(async (el) => {
|
|
92
|
-
const employerName = await el.findOne('.employer').text();
|
|
93
|
-
const employerUrl = await el.findOne('.offer-company-logo-link').href();
|
|
94
|
-
const employerLogoUrl = await el.findOne('.offer-company-logo-link img').src();
|
|
95
|
-
|
|
96
|
-
const offerUrlEl = el.findOne('h2 a');
|
|
97
|
-
const offerUrl = await offerUrlEl.href();
|
|
98
|
-
const offerName = await offerUrlEl.text();
|
|
99
|
-
const offerId = offerUrl?.match(/O\d{2,}/)?.[0] ?? null;
|
|
100
|
-
|
|
101
|
-
const location = await el.findOne('.job-location').text();
|
|
102
|
-
|
|
103
|
-
const salaryText = await el.findOne('.label-group > a[data-dimension7="Salary label"]').text();
|
|
104
|
-
|
|
105
|
-
const labels = await el.findMany('.label-group > a:not([data-dimension7="Salary label"])')
|
|
106
|
-
.mapAsyncSerial((el) => el.text())
|
|
107
|
-
.then((arr) => arr.filter(Boolean) as string[]);
|
|
108
|
-
|
|
109
|
-
const footerInfoEl = el.findOne('.list-footer .info');
|
|
110
|
-
const lastChangeRelativeTimeEl = footerInfoEl.findOne('strong');
|
|
111
|
-
const lastChangeRelativeTime = await lastChangeRelativeTimeEl.text();
|
|
112
|
-
// Remove the element so it's easier to get the text content
|
|
113
|
-
await lastChangeRelativeTimeEl.remove();
|
|
114
|
-
const lastChangeTypeText = await footerInfoEl.textAsLower();
|
|
115
|
-
const lastChangeType = lastChangeTypeText === 'pridané' ? 'added' : 'modified';
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
listingUrl: url,
|
|
119
|
-
employerName,
|
|
120
|
-
employerUrl,
|
|
121
|
-
employerLogoUrl,
|
|
122
|
-
offerName,
|
|
123
|
-
offerUrl,
|
|
124
|
-
offerId,
|
|
125
|
-
location,
|
|
126
|
-
labels,
|
|
127
|
-
lastChangeRelativeTime,
|
|
128
|
-
lastChangeType,
|
|
129
|
-
};
|
|
130
|
-
});
|
|
37
|
+
// 2. Exact same API -- no changes needed
|
|
38
|
+
await dom.findOne('h1').text();
|
|
39
|
+
await dom.findOne('a').href();
|
|
131
40
|
```
|
|
132
41
|
|
|
133
|
-
|
|
42
|
+
## Why portadom?
|
|
134
43
|
|
|
135
|
-
|
|
44
|
+
### Write once. Run anywhere.
|
|
136
45
|
|
|
137
|
-
|
|
46
|
+
Cheerio, Playwright, and the Browser API have incompatible DOM APIs. Portadom wraps them behind a single `Portadom` interface. Your selectors, traversals, and data extraction stay the same regardless of engine.
|
|
138
47
|
|
|
139
|
-
|
|
48
|
+
### Chain without awaits.
|
|
140
49
|
|
|
141
|
-
|
|
142
|
-
import { browserPortadom } from 'portadom';
|
|
50
|
+
Traversal methods return `PortadomPromise` -- chain `findOne`, `closest`, `parent`, and more without intermediate `await`s. The promise resolves when you extract a value.
|
|
143
51
|
|
|
144
|
-
|
|
145
|
-
|
|
52
|
+
```typescript
|
|
53
|
+
// Without portadom
|
|
54
|
+
const root = await page.locator('#root').elementHandle();
|
|
55
|
+
const heading = root ? await root.$('h1') : null;
|
|
56
|
+
const text = heading ? await heading.textContent() : null;
|
|
146
57
|
|
|
147
|
-
//
|
|
148
|
-
const
|
|
149
|
-
const dom = browserPortadom(startNode);
|
|
150
|
-
const btnNode = await dom.findOne('a').node;
|
|
58
|
+
// With portadom
|
|
59
|
+
const text = await dom.findOne('#root').findOne('h1').text();
|
|
151
60
|
```
|
|
152
61
|
|
|
153
|
-
|
|
62
|
+
### Collections that feel like arrays.
|
|
154
63
|
|
|
155
|
-
|
|
64
|
+
`findMany()` returns `PortadomArrayPromise` -- the full `Array` API (`map`, `filter`, `find`, `slice`, `reduce`, ...) plus async helpers like `mapAsyncSerial` and `filterAsyncParallel`.
|
|
156
65
|
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const dom = cheerioPortadom($.root(), url);
|
|
163
|
-
const btnNode = await dom.findOne('a').node;
|
|
164
|
-
|
|
165
|
-
// Or
|
|
166
|
-
const startNode = $('a');
|
|
167
|
-
const dom = cheerioPortadom(startNode, url);
|
|
168
|
-
const btnNode = await dom.findOne('a').node;
|
|
169
|
-
|
|
170
|
-
// Set `null` if you don't have an URL for the HTML
|
|
171
|
-
const dom = cheerioPortadom($.root(), null);
|
|
66
|
+
```typescript
|
|
67
|
+
const prices = await dom
|
|
68
|
+
.findMany('.product')
|
|
69
|
+
.filterAsyncParallel(async (el) => (await el.attr('in-stock')) === 'true')
|
|
70
|
+
.mapAsyncSerial(async (el) => await el.findOne('.price').textAsNumber({ mode: 'float' }));
|
|
172
71
|
```
|
|
173
72
|
|
|
174
|
-
|
|
73
|
+
### URLs resolved automatically.
|
|
175
74
|
|
|
176
|
-
|
|
75
|
+
`href()` and `src()` resolve relative paths to absolute URLs using the page's base URL. No manual `new URL()` calls.
|
|
177
76
|
|
|
178
|
-
|
|
77
|
+
<details>
|
|
78
|
+
<summary>What portadom replaces (click to expand)</summary>
|
|
179
79
|
|
|
180
|
-
|
|
181
|
-
import { playwrightLocatorPortadom } from 'portadom';
|
|
80
|
+
**Cheerio -- extracting an href:**
|
|
182
81
|
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const btnNode = await dom.findOne('a').node;
|
|
82
|
+
```typescript
|
|
83
|
+
const rawHref = $('a').attr('href'); // "/about"
|
|
84
|
+
const absHref = rawHref?.startsWith('/') ? new URL(rawHref, 'https://example.com').href : rawHref;
|
|
187
85
|
```
|
|
188
86
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
When using ElementHandles, the `node` is an ElementHandle instance.
|
|
192
|
-
|
|
193
|
-
NOTE: You can pass Locator to `playwrightHandlePortadom`, but this will be converted to JSHandle internally.
|
|
194
|
-
|
|
195
|
-
```js
|
|
196
|
-
import { playwrightHandlePortadom } from 'portadom';
|
|
197
|
-
|
|
198
|
-
const page = await somehowLoadPage();
|
|
87
|
+
**Portadom:**
|
|
199
88
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const handle = await page.evaluateHandle(, () => document.querySelector('.myClass'));
|
|
203
|
-
|
|
204
|
-
// Or use other helpers such as `getByText`
|
|
205
|
-
const handle = await page.getByText('hello');
|
|
206
|
-
|
|
207
|
-
// Or use locators
|
|
208
|
-
const handle = page.locator('body');
|
|
209
|
-
|
|
210
|
-
const dom = playwrightHandlePortadom(bodyLoc, page);
|
|
211
|
-
const btnNode = await dom.findOne('a').node;
|
|
89
|
+
```typescript
|
|
90
|
+
await dom.findOne('a').href(); // "https://example.com/about"
|
|
212
91
|
```
|
|
213
92
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
For cross-compatibility, each method on a Portadom instance returns
|
|
217
|
-
a Promise.
|
|
93
|
+
</details>
|
|
218
94
|
|
|
219
|
-
|
|
95
|
+
## Supported engines
|
|
220
96
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
97
|
+
| Factory function | Engine | Element type |
|
|
98
|
+
| ------------------------------------------ | --------------------- | -------------------------- |
|
|
99
|
+
| `cheerioPortadom(el, url)` | Cheerio | `Cheerio<AnyNode>` |
|
|
100
|
+
| `playwrightLocatorPortadom(locator, page)` | Playwright (locators) | `Locator` |
|
|
101
|
+
| `playwrightHandlePortadom(handle, page)` | Playwright (handles) | `Locator \| ElementHandle` |
|
|
102
|
+
| `browserPortadom(element)` | Browser API | `Element` |
|
|
226
103
|
|
|
227
|
-
|
|
104
|
+
Install only the engine(s) you need:
|
|
228
105
|
|
|
229
|
-
```
|
|
230
|
-
|
|
106
|
+
```bash
|
|
107
|
+
npm install cheerio # static HTML
|
|
108
|
+
npm install playwright # browser automation
|
|
231
109
|
```
|
|
232
110
|
|
|
233
|
-
|
|
111
|
+
## Page-level operations (experimental)
|
|
234
112
|
|
|
235
|
-
|
|
236
|
-
const mapPromises = await dom.findOne('ul')
|
|
237
|
-
.parent()
|
|
238
|
-
.findMany('li[data-id]')
|
|
239
|
-
.map((li) => li.attr('data-id'));
|
|
240
|
-
const attrs = await Promise.all(mapResult);
|
|
241
|
-
```
|
|
113
|
+
`Portapage` provides page-level helpers like infinite scroll handling:
|
|
242
114
|
|
|
243
|
-
|
|
115
|
+
```typescript
|
|
116
|
+
import { playwrightPortapage } from 'portadom';
|
|
244
117
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const attrs = await Promise.all(mapPromises);
|
|
118
|
+
const portapage = await playwrightPortapage(page);
|
|
119
|
+
await portapage.infiniteScroll('#feed', async (newItems, ctx, stop) => {
|
|
120
|
+
// Process each batch of new DOM elements as they load
|
|
121
|
+
if (shouldStop) stop();
|
|
122
|
+
});
|
|
251
123
|
```
|
|
252
124
|
|
|
253
|
-
##
|
|
125
|
+
## Documentation
|
|
254
126
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
127
|
+
| Document | Description |
|
|
128
|
+
| ------------------------------------------ | -------------------------------- |
|
|
129
|
+
| [API reference](./docs/typedoc/globals.md) | Full typedoc-generated API docs. |
|
|
130
|
+
| [Changelog](./CHANGELOG.md) | Release history. |
|
|
258
131
|
|
|
259
|
-
##
|
|
132
|
+
## License
|
|
260
133
|
|
|
261
|
-
|
|
262
|
-
- [Example 1](https://github.com/JuroOravec/apify-actor-profesia-sk/blob/3793915632bd81dc257d36699808635c8bc3f87e/src/pageActions/jobListing.ts#L128)
|
|
263
|
-
- [Example 2](https://github.com/JuroOravec/apify-actor-profesia-sk/blob/3793915632bd81dc257d36699808635c8bc3f87e/src/pageActions/jobDetail.ts#L75)
|
|
264
|
-
- [SKCRIS Scraper](https://github.com/JuroOravec/apify-actor-skcris/blob/9ce92f9bd55ffcde91f22744e49ba97b6b4f0e44/src/pageActions/detail.ts#L510)
|
|
134
|
+
MIT
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import type { AnyNode
|
|
1
|
+
import type { AnyNode } from 'domhandler';
|
|
2
|
+
import type { Cheerio } from 'cheerio';
|
|
2
3
|
import type { ElementHandle, Locator, Page } from 'playwright';
|
|
3
|
-
import { type Portadom } from './types';
|
|
4
|
+
import { type Portadom } from './types.js';
|
|
4
5
|
/** Implementation of Portadom in browser (using Browser API) */
|
|
5
|
-
export type BrowserPortadom<
|
|
6
|
+
export type BrowserPortadom<El extends Element = Element> = Portadom<El>;
|
|
6
7
|
/** Implementation of Portadom in browser (using Browser API) */
|
|
7
|
-
export declare const browserPortadom: <El extends Element>(node: El) => BrowserPortadom<El>;
|
|
8
|
+
export declare const browserPortadom: <El extends Element = Element>(node: El) => BrowserPortadom<El>;
|
|
8
9
|
/** Implementation of Portadom in Cheerio */
|
|
9
10
|
export type CheerioPortadom<El extends Cheerio<AnyNode> = Cheerio<AnyNode>> = Portadom<El, Cheerio<AnyNode>>;
|
|
10
11
|
/** Implementation of Portadom in Cheerio */
|
|
11
|
-
export declare const cheerioPortadom: <El extends Cheerio<AnyNode>>(cheerioNode: El, srcUrl: string | null) => CheerioPortadom<El>;
|
|
12
|
+
export declare const cheerioPortadom: <El extends Cheerio<AnyNode> = Cheerio<AnyNode>>(cheerioNode: El, srcUrl: string | null) => CheerioPortadom<El>;
|
|
12
13
|
/** Implementation of Portadom in Playwright using Handles */
|
|
13
|
-
export type PlaywrightHandlePortadom<El extends Locator | ElementHandle
|
|
14
|
+
export type PlaywrightHandlePortadom<El extends Locator | ElementHandle = Locator | ElementHandle> = Portadom<El, Locator | ElementHandle>;
|
|
14
15
|
/** Implementation of Portadom in Playwright using Handles */
|
|
15
|
-
export declare const playwrightHandlePortadom: <El extends ElementHandle
|
|
16
|
+
export declare const playwrightHandlePortadom: <El extends Locator | ElementHandle = Locator | ElementHandle>(node: El, page: Page) => PlaywrightHandlePortadom<El>;
|
|
16
17
|
/** Implementation of Portadom in Playwright using Locators */
|
|
17
|
-
export type PlaywrightLocatorPortadom<El extends Locator = Locator> = Portadom<El
|
|
18
|
+
export type PlaywrightLocatorPortadom<El extends Locator = Locator> = Portadom<El>;
|
|
18
19
|
/** Implementation of Portadom in Playwright using Locators */
|
|
19
|
-
export declare const playwrightLocatorPortadom: <El extends Locator>(node: El, page: Page) => PlaywrightLocatorPortadom<El>;
|
|
20
|
+
export declare const playwrightLocatorPortadom: <El extends Locator = Locator>(node: El, page: Page) => PlaywrightLocatorPortadom<El>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { AnyNode
|
|
1
|
+
import type { AnyNode } from 'domhandler';
|
|
2
|
+
import type { Cheerio } from 'cheerio';
|
|
2
3
|
import type { ElementHandle, JSHandle, Locator } from 'playwright';
|
|
3
|
-
import type { MaybeArray, MaybePromise } from '../utils/types';
|
|
4
|
+
import type { MaybeArray, MaybePromise } from '../utils/types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Given a Cheerio selection, split it into an array of Cheerio selections,
|
|
6
7
|
* where each has only one element.
|
|
@@ -9,7 +10,7 @@ import type { MaybeArray, MaybePromise } from '../utils/types';
|
|
|
9
10
|
*
|
|
10
11
|
* To `[Cheerio[el], Cheerio[el], Cheerio[el], Cheerio[el]]`
|
|
11
12
|
*/
|
|
12
|
-
export declare const splitCheerioSelection: (cheerioSel: Cheerio<
|
|
13
|
+
export declare const splitCheerioSelection: <T extends AnyNode>(cheerioSel: Cheerio<T>) => Cheerio<T>[];
|
|
13
14
|
/**
|
|
14
15
|
* Given a Playwright JSHandle that points to an array of Elements, split it into an array of
|
|
15
16
|
* ElementHandles, where each has only one element.
|
|
@@ -18,12 +19,12 @@ export declare const splitCheerioSelection: (cheerioSel: Cheerio<AnyNode>) => Ch
|
|
|
18
19
|
*
|
|
19
20
|
* To `ElHandle(el), ElHandle(el), ElHandle(el)`
|
|
20
21
|
*/
|
|
21
|
-
export declare const splitPlaywrightSelection: <T>(handle: JSHandle<T[]>) => Promise<
|
|
22
|
+
export declare const splitPlaywrightSelection: <T>(handle: JSHandle<T[]>) => Promise<JSHandle<T>[]>;
|
|
22
23
|
/** Any instance that is a Playwright Handle. */
|
|
23
|
-
export type AnyHandle
|
|
24
|
+
export type AnyHandle = JSHandle | ElementHandle;
|
|
24
25
|
/** Any instance that is a Playwright Handle, or can be converted to one. */
|
|
25
|
-
export type HandleLike
|
|
26
|
-
export declare const handleIsLocator:
|
|
26
|
+
export type HandleLike = Locator | JSHandle | ElementHandle;
|
|
27
|
+
export declare const handleIsLocator: (h: HandleLike) => h is Locator;
|
|
27
28
|
/**
|
|
28
29
|
* Join several Locators and Handles in a single JSHandle.
|
|
29
30
|
*
|
|
@@ -31,12 +32,12 @@ export declare const handleIsLocator: <T>(h: HandleLike<T>) => h is Locator;
|
|
|
31
32
|
*
|
|
32
33
|
* To override how Locators are resolved, supply own `locatorResolver` function.
|
|
33
34
|
*/
|
|
34
|
-
export declare const mergeHandles:
|
|
35
|
+
export declare const mergeHandles: (handles: HandleLike[], options?: {
|
|
35
36
|
/**
|
|
36
37
|
* Configure how to process {@link Locator}s into {@link JSHandle}s.
|
|
37
38
|
*
|
|
38
39
|
* By default, Locator resolves to the first DOM Element it matches,
|
|
39
40
|
* using {@link Locator.elementHandle}.
|
|
40
41
|
*/
|
|
41
|
-
locatorResolver?: (
|
|
42
|
-
}
|
|
42
|
+
locatorResolver?: (loc: Locator) => MaybePromise<MaybeArray<AnyHandle>>;
|
|
43
|
+
}) => Promise<JSHandle<Element[]>>;
|