@rickcedwhat/playwright-smart-table 6.7.1 ā 6.7.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/README.md +2 -0
- package/dist/engine/rowFinder.js +62 -57
- package/dist/minimalConfigContext.d.ts +1 -1
- package/dist/minimalConfigContext.js +0 -3
- package/dist/plugins.d.ts +5 -2
- package/dist/smartRow.js +20 -25
- package/dist/strategies/glide.d.ts +5 -2
- package/dist/strategies/glide.js +3 -0
- package/dist/strategies/index.d.ts +2 -0
- package/dist/strategies/pagination.d.ts +2 -0
- package/dist/strategies/pagination.js +28 -7
- package/dist/strategies/rdg.d.ts +2 -2
- package/dist/strategies/validation.d.ts +2 -7
- package/dist/strategies/validation.js +6 -14
- package/dist/typeContext.d.ts +2 -2
- package/dist/typeContext.js +29 -10
- package/dist/types.d.ts +25 -9
- package/dist/useTable.js +186 -138
- package/dist/utils/paginationPath.d.ts +37 -0
- package/dist/utils/paginationPath.js +227 -0
- package/package.json +7 -2
package/dist/typeContext.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TYPE_CONTEXT = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* š¤ AUTO-GENERATED FILE. DO NOT EDIT.
|
|
6
|
-
* This file is generated by scripts/embed-types.
|
|
6
|
+
* This file is generated by scripts/embed-types.mjs
|
|
7
7
|
* It contains the raw text of types.ts to provide context for LLM prompts.
|
|
8
8
|
*/
|
|
9
9
|
exports.TYPE_CONTEXT = `
|
|
@@ -231,20 +231,30 @@ export interface PaginationPrimitives {
|
|
|
231
231
|
/** Classic "Previous Page" or "Scroll Up" */
|
|
232
232
|
goPrevious?: (context: TableContext) => Promise<boolean>;
|
|
233
233
|
|
|
234
|
-
/** Bulk skip forward multiple pages at once */
|
|
235
|
-
goNextBulk?: (context: TableContext) => Promise<boolean>;
|
|
234
|
+
/** Bulk skip forward multiple pages at once. Returns number of pages skipped. */
|
|
235
|
+
goNextBulk?: (context: TableContext) => Promise<boolean | number>;
|
|
236
236
|
|
|
237
|
-
/** Bulk skip backward multiple pages at once */
|
|
238
|
-
goPreviousBulk?: (context: TableContext) => Promise<boolean>;
|
|
237
|
+
/** Bulk skip backward multiple pages at once. Returns number of pages skipped. */
|
|
238
|
+
goPreviousBulk?: (context: TableContext) => Promise<boolean | number>;
|
|
239
239
|
|
|
240
240
|
/** Jump to first page / scroll to top */
|
|
241
241
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
242
242
|
|
|
243
|
-
/**
|
|
243
|
+
/**
|
|
244
|
+
* Jump to specific page index (0-indexed).
|
|
245
|
+
* Can be full-range (e.g. page number input: any page works) or windowed (e.g. only visible links 6ā14).
|
|
246
|
+
* Return false when the page is not reachable in the current UI; the library will step toward the target (goNextBulk/goNext or goPreviousBulk/goPrevious) and retry goToPage until it succeeds.
|
|
247
|
+
*/
|
|
244
248
|
goToPage?: (pageIndex: number, context: TableContext) => Promise<boolean>;
|
|
249
|
+
|
|
250
|
+
/** How many pages one goNextBulk() advances. Used by navigation path planner for optimal bringIntoView. */
|
|
251
|
+
nextBulkPages?: number;
|
|
252
|
+
|
|
253
|
+
/** How many pages one goPreviousBulk() goes back. Used by navigation path planner for optimal bringIntoView. */
|
|
254
|
+
previousBulkPages?: number;
|
|
245
255
|
}
|
|
246
256
|
|
|
247
|
-
export type PaginationStrategy =
|
|
257
|
+
export type PaginationStrategy = PaginationPrimitives;
|
|
248
258
|
|
|
249
259
|
export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
|
|
250
260
|
|
|
@@ -417,6 +427,11 @@ export type RowIterationOptions = {
|
|
|
417
427
|
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
418
428
|
*/
|
|
419
429
|
dedupe?: DedupeStrategy;
|
|
430
|
+
/**
|
|
431
|
+
* When true, use goNextBulk (if present) to advance pages during iteration.
|
|
432
|
+
* @default false ā uses goNext for one-page-at-a-time advancement
|
|
433
|
+
*/
|
|
434
|
+
useBulkPagination?: boolean;
|
|
420
435
|
};
|
|
421
436
|
|
|
422
437
|
export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>; rowIndex: number }> {
|
|
@@ -451,10 +466,9 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
451
466
|
) => SmartRow;
|
|
452
467
|
|
|
453
468
|
/**
|
|
454
|
-
* Gets a row by
|
|
469
|
+
* Gets a row by 0-based index on the current page.
|
|
455
470
|
* Throws error if table is not initialized.
|
|
456
|
-
* @param index
|
|
457
|
-
* @param options Optional settings including bringIntoView
|
|
471
|
+
* @param index 0-based row index
|
|
458
472
|
*/
|
|
459
473
|
getRowByIndex: (
|
|
460
474
|
index: number
|
|
@@ -581,6 +595,11 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
581
595
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
582
596
|
* Automatically throws an Error containing the prompt.
|
|
583
597
|
*/
|
|
598
|
+
generateConfig: () => Promise<void>;
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* @deprecated Use \`generateConfig()\` instead. Will be removed in v7.0.0.
|
|
602
|
+
*/
|
|
584
603
|
generateConfigPrompt: () => Promise<void>;
|
|
585
604
|
}
|
|
586
605
|
`;
|
package/dist/types.d.ts
CHANGED
|
@@ -205,16 +205,24 @@ export interface PaginationPrimitives {
|
|
|
205
205
|
goNext?: (context: TableContext) => Promise<boolean>;
|
|
206
206
|
/** Classic "Previous Page" or "Scroll Up" */
|
|
207
207
|
goPrevious?: (context: TableContext) => Promise<boolean>;
|
|
208
|
-
/** Bulk skip forward multiple pages at once */
|
|
209
|
-
goNextBulk?: (context: TableContext) => Promise<boolean>;
|
|
210
|
-
/** Bulk skip backward multiple pages at once */
|
|
211
|
-
goPreviousBulk?: (context: TableContext) => Promise<boolean>;
|
|
208
|
+
/** Bulk skip forward multiple pages at once. Returns number of pages skipped. */
|
|
209
|
+
goNextBulk?: (context: TableContext) => Promise<boolean | number>;
|
|
210
|
+
/** Bulk skip backward multiple pages at once. Returns number of pages skipped. */
|
|
211
|
+
goPreviousBulk?: (context: TableContext) => Promise<boolean | number>;
|
|
212
212
|
/** Jump to first page / scroll to top */
|
|
213
213
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
214
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* Jump to specific page index (0-indexed).
|
|
216
|
+
* Can be full-range (e.g. page number input: any page works) or windowed (e.g. only visible links 6ā14).
|
|
217
|
+
* Return false when the page is not reachable in the current UI; the library will step toward the target (goNextBulk/goNext or goPreviousBulk/goPrevious) and retry goToPage until it succeeds.
|
|
218
|
+
*/
|
|
215
219
|
goToPage?: (pageIndex: number, context: TableContext) => Promise<boolean>;
|
|
220
|
+
/** How many pages one goNextBulk() advances. Used by navigation path planner for optimal bringIntoView. */
|
|
221
|
+
nextBulkPages?: number;
|
|
222
|
+
/** How many pages one goPreviousBulk() goes back. Used by navigation path planner for optimal bringIntoView. */
|
|
223
|
+
previousBulkPages?: number;
|
|
216
224
|
}
|
|
217
|
-
export type PaginationStrategy =
|
|
225
|
+
export type PaginationStrategy = PaginationPrimitives;
|
|
218
226
|
export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
|
|
219
227
|
export type FillStrategy = (options: {
|
|
220
228
|
row: SmartRow;
|
|
@@ -387,6 +395,11 @@ export type RowIterationOptions = {
|
|
|
387
395
|
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
388
396
|
*/
|
|
389
397
|
dedupe?: DedupeStrategy;
|
|
398
|
+
/**
|
|
399
|
+
* When true, use goNextBulk (if present) to advance pages during iteration.
|
|
400
|
+
* @default false ā uses goNext for one-page-at-a-time advancement
|
|
401
|
+
*/
|
|
402
|
+
useBulkPagination?: boolean;
|
|
390
403
|
};
|
|
391
404
|
export interface TableResult<T = any> extends AsyncIterable<{
|
|
392
405
|
row: SmartRow<T>;
|
|
@@ -419,10 +432,9 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
419
432
|
exact?: boolean;
|
|
420
433
|
}) => SmartRow;
|
|
421
434
|
/**
|
|
422
|
-
* Gets a row by
|
|
435
|
+
* Gets a row by 0-based index on the current page.
|
|
423
436
|
* Throws error if table is not initialized.
|
|
424
|
-
* @param index
|
|
425
|
-
* @param options Optional settings including bringIntoView
|
|
437
|
+
* @param index 0-based row index
|
|
426
438
|
*/
|
|
427
439
|
getRowByIndex: (index: number) => SmartRow;
|
|
428
440
|
/**
|
|
@@ -526,5 +538,9 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
526
538
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
527
539
|
* Automatically throws an Error containing the prompt.
|
|
528
540
|
*/
|
|
541
|
+
generateConfig: () => Promise<void>;
|
|
542
|
+
/**
|
|
543
|
+
* @deprecated Use `generateConfig()` instead. Will be removed in v7.0.0.
|
|
544
|
+
*/
|
|
529
545
|
generateConfigPrompt: () => Promise<void>;
|
|
530
546
|
}
|
package/dist/useTable.js
CHANGED
|
@@ -24,6 +24,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.useTable = void 0;
|
|
26
26
|
const minimalConfigContext_1 = require("./minimalConfigContext");
|
|
27
|
+
const validation_1 = require("./strategies/validation");
|
|
27
28
|
const loading_1 = require("./strategies/loading");
|
|
28
29
|
const fill_1 = require("./strategies/fill");
|
|
29
30
|
const headers_1 = require("./strategies/headers");
|
|
@@ -33,6 +34,7 @@ const tableMapper_1 = require("./engine/tableMapper");
|
|
|
33
34
|
const rowFinder_1 = require("./engine/rowFinder");
|
|
34
35
|
const debugUtils_1 = require("./utils/debugUtils");
|
|
35
36
|
const smartRowArray_1 = require("./utils/smartRowArray");
|
|
37
|
+
const elementTracker_1 = require("./utils/elementTracker");
|
|
36
38
|
/**
|
|
37
39
|
* Main hook to interact with a table.
|
|
38
40
|
*/
|
|
@@ -44,7 +46,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
44
46
|
const defaultStrategies = {
|
|
45
47
|
fill: fill_1.FillStrategies.default,
|
|
46
48
|
header: headers_1.HeaderStrategies.visible,
|
|
47
|
-
pagination:
|
|
49
|
+
pagination: {},
|
|
48
50
|
loading: {
|
|
49
51
|
isHeaderLoading: loading_1.LoadingStrategies.Headers.stable(200)
|
|
50
52
|
}
|
|
@@ -124,20 +126,26 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
124
126
|
const _autoInit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
125
127
|
yield tableMapper.getMap();
|
|
126
128
|
});
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
// Default: goNext (one page). Pass useBulk true to prefer goNextBulk. "How far" uses numeric return when strategy provides it.
|
|
130
|
+
const _advancePage = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (useBulk = false) {
|
|
129
131
|
const context = { root: rootLocator, config, page: rootLocator.page(), resolve, getHeaderCell: result.getHeaderCell, getHeaders: result.getHeaders, scrollToColumn: result.scrollToColumn };
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
const pagination = config.strategies.pagination;
|
|
133
|
+
let rawResult;
|
|
134
|
+
if (useBulk && (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk)) {
|
|
135
|
+
rawResult = yield pagination.goNextBulk(context);
|
|
133
136
|
}
|
|
134
|
-
else {
|
|
135
|
-
|
|
137
|
+
else if (pagination === null || pagination === void 0 ? void 0 : pagination.goNext) {
|
|
138
|
+
rawResult = yield pagination.goNext(context);
|
|
136
139
|
}
|
|
137
|
-
if (
|
|
138
|
-
|
|
140
|
+
else if (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk) {
|
|
141
|
+
rawResult = yield pagination.goNextBulk(context);
|
|
139
142
|
}
|
|
140
|
-
|
|
143
|
+
const didAdvance = rawResult !== undefined && (0, validation_1.validatePaginationResult)(rawResult, 'Pagination Strategy');
|
|
144
|
+
const pagesJumped = typeof rawResult === 'number' ? rawResult : (didAdvance ? 1 : 0);
|
|
145
|
+
if (pagesJumped > 0) {
|
|
146
|
+
tableState.currentPageIndex += pagesJumped;
|
|
147
|
+
}
|
|
148
|
+
return didAdvance;
|
|
141
149
|
});
|
|
142
150
|
const result = {
|
|
143
151
|
get currentPageIndex() { return tableState.currentPageIndex; },
|
|
@@ -177,7 +185,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
177
185
|
log("Resetting table...");
|
|
178
186
|
const context = { root: rootLocator, config, page: rootLocator.page(), resolve, getHeaderCell: result.getHeaderCell };
|
|
179
187
|
yield config.onReset(context);
|
|
180
|
-
if (
|
|
188
|
+
if ((_a = config.strategies.pagination) === null || _a === void 0 ? void 0 : _a.goToFirst) {
|
|
181
189
|
log("Auto-navigating to first page...");
|
|
182
190
|
yield config.strategies.pagination.goToFirst(context);
|
|
183
191
|
}
|
|
@@ -266,185 +274,225 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
266
274
|
yield __await(_autoInit());
|
|
267
275
|
const map = tableMapper.getMapSync();
|
|
268
276
|
const effectiveMaxPages = config.maxPages;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
const tracker = new elementTracker_1.ElementTracker('iterator');
|
|
278
|
+
const useBulk = false; // iterator has no options; default goNext
|
|
279
|
+
try {
|
|
280
|
+
let rowIndex = 0;
|
|
281
|
+
let pagesScanned = 1;
|
|
282
|
+
while (true) {
|
|
283
|
+
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
284
|
+
const newIndices = yield __await(tracker.getUnseenIndices(rowLocators));
|
|
285
|
+
const pageRows = yield __await(rowLocators.all());
|
|
286
|
+
for (const idx of newIndices) {
|
|
287
|
+
yield yield __await({ row: _makeSmart(pageRows[idx], map, rowIndex), rowIndex });
|
|
288
|
+
rowIndex++;
|
|
289
|
+
}
|
|
290
|
+
if (pagesScanned >= effectiveMaxPages)
|
|
291
|
+
break;
|
|
292
|
+
if (!(yield __await(_advancePage(useBulk))))
|
|
293
|
+
break;
|
|
294
|
+
pagesScanned++;
|
|
276
295
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
break;
|
|
281
|
-
pagesScanned++;
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
yield __await(tracker.cleanup(rootLocator.page()));
|
|
282
299
|
}
|
|
283
300
|
});
|
|
284
301
|
},
|
|
285
302
|
// āāā Private row-iteration engine āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
286
303
|
forEach: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
287
|
-
var _a, _b, _c;
|
|
304
|
+
var _a, _b, _c, _d;
|
|
288
305
|
yield _autoInit();
|
|
289
306
|
const map = tableMapper.getMapSync();
|
|
290
307
|
const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
|
|
291
308
|
const dedupeStrategy = (_b = options.dedupe) !== null && _b !== void 0 ? _b : config.strategies.dedupe;
|
|
292
309
|
const dedupeKeys = dedupeStrategy ? new Set() : null;
|
|
293
310
|
const parallel = (_c = options.parallel) !== null && _c !== void 0 ? _c : false;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
311
|
+
const useBulk = (_d = options.useBulkPagination) !== null && _d !== void 0 ? _d : false;
|
|
312
|
+
const tracker = new elementTracker_1.ElementTracker('forEach');
|
|
313
|
+
try {
|
|
314
|
+
let rowIndex = 0;
|
|
315
|
+
let stopped = false;
|
|
316
|
+
let pagesScanned = 1;
|
|
317
|
+
const stop = () => { stopped = true; };
|
|
318
|
+
while (!stopped) {
|
|
319
|
+
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
320
|
+
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
321
|
+
const pageRows = yield rowLocators.all();
|
|
322
|
+
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
323
|
+
if (parallel) {
|
|
324
|
+
yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
325
|
+
if (stopped)
|
|
308
326
|
return;
|
|
309
|
-
dedupeKeys
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
dedupeKeys
|
|
327
|
+
if (dedupeKeys) {
|
|
328
|
+
const key = yield dedupeStrategy(row);
|
|
329
|
+
if (dedupeKeys.has(key))
|
|
330
|
+
return;
|
|
331
|
+
dedupeKeys.add(key);
|
|
332
|
+
}
|
|
333
|
+
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
334
|
+
})));
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
for (const row of smartRows) {
|
|
338
|
+
if (stopped)
|
|
339
|
+
break;
|
|
340
|
+
if (dedupeKeys) {
|
|
341
|
+
const key = yield dedupeStrategy(row);
|
|
342
|
+
if (dedupeKeys.has(key))
|
|
343
|
+
continue;
|
|
344
|
+
dedupeKeys.add(key);
|
|
345
|
+
}
|
|
346
|
+
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
323
347
|
}
|
|
324
|
-
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
325
348
|
}
|
|
349
|
+
rowIndex += smartRows.length;
|
|
350
|
+
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
351
|
+
break;
|
|
352
|
+
if (!(yield _advancePage(useBulk)))
|
|
353
|
+
break;
|
|
354
|
+
pagesScanned++;
|
|
326
355
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if (!(yield _advancePage()))
|
|
331
|
-
break;
|
|
332
|
-
pagesScanned++;
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
yield tracker.cleanup(rootLocator.page());
|
|
333
359
|
}
|
|
334
360
|
}),
|
|
335
361
|
map: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
336
|
-
var _a, _b, _c;
|
|
362
|
+
var _a, _b, _c, _d;
|
|
337
363
|
yield _autoInit();
|
|
338
364
|
const map = tableMapper.getMapSync();
|
|
339
365
|
const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
|
|
340
366
|
const dedupeStrategy = (_b = options.dedupe) !== null && _b !== void 0 ? _b : config.strategies.dedupe;
|
|
341
367
|
const dedupeKeys = dedupeStrategy ? new Set() : null;
|
|
342
368
|
const parallel = (_c = options.parallel) !== null && _c !== void 0 ? _c : true;
|
|
369
|
+
const useBulk = (_d = options.useBulkPagination) !== null && _d !== void 0 ? _d : false;
|
|
370
|
+
const tracker = new elementTracker_1.ElementTracker('map');
|
|
343
371
|
const results = [];
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
372
|
+
try {
|
|
373
|
+
let rowIndex = 0;
|
|
374
|
+
let stopped = false;
|
|
375
|
+
let pagesScanned = 1;
|
|
376
|
+
const stop = () => { stopped = true; };
|
|
377
|
+
while (!stopped) {
|
|
378
|
+
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
379
|
+
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
380
|
+
const pageRows = yield rowLocators.all();
|
|
381
|
+
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
382
|
+
if (parallel) {
|
|
383
|
+
const SKIP = Symbol('skip');
|
|
384
|
+
const pageResults = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
385
|
+
if (dedupeKeys) {
|
|
386
|
+
const key = yield dedupeStrategy(row);
|
|
387
|
+
if (dedupeKeys.has(key))
|
|
388
|
+
return SKIP;
|
|
389
|
+
dedupeKeys.add(key);
|
|
390
|
+
}
|
|
391
|
+
return callback({ row, rowIndex: row.rowIndex, stop });
|
|
392
|
+
})));
|
|
393
|
+
for (const r of pageResults) {
|
|
394
|
+
if (r !== SKIP)
|
|
395
|
+
results.push(r);
|
|
359
396
|
}
|
|
360
|
-
return callback({ row, rowIndex: row.rowIndex, stop });
|
|
361
|
-
})));
|
|
362
|
-
for (const r of pageResults) {
|
|
363
|
-
if (r !== SKIP)
|
|
364
|
-
results.push(r);
|
|
365
397
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
398
|
+
else {
|
|
399
|
+
for (const row of smartRows) {
|
|
400
|
+
if (stopped)
|
|
401
|
+
break;
|
|
402
|
+
if (dedupeKeys) {
|
|
403
|
+
const key = yield dedupeStrategy(row);
|
|
404
|
+
if (dedupeKeys.has(key))
|
|
405
|
+
continue;
|
|
406
|
+
dedupeKeys.add(key);
|
|
407
|
+
}
|
|
408
|
+
results.push(yield callback({ row, rowIndex: row.rowIndex, stop }));
|
|
376
409
|
}
|
|
377
|
-
results.push(yield callback({ row, rowIndex: row.rowIndex, stop }));
|
|
378
410
|
}
|
|
411
|
+
rowIndex += smartRows.length;
|
|
412
|
+
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
413
|
+
break;
|
|
414
|
+
if (!(yield _advancePage(useBulk)))
|
|
415
|
+
break;
|
|
416
|
+
pagesScanned++;
|
|
379
417
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (!(yield _advancePage()))
|
|
384
|
-
break;
|
|
385
|
-
pagesScanned++;
|
|
418
|
+
}
|
|
419
|
+
finally {
|
|
420
|
+
yield tracker.cleanup(rootLocator.page());
|
|
386
421
|
}
|
|
387
422
|
return results;
|
|
388
423
|
}),
|
|
389
424
|
filter: (predicate_1, ...args_1) => __awaiter(void 0, [predicate_1, ...args_1], void 0, function* (predicate, options = {}) {
|
|
390
|
-
var _a, _b, _c;
|
|
425
|
+
var _a, _b, _c, _d;
|
|
391
426
|
yield _autoInit();
|
|
392
427
|
const map = tableMapper.getMapSync();
|
|
393
428
|
const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
|
|
394
429
|
const dedupeStrategy = (_b = options.dedupe) !== null && _b !== void 0 ? _b : config.strategies.dedupe;
|
|
395
430
|
const dedupeKeys = dedupeStrategy ? new Set() : null;
|
|
396
431
|
const parallel = (_c = options.parallel) !== null && _c !== void 0 ? _c : false;
|
|
432
|
+
const useBulk = (_d = options.useBulkPagination) !== null && _d !== void 0 ? _d : false;
|
|
433
|
+
const tracker = new elementTracker_1.ElementTracker('filter');
|
|
397
434
|
const matched = [];
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
435
|
+
try {
|
|
436
|
+
let rowIndex = 0;
|
|
437
|
+
let stopped = false;
|
|
438
|
+
let pagesScanned = 1;
|
|
439
|
+
const stop = () => { stopped = true; };
|
|
440
|
+
while (!stopped) {
|
|
441
|
+
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
442
|
+
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
443
|
+
const pageRows = yield rowLocators.all();
|
|
444
|
+
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i, pagesScanned - 1));
|
|
445
|
+
if (parallel) {
|
|
446
|
+
const flags = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
447
|
+
if (dedupeKeys) {
|
|
448
|
+
const key = yield dedupeStrategy(row);
|
|
449
|
+
if (dedupeKeys.has(key))
|
|
450
|
+
return false;
|
|
451
|
+
dedupeKeys.add(key);
|
|
452
|
+
}
|
|
453
|
+
return predicate({ row, rowIndex: row.rowIndex, stop });
|
|
454
|
+
})));
|
|
455
|
+
smartRows.forEach((row, i) => { if (flags[i])
|
|
456
|
+
matched.push(row); });
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
for (const row of smartRows) {
|
|
460
|
+
if (stopped)
|
|
461
|
+
break;
|
|
462
|
+
if (dedupeKeys) {
|
|
463
|
+
const key = yield dedupeStrategy(row);
|
|
464
|
+
if (dedupeKeys.has(key))
|
|
465
|
+
continue;
|
|
466
|
+
dedupeKeys.add(key);
|
|
467
|
+
}
|
|
468
|
+
if (yield predicate({ row, rowIndex: row.rowIndex, stop })) {
|
|
469
|
+
matched.push(row);
|
|
470
|
+
}
|
|
430
471
|
}
|
|
431
472
|
}
|
|
473
|
+
rowIndex += smartRows.length;
|
|
474
|
+
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
475
|
+
break;
|
|
476
|
+
if (!(yield _advancePage(useBulk)))
|
|
477
|
+
break;
|
|
478
|
+
pagesScanned++;
|
|
432
479
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (!(yield _advancePage()))
|
|
437
|
-
break;
|
|
438
|
-
pagesScanned++;
|
|
480
|
+
}
|
|
481
|
+
finally {
|
|
482
|
+
yield tracker.cleanup(rootLocator.page());
|
|
439
483
|
}
|
|
440
484
|
return (0, smartRowArray_1.createSmartRowArray)(matched);
|
|
441
485
|
}),
|
|
442
|
-
|
|
486
|
+
generateConfig: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
443
487
|
const html = yield _getCleanHtml(rootLocator);
|
|
444
488
|
const separator = "=".repeat(50);
|
|
445
489
|
const content = `\n${separator} \nš¤ COPY INTO GEMINI / ChatGPT š¤\n${separator} \nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()} \nGenerate config for: \n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n${separator}\n`;
|
|
446
490
|
yield _handlePrompt('Smart Table Config', content);
|
|
447
491
|
}),
|
|
492
|
+
generateConfigPrompt: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
493
|
+
console.warn('ā ļø [playwright-smart-table] generateConfigPrompt() is deprecated and will be removed in v7.0.0. Please use generateConfig() instead.');
|
|
494
|
+
return result.generateConfig();
|
|
495
|
+
}),
|
|
448
496
|
};
|
|
449
497
|
finalTable = result;
|
|
450
498
|
return result;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PaginationPrimitives, TableContext } from '../types';
|
|
2
|
+
/** A single step in a navigation plan (e.g. "goNextBulk 3 times"). */
|
|
3
|
+
export type NavigationStep = {
|
|
4
|
+
type: 'goToPage';
|
|
5
|
+
pageIndex: number;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'goNextBulk';
|
|
8
|
+
count: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'goNext';
|
|
11
|
+
count: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'goPreviousBulk';
|
|
14
|
+
count: number;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'goPrevious';
|
|
17
|
+
count: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Plans an optimal path from currentPageIndex to targetPageIndex using available primitives.
|
|
21
|
+
* Prefers goToPage when present; otherwise uses bulk steps (goNextBulk / goPreviousBulk) then
|
|
22
|
+
* single steps (goNext / goPrevious). May choose to overshoot with bulk then step back when
|
|
23
|
+
* that reduces total primitive calls (e.g. page 3 ā 12 with bulk 10: goNextBulk once, goPrevious once).
|
|
24
|
+
*/
|
|
25
|
+
export declare function planNavigationPath(currentPageIndex: number, targetPageIndex: number, primitives: PaginationPrimitives): NavigationStep[];
|
|
26
|
+
/**
|
|
27
|
+
* Navigate to targetPageIndex when goToPage is available but may be "windowed"
|
|
28
|
+
* (e.g. only works for visible page links 6ā14). Tries goToPage(target); on false,
|
|
29
|
+
* steps once toward target (goNextBulk/goNext or goPreviousBulk/goPrevious), then retries.
|
|
30
|
+
* Example: from 3 to 38 with windowed goToPage ā goToPage(38) false, goNextBulk(), goToPage(38) false, ⦠goToPage(38) true.
|
|
31
|
+
*/
|
|
32
|
+
export declare function executeNavigationWithGoToPageRetry(targetPageIndex: number, primitives: PaginationPrimitives, context: TableContext, getCurrentPage: () => number, setCurrentPage: (n: number) => void): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Executes a navigation path by calling the corresponding primitives.
|
|
35
|
+
* Updates currentPageIndex via the provided setter as steps run.
|
|
36
|
+
*/
|
|
37
|
+
export declare function executeNavigationPath(path: NavigationStep[], primitives: PaginationPrimitives, context: TableContext, getCurrentPage: () => number, setCurrentPage: (n: number) => void): Promise<void>;
|