pervert-monkey 1.0.17 → 1.0.19

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 (56) hide show
  1. package/dist/core/pervertmonkey.core.es.d.ts +22 -19
  2. package/dist/core/pervertmonkey.core.es.js +148 -159
  3. package/dist/core/pervertmonkey.core.es.js.map +1 -1
  4. package/dist/core/pervertmonkey.core.umd.js +148 -159
  5. package/dist/core/pervertmonkey.core.umd.js.map +1 -1
  6. package/dist/test/test.user.js +10301 -0
  7. package/dist/userscripts/3hentai.user.js +2 -2
  8. package/dist/userscripts/camgirlfinder.user.js +2 -2
  9. package/dist/userscripts/camwhores.user.js +4 -5
  10. package/dist/userscripts/e-hentai.user.js +2 -2
  11. package/dist/userscripts/ebalka.user.js +7 -3
  12. package/dist/userscripts/eporner.user.js +2 -2
  13. package/dist/userscripts/erome.user.js +2 -2
  14. package/dist/userscripts/eroprofile.user.js +2 -2
  15. package/dist/userscripts/javhdporn.user.js +2 -2
  16. package/dist/userscripts/missav.user.js +3 -8
  17. package/dist/userscripts/motherless.user.js +2 -2
  18. package/dist/userscripts/namethatporn.user.js +2 -2
  19. package/dist/userscripts/nhentai.user.js +2 -2
  20. package/dist/userscripts/obmenvsem.user.js +3 -3
  21. package/dist/userscripts/pornhub.user.js +2 -2
  22. package/dist/userscripts/spankbang.user.js +3 -4
  23. package/dist/userscripts/thisvid.user.js +35 -30
  24. package/dist/userscripts/xhamster.user.js +3 -3
  25. package/dist/userscripts/xvideos.user.js +3 -3
  26. package/package.json +4 -4
  27. package/src/core/data-handler/data-filter.ts +4 -4
  28. package/src/core/data-handler/data-manager.ts +47 -115
  29. package/src/core/infinite-scroll/index.ts +8 -13
  30. package/src/core/parsers/thumb-data-parser.ts +4 -3
  31. package/src/core/parsers/thumbs-parser.ts +9 -10
  32. package/src/core/rules/index.ts +6 -7
  33. package/src/userscripts/index.ts +1 -1
  34. package/src/userscripts/scripts/3hentai.ts +1 -1
  35. package/src/userscripts/scripts/camgirlfinder.ts +1 -1
  36. package/src/userscripts/scripts/camwhores.ts +3 -4
  37. package/src/userscripts/scripts/e-hentai.ts +1 -1
  38. package/src/userscripts/scripts/ebalka.ts +10 -3
  39. package/src/userscripts/scripts/eporner.ts +1 -1
  40. package/src/userscripts/scripts/erome.ts +1 -1
  41. package/src/userscripts/scripts/eroprofile.ts +1 -1
  42. package/src/userscripts/scripts/javhdporn.ts +1 -1
  43. package/src/userscripts/scripts/missav.ts +2 -7
  44. package/src/userscripts/scripts/motherless.ts +1 -1
  45. package/src/userscripts/scripts/namethatporn.ts +1 -1
  46. package/src/userscripts/scripts/nhentai.ts +1 -2
  47. package/src/userscripts/scripts/obmenvsem.ts +2 -2
  48. package/src/userscripts/scripts/pornhub.ts +1 -1
  49. package/src/userscripts/scripts/spankbang.ts +1 -3
  50. package/src/userscripts/scripts/thisvid.ts +46 -38
  51. package/src/userscripts/scripts/xhamster.ts +2 -2
  52. package/src/userscripts/scripts/xvideos.ts +2 -2
  53. package/src/utils/dom/index.ts +23 -16
  54. package/src/utils/index.ts +4 -22
  55. package/src/utils/parsers/index.ts +1 -1
  56. package/src/utils/performance/index.ts +44 -0
@@ -16,6 +16,8 @@ export declare function chunks<T>(arr: T[], size: number): T[][];
16
16
 
17
17
  export declare function circularShift(n: number, c?: number, s?: number): number;
18
18
 
19
+ export declare function containMutation(container: HTMLElement, callback: () => void): void;
20
+
19
21
  export declare function copyAttributes<T extends Element = HTMLElement>(target: T, source: T): void;
20
22
 
21
23
  export declare type DataElement = {
@@ -26,7 +28,7 @@ export declare type DataElement = {
26
28
  export declare class DataFilter {
27
29
  private rules;
28
30
  filters: Map<string, () => DataFilterFnRendered>;
29
- filterMapping: Record<string, string>;
31
+ filterDepsMapping: Record<string, string>;
30
32
  constructor(rules: Rules);
31
33
  static isFiltered(e: HTMLElement): boolean;
32
34
  createCssFilters(wrapper?: (cssRule: string) => string): void;
@@ -68,11 +70,9 @@ export declare class DataManager {
68
70
  private lazyImgLoader;
69
71
  dataFilter: DataFilter;
70
72
  constructor(rules: Rules, containerHomogenity?: Parameters<typeof checkHomogenity>[2] | undefined);
71
- applyFilters: (filters?: Record<string, boolean>, offset?: number) => Promise<void>;
72
- layoutStylePaintEnabled: boolean;
73
- private layoutStylePaint;
74
- filterAll: (offset?: number) => Promise<void>;
75
- parseData: (html: HTMLElement, container?: HTMLElement, removeDuplicates?: boolean, shouldLazify?: boolean) => void;
73
+ applyFilters(filters?: Record<string, boolean>, offset?: number): Promise<void>;
74
+ filterAll(offset?: number): Promise<void>;
75
+ parseData(html: HTMLElement, container?: HTMLElement, removeDuplicates?: boolean, shouldLazify?: boolean): Promise<void>;
76
76
  sortBy<K extends keyof DataElement>(key: K, direction?: boolean): void;
77
77
  }
78
78
 
@@ -200,11 +200,11 @@ declare const DefaultScheme: [{
200
200
  }];
201
201
  }];
202
202
 
203
- export declare function downloader(options?: {
204
- append: string;
205
- after: string;
206
- button: string;
207
- cbBefore: () => void;
203
+ export declare function downloader(options: {
204
+ append?: string;
205
+ after?: string;
206
+ buttonHtml: string;
207
+ doBefore?: () => void;
208
208
  }): void;
209
209
 
210
210
  export declare function exterminateVideo(video: HTMLVideoElement): void;
@@ -235,12 +235,11 @@ declare type GeneratorResult = {
235
235
  offset: number;
236
236
  };
237
237
 
238
- export declare function getCommonParents(elements: HTMLCollection | HTMLElement[]): HTMLElement[];
238
+ export declare function getCommonParents<T extends HTMLElement>(elements: Iterable<T>): HTMLElement[];
239
239
 
240
240
  export declare function getPaginationStrategy(options: Partial<PaginationStrategy>): PaginationStrategy;
241
241
 
242
242
  export declare class InfiniteScroller {
243
- enabled: boolean;
244
243
  paginationOffset: number;
245
244
  rules: Rules;
246
245
  private observer?;
@@ -261,6 +260,8 @@ declare type InfiniteScrollerOptions = Pick<InfiniteScroller, 'rules'> & Partial
261
260
 
262
261
  export declare function instantiateTemplate(sourceSelector: string, attributeUpdates: Record<string, string>, contentUpdates: Record<string, string>): string;
263
262
 
263
+ export declare function irange(start?: number, step?: number): Generator<number, void, unknown>;
264
+
264
265
  declare type IScrollerSubject = {
265
266
  type: 'scroll';
266
267
  scroller: InfiniteScroller;
@@ -377,7 +378,7 @@ export declare function parseHtml(html: string): HTMLElement;
377
378
 
378
379
  export declare function parseIntegerOr(n: string | number, or: number): number;
379
380
 
380
- export declare function parseNumberWithLetter(str: string): number;
381
+ export declare function parseNumericAbbreviation(str: string): number;
381
382
 
382
383
  export declare function parseUrl(s: HTMLAnchorElement | Location | URL | string): URL;
383
384
 
@@ -387,6 +388,8 @@ export declare function querySelectorLast<T extends Element = HTMLElement>(root:
387
388
 
388
389
  export declare function querySelectorLastNumber(selector: string, e?: ParentNode): number;
389
390
 
391
+ export declare function querySelectorOrSelf<T extends Element = HTMLElement>(element: T, selector: string): T | null;
392
+
390
393
  export declare function querySelectorText(e: ParentNode, selector?: string): string;
391
394
 
392
395
  export declare function range(size: number, start?: number, step?: number): number[];
@@ -414,7 +417,7 @@ export declare class Rules {
414
417
  containerSelectorLast?: string;
415
418
  get container(): HTMLElement;
416
419
  intersectionObservableSelector?: string;
417
- get intersectionObservable(): "" | Element | null | undefined;
420
+ get intersectionObservable(): HTMLElement | null | undefined;
418
421
  get observable(): HTMLElement;
419
422
  paginationStrategyOptions: Partial<PaginationStrategy>;
420
423
  paginationStrategy: PaginationStrategy;
@@ -445,6 +448,8 @@ export declare class Rules {
445
448
  constructor(options: Partial<Rules>);
446
449
  }
447
450
 
451
+ export declare function runIdleJob<T>(iterator: Iterator<T>, job: (v: T) => void): Promise<unknown>;
452
+
448
453
  export declare function sanitizeStr(s: string): string;
449
454
 
450
455
  declare type SchemeKeys = JabroniTypes.ExtractValuesByKey<typeof DefaultScheme, 'title'>;
@@ -495,13 +500,11 @@ export declare class ThumbImgParser {
495
500
  }
496
501
 
497
502
  export declare class ThumbsParser {
498
- containerSelector: string;
499
503
  selector: string;
500
504
  strategy: 'default' | 'auto';
501
505
  transform?: (thumb: HTMLElement) => void;
502
- static create(options: Partial<Pick<ThumbsParser, "selector" | "strategy" | "transform">> | undefined, containerSelector: string): ThumbsParser & Partial<Pick<ThumbsParser, "selector" | "strategy" | "transform">>;
503
- constructor(containerSelector: string);
504
- getThumbs(html: HTMLElement): HTMLElement[];
506
+ static create(options?: Partial<Pick<ThumbsParser, 'selector' | 'strategy' | 'transform'>>): ThumbsParser & Partial<Pick<ThumbsParser, "selector" | "strategy" | "transform">>;
507
+ getThumbs(container: HTMLElement): HTMLElement[];
505
508
  }
506
509
 
507
510
  export declare class Tick {
@@ -172,9 +172,19 @@ function watchDomChangesWithThrottle(element, callback, throttle = 1e3, times =
172
172
  observer.observe(element, options);
173
173
  return observer;
174
174
  }
175
+ function querySelectorOrSelf(element, selector) {
176
+ var _a3;
177
+ if ((_a3 = element.matches) == null ? void 0 : _a3.call(element, selector)) {
178
+ return element;
179
+ }
180
+ return element.querySelector(selector);
181
+ }
175
182
  function querySelectorLast(root = document, selector) {
176
183
  const nodes = root.querySelectorAll(selector);
177
- return nodes.length > 0 ? nodes[nodes.length - 1] : void 0;
184
+ if (nodes.length < 1) {
185
+ return querySelectorOrSelf(root, selector) || void 0;
186
+ }
187
+ return nodes[nodes.length - 1];
178
188
  }
179
189
  function querySelectorLastNumber(selector, e = document) {
180
190
  var _a3;
@@ -184,7 +194,7 @@ function querySelectorLastNumber(selector, e = document) {
184
194
  function querySelectorText(e, selector) {
185
195
  var _a3;
186
196
  if (typeof selector !== "string") return "";
187
- const text = ((_a3 = e.querySelector(selector)) == null ? void 0 : _a3.innerText) || "";
197
+ const text = ((_a3 = querySelectorOrSelf(e, selector)) == null ? void 0 : _a3.innerText) || "";
188
198
  return sanitizeStr(text);
189
199
  }
190
200
  function parseHtml(html) {
@@ -220,8 +230,7 @@ function removeClassesAndDataAttributes(element, keyword) {
220
230
  });
221
231
  }
222
232
  function getCommonParents(elements) {
223
- const parents = Array.from(elements).map((e) => e.parentElement).filter((parent) => parent !== null);
224
- return [...new Set(parents)];
233
+ return Map.groupBy(elements, (e) => e.parentElement).keys().filter((e) => e !== null).toArray();
225
234
  }
226
235
  function findNextSibling(e) {
227
236
  if (e.nextElementSibling) return e.nextElementSibling;
@@ -264,15 +273,15 @@ function exterminateVideo(video) {
264
273
  video.load();
265
274
  video.remove();
266
275
  }
267
- function downloader(options = { append: "", after: "", button: "", cbBefore: () => {
268
- } }) {
276
+ function downloader(options) {
269
277
  var _a3, _b2;
270
- const btn = parseHtml(options.button);
278
+ const btn = parseHtml(options.buttonHtml);
271
279
  if (options.append) (_a3 = document.querySelector(options.append)) == null ? void 0 : _a3.append(btn);
272
280
  if (options.after) (_b2 = document.querySelector(options.after)) == null ? void 0 : _b2.after(btn);
273
- btn.addEventListener("click", (e) => {
281
+ btn == null ? void 0 : btn.addEventListener("click", (e) => {
282
+ var _a4;
274
283
  e.preventDefault();
275
- if (options.cbBefore) options.cbBefore();
284
+ (_a4 = options.doBefore) == null ? void 0 : _a4.call(options);
276
285
  waitForElementToAppear(document.body, "video", (video) => {
277
286
  window.location.href = video.getAttribute("src");
278
287
  });
@@ -431,7 +440,7 @@ function parseIntegerOr(n, or2) {
431
440
  const num = Number(n);
432
441
  return Number.isSafeInteger(num) ? num : or2;
433
442
  }
434
- function parseNumberWithLetter(str) {
443
+ function parseNumericAbbreviation(str) {
435
444
  var _a3;
436
445
  const multipliers = { k: 1e3, m: 1e6 };
437
446
  const match = str.trim().match(/([\d., ]+)(\w)?/);
@@ -466,6 +475,42 @@ function parseDataParams(str) {
466
475
  function parseCssUrl(s) {
467
476
  return s.replace(/url\("|"\).*/g, "");
468
477
  }
478
+ function runIdleJob(iterator2, job) {
479
+ return new Promise((resolve) => {
480
+ const scheduler = window.requestIdleCallback || ((cb) => {
481
+ return setTimeout(() => {
482
+ cb({
483
+ didTimeout: true,
484
+ timeRemaining: () => 50
485
+ });
486
+ }, 1);
487
+ });
488
+ function runBatch(deadline) {
489
+ while (deadline.timeRemaining() > 0) {
490
+ const { value, done } = iterator2.next();
491
+ if (done) {
492
+ resolve(true);
493
+ return;
494
+ }
495
+ job(value);
496
+ }
497
+ scheduler(runBatch);
498
+ }
499
+ scheduler(runBatch);
500
+ });
501
+ }
502
+ function containMutation(container, callback) {
503
+ container.style.contain = "content";
504
+ try {
505
+ callback();
506
+ } finally {
507
+ requestAnimationFrame(() => {
508
+ requestAnimationFrame(() => {
509
+ container.style.contain = "none";
510
+ });
511
+ });
512
+ }
513
+ }
469
514
  function createTextFilter(filterName, dataPropName, positive) {
470
515
  const filterNameValue = `${filterName}Words`;
471
516
  return {
@@ -510,7 +555,7 @@ const defaultDataFilterFns = {
510
555
  class DataFilter {
511
556
  constructor(rules) {
512
557
  __publicField(this, "filters", /* @__PURE__ */ new Map());
513
- __publicField(this, "filterMapping", {});
558
+ __publicField(this, "filterDepsMapping", {});
514
559
  __publicField(this, "customDataFilterFns", {});
515
560
  this.rules = rules;
516
561
  this.registerFilters(rules.customDataFilterFns);
@@ -541,12 +586,12 @@ class DataFilter {
541
586
  );
542
587
  dataFilterFn.deps.push(customSelectorName);
543
588
  dataFilterFn.deps.forEach((name) => {
544
- Object.assign(this.filterMapping, { [name]: customSelectorName });
589
+ Object.assign(this.filterDepsMapping, { [name]: customSelectorName });
545
590
  });
546
591
  this.filters.set(customSelectorName, dataFilterFn.renderFn(this.rules.store.state));
547
592
  }
548
593
  selectFilters(filters) {
549
- const selectedFilters = Object.keys(filters).filter((k2) => k2 in this.filterMapping).map((k2) => this.filterMapping[k2]).map((k2) => this.filters.get(k2));
594
+ const selectedFilters = Object.keys(filters).filter((k2) => k2 in this.filterDepsMapping).map((k2) => this.filterDepsMapping[k2]).map((k2) => this.filters.get(k2));
550
595
  return selectedFilters;
551
596
  }
552
597
  }
@@ -557,136 +602,82 @@ class DataManager {
557
602
  (target) => !DataFilter.isFiltered(target)
558
603
  ));
559
604
  __publicField(this, "dataFilter");
560
- __publicField(this, "applyFilters", async (filters = {}, offset = 0) => {
561
- const filtersToApply = this.dataFilter.selectFilters(filters);
562
- if (filtersToApply.length === 0) return;
563
- const iterator2 = this.data.values().drop(offset);
564
- let finished = false;
565
- const updates = [];
566
- await new Promise((resolve) => {
567
- function runBatch(deadline) {
568
- while (deadline.timeRemaining() > 0) {
569
- const { value, done } = iterator2.next();
570
- finished = !!done;
571
- if (done) break;
572
- for (const f of filtersToApply) {
573
- const { name, condition } = f()(value);
574
- updates.push({ e: value.element, name, condition });
575
- }
576
- }
577
- if (!finished) {
578
- requestIdleCallback(runBatch);
579
- } else {
580
- resolve(true);
581
- }
582
- }
583
- requestIdleCallback(runBatch);
584
- });
585
- const parents = [...new Set(updates.map((u) => u.e.parentElement))].filter(
586
- (_2) => _2 !== null
587
- );
588
- requestAnimationFrame(() => {
589
- const revertDisplayStyle = parents.map((p) => {
590
- const display = p.style.display;
591
- p.style.display = "none";
592
- this.layoutStylePaint(p);
593
- p.style.willChange = "contents";
594
- return () => {
595
- p.style.display = display;
596
- requestAnimationFrame(() => {
597
- p.style.willChange = "auto";
598
- });
599
- };
600
- });
601
- updates.forEach((u) => {
605
+ this.rules = rules;
606
+ this.containerHomogenity = containerHomogenity;
607
+ this.dataFilter = new DataFilter(this.rules);
608
+ }
609
+ async applyFilters(filters = {}, offset = 0) {
610
+ const filtersToApply = this.dataFilter.selectFilters(filters);
611
+ if (filtersToApply.length === 0) return;
612
+ const iterator2 = this.data.values().drop(offset);
613
+ const updates = [];
614
+ await runIdleJob(iterator2, (v2) => {
615
+ for (const f of filtersToApply) {
616
+ const { name, condition } = f()(v2);
617
+ updates.push({ e: v2.element, name, condition });
618
+ }
619
+ });
620
+ const parents = Map.groupBy(updates, (u) => u.e.parentElement);
621
+ parents.forEach((v2, parent) => {
622
+ const f = () => {
623
+ v2.forEach((u) => {
602
624
  u.e.classList.toggle(u.name, u.condition);
603
625
  });
604
- revertDisplayStyle.forEach((f) => {
605
- f == null ? void 0 : f();
606
- });
607
- });
608
- });
609
- __publicField(this, "layoutStylePaintEnabled", false);
610
- __publicField(this, "filterAll", async (offset) => {
611
- const keys = Array.from(this.dataFilter.filters.keys());
612
- const filters = Object.fromEntries(
613
- keys.map((k2) => [k2, this.rules.store.state[k2]])
614
- );
615
- await this.applyFilters(filters, offset);
616
- });
617
- __publicField(this, "parseData", (html, container, removeDuplicates = false, shouldLazify = true) => {
618
- const thumbs = this.rules.thumbsParser.getThumbs(html);
619
- const dataOffset = this.data.size;
620
- const fragment = document.createDocumentFragment();
621
- const parent = container || this.rules.container;
622
- const homogenity = !!this.containerHomogenity;
623
- for (const thumbElement of thumbs) {
624
- const url = this.rules.thumbDataParser.getUrl(thumbElement);
625
- if (!url || this.data.has(url) || parent !== container && (parent == null ? void 0 : parent.contains(thumbElement)) || homogenity && !checkHomogenity(
626
- parent,
627
- thumbElement.parentElement,
628
- this.containerHomogenity
629
- )) {
630
- if (removeDuplicates) thumbElement.remove();
631
- continue;
632
- }
633
- const data = this.rules.thumbDataParser.getThumbData(thumbElement);
634
- this.data.set(url, { element: thumbElement, ...data });
635
- if (shouldLazify) {
636
- const { img, imgSrc } = this.rules.thumbImgParser.getImgData(thumbElement);
637
- this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
638
- }
639
- fragment.append(thumbElement);
640
- }
641
- this.filterAll(dataOffset).then(() => {
642
- if (!parent) return;
643
- parent.style.willChange = "contents";
626
+ };
627
+ if (!parent) {
628
+ f();
629
+ } else {
644
630
  requestAnimationFrame(() => {
645
- parent == null ? void 0 : parent.appendChild(fragment);
646
- requestAnimationFrame(() => {
647
- parent.style.willChange = "auto";
648
- });
631
+ containMutation(parent, f);
649
632
  });
650
- });
633
+ }
651
634
  });
652
- this.rules = rules;
653
- this.containerHomogenity = containerHomogenity;
654
- this.dataFilter = new DataFilter(this.rules);
655
635
  }
656
- layoutStylePaint(e) {
657
- if (!this.layoutStylePaintEnabled) return;
658
- e.style.contain = "layout style paint";
636
+ async filterAll(offset) {
637
+ const keys = Array.from(this.dataFilter.filters.keys());
638
+ const filters = Object.fromEntries(
639
+ keys.map((k2) => [k2, this.rules.store.state[k2]])
640
+ );
641
+ await this.applyFilters(filters, offset);
642
+ }
643
+ async parseData(html, container, removeDuplicates = false, shouldLazify = true) {
644
+ const thumbs = this.rules.thumbsParser.getThumbs(html);
645
+ const dataOffset = this.data.size;
646
+ const fragment = document.createDocumentFragment();
647
+ const parent = container || this.rules.container;
648
+ const homogenity = !!this.containerHomogenity;
649
+ for (const thumbElement of thumbs) {
650
+ const url = this.rules.thumbDataParser.getUrl(thumbElement);
651
+ const isHomogenic = homogenity && !checkHomogenity(
652
+ parent,
653
+ thumbElement.parentElement,
654
+ this.containerHomogenity
655
+ );
656
+ if (!url || this.data.has(url) || parent !== container && (parent == null ? void 0 : parent.contains(thumbElement)) || isHomogenic) {
657
+ if (removeDuplicates) thumbElement.remove();
658
+ continue;
659
+ }
660
+ const data = this.rules.thumbDataParser.getThumbData(thumbElement);
661
+ this.data.set(url, { element: thumbElement, ...data });
662
+ if (shouldLazify) {
663
+ const { img, imgSrc } = this.rules.thumbImgParser.getImgData(thumbElement);
664
+ this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
665
+ }
666
+ fragment.append(thumbElement);
667
+ }
668
+ await this.filterAll(dataOffset);
669
+ if (!parent) return;
670
+ containMutation(parent, () => parent == null ? void 0 : parent.appendChild(fragment));
659
671
  }
660
672
  sortBy(key, direction = true) {
661
673
  if (this.data.size < 2) return;
662
- const elements = this.data.values().toArray().filter((e) => e.element.parentElement !== null).map((e) => e);
663
- const containers = new Set(elements.map((e) => e.element.parentElement));
664
- containers.forEach((c) => {
665
- this.layoutStylePaint(c);
666
- c.style.willChange = "contents";
667
- });
668
- const elementsByContainers = /* @__PURE__ */ new Map();
669
- containers.forEach((c) => {
670
- elementsByContainers.set(c, []);
671
- });
672
- elements.forEach((e) => {
673
- const parent = e.element.parentElement;
674
- const container = elementsByContainers.get(parent);
675
- container == null ? void 0 : container.push(e);
676
- });
674
+ const ds2 = this.data.values().toArray().filter((e) => e.element.parentElement !== null);
675
+ const byContainers = Map.groupBy(ds2, (e) => e.element.parentElement);
677
676
  const dir = direction ? -1 : 1;
678
- for (const [container, items] of elementsByContainers) {
677
+ for (const [container, items] of byContainers) {
679
678
  items.sort((a2, b2) => (a2[key] - b2[key]) * dir);
680
- const domNodes = items.map((e) => e.element);
681
- const display = container.style.display;
682
- container.style.display = "none";
683
- container.replaceChildren(...domNodes);
684
- requestAnimationFrame(() => {
685
- container.style.display = display;
686
- requestAnimationFrame(() => {
687
- container.style.willChange = "auto";
688
- });
689
- });
679
+ const children = items.map((e) => e.element);
680
+ containMutation(container, () => container.replaceChildren(...children));
690
681
  }
691
682
  }
692
683
  }
@@ -1966,14 +1957,13 @@ function takeUntil(notifier) {
1966
1957
  }
1967
1958
  class InfiniteScroller {
1968
1959
  constructor(options) {
1969
- __publicField(this, "enabled", true);
1970
1960
  __publicField(this, "paginationOffset", 1);
1971
1961
  __publicField(this, "rules");
1972
1962
  __publicField(this, "observer");
1973
1963
  __publicField(this, "paginationGenerator");
1974
1964
  __publicField(this, "subject", new Subject());
1975
1965
  __publicField(this, "generatorConsumer", async () => {
1976
- if (!this.enabled) return false;
1966
+ if (!this.rules.store.state.infiniteScrollEnabled) return true;
1977
1967
  const { value, done } = await this.paginationGenerator.next();
1978
1968
  if (done) return false;
1979
1969
  const { url, offset } = value;
@@ -2023,10 +2013,8 @@ class InfiniteScroller {
2023
2013
  }
2024
2014
  async doScroll(url, offset) {
2025
2015
  const page = await this.getPaginationData(url);
2026
- const prevScrollPos = document.documentElement.scrollTop;
2027
2016
  this.paginationOffset = Math.max(this.paginationOffset, offset);
2028
2017
  this.subject.next({ type: "scroll", scroller: this, page });
2029
- window.scrollTo(0, prevScrollPos);
2030
2018
  if (this.rules.store.state.writeHistory) {
2031
2019
  history.replaceState({}, "", url);
2032
2020
  }
@@ -2041,19 +2029,18 @@ class InfiniteScroller {
2041
2029
  }
2042
2030
  }
2043
2031
  static create(rules) {
2044
- const enabled = rules.store.state.infiniteScrollEnabled;
2045
2032
  rules.store.state.$paginationLast = rules.paginationStrategy.getPaginationLast();
2046
- const infiniteScroller = new InfiniteScroller({ enabled, rules });
2033
+ const infiniteScroller = new InfiniteScroller({ rules });
2047
2034
  rules.store.state.$paginationOffset = infiniteScroller.paginationOffset;
2048
2035
  infiniteScroller.subject.subscribe((x2) => {
2049
2036
  if (x2.type === "scroll") {
2050
2037
  rules.store.state.$paginationOffset = x2.scroller.paginationOffset;
2051
- rules.dataManager.parseData(x2.page);
2038
+ const prevScrollPos = document.documentElement.scrollTop;
2039
+ rules.dataManager.parseData(x2.page).then(() => {
2040
+ window.scrollTo(0, prevScrollPos);
2041
+ });
2052
2042
  }
2053
2043
  });
2054
- rules.store.stateSubject.subscribe(() => {
2055
- infiniteScroller.enabled = rules.store.state.infiniteScrollEnabled;
2056
- });
2057
2044
  return infiniteScroller;
2058
2045
  }
2059
2046
  }
@@ -3112,7 +3099,7 @@ class ThumbDataParser {
3112
3099
  getThumbDataWith(thumb, { type, selector }) {
3113
3100
  var _a3;
3114
3101
  if (type === "boolean") {
3115
- return !!thumb.querySelector(selector);
3102
+ return !!querySelectorOrSelf(thumb, selector);
3116
3103
  }
3117
3104
  if (type === "string") {
3118
3105
  return sanitizeStr(((_a3 = querySelectorLast(thumb, selector)) == null ? void 0 : _a3.innerText) || "");
@@ -3122,7 +3109,7 @@ class ThumbDataParser {
3122
3109
  }
3123
3110
  if (type === "float") {
3124
3111
  const value = querySelectorText(thumb, selector);
3125
- return parseNumberWithLetter(value);
3112
+ return parseNumericAbbreviation(value);
3126
3113
  }
3127
3114
  return Number.parseInt(querySelectorText(thumb, selector));
3128
3115
  }
@@ -3191,24 +3178,21 @@ class ThumbImgParser {
3191
3178
  }
3192
3179
  }
3193
3180
  class ThumbsParser {
3194
- constructor(containerSelector) {
3181
+ constructor() {
3195
3182
  __publicField(this, "selector", ".thumb");
3196
3183
  __publicField(this, "strategy", "default");
3197
3184
  __publicField(this, "transform");
3198
- this.containerSelector = containerSelector;
3199
3185
  }
3200
- static create(options = {}, containerSelector) {
3201
- return Object.assign(new ThumbsParser(containerSelector), options);
3186
+ static create(options = {}) {
3187
+ return Object.assign(new ThumbsParser(), options);
3202
3188
  }
3203
- getThumbs(html) {
3204
- if (!html) return [];
3205
- let thumbs;
3189
+ getThumbs(container) {
3190
+ if (!container) return [];
3206
3191
  if (this.strategy === "auto") {
3207
3192
  if (typeof this.selector !== "string") return [];
3208
- const container = html.querySelector(this.containerSelector);
3209
- thumbs = [...(container == null ? void 0 : container.children) || []];
3193
+ return [...(container == null ? void 0 : container.children) || []];
3210
3194
  }
3211
- thumbs = Array.from(html.querySelectorAll(this.selector));
3195
+ const thumbs = Array.from(container.querySelectorAll(this.selector));
3212
3196
  if (typeof this.transform === "function") {
3213
3197
  thumbs.forEach(this.transform);
3214
3198
  }
@@ -9908,7 +9892,7 @@ class Rules {
9908
9892
  Object.assign(this, options);
9909
9893
  this.thumbDataParser = ThumbDataParser.create(this.thumb);
9910
9894
  this.thumbImgParser = ThumbImgParser.create(this.thumbImg);
9911
- this.thumbsParser = ThumbsParser.create(this.thumbs, this.containerSelector);
9895
+ this.thumbsParser = ThumbsParser.create(this.thumbs);
9912
9896
  this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
9913
9897
  this.store = this.createStore();
9914
9898
  this.gui = this.createGui();
@@ -9919,15 +9903,16 @@ class Rules {
9919
9903
  }
9920
9904
  get container() {
9921
9905
  if (typeof this.containerSelectorLast === "string") {
9922
- return querySelectorLast(document, this.containerSelectorLast);
9906
+ return querySelectorLast(document.body, this.containerSelectorLast);
9923
9907
  }
9924
9908
  if (typeof this.containerSelector === "string") {
9925
- return document.querySelector(this.containerSelector);
9909
+ return querySelectorOrSelf(document.body, this.containerSelector);
9926
9910
  }
9927
9911
  return this.containerSelector();
9928
9912
  }
9929
9913
  get intersectionObservable() {
9930
- return this.intersectionObservableSelector && document.querySelector(this.intersectionObservableSelector);
9914
+ if (!this.intersectionObservableSelector) return void 0;
9915
+ return document.querySelector(this.intersectionObservableSelector);
9931
9916
  }
9932
9917
  get observable() {
9933
9918
  return this.intersectionObservable || this.paginationStrategy.getPaginationElement();
@@ -10024,6 +10009,7 @@ export {
10024
10009
  checkHomogenity,
10025
10010
  chunks,
10026
10011
  circularShift,
10012
+ containMutation,
10027
10013
  copyAttributes,
10028
10014
  downloader,
10029
10015
  exterminateVideo,
@@ -10036,20 +10022,23 @@ export {
10036
10022
  getCommonParents,
10037
10023
  getPaginationStrategy,
10038
10024
  instantiateTemplate,
10025
+ irange,
10039
10026
  memoize,
10040
10027
  objectToFormData,
10041
10028
  parseCssUrl,
10042
10029
  parseDataParams,
10043
10030
  parseHtml,
10044
10031
  parseIntegerOr,
10045
- parseNumberWithLetter,
10032
+ parseNumericAbbreviation,
10046
10033
  parseUrl,
10047
10034
  querySelectorLast,
10048
10035
  querySelectorLastNumber,
10036
+ querySelectorOrSelf,
10049
10037
  querySelectorText,
10050
10038
  range,
10051
10039
  removeClassesAndDataAttributes,
10052
10040
  replaceElementTag,
10041
+ runIdleJob,
10053
10042
  sanitizeStr,
10054
10043
  splitWith,
10055
10044
  timeToSeconds,