pervert-monkey 1.0.15 → 1.0.17

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 (51) hide show
  1. package/dist/core/pervertmonkey.core.es.d.ts +9 -8
  2. package/dist/core/pervertmonkey.core.es.js +57 -46
  3. package/dist/core/pervertmonkey.core.es.js.map +1 -1
  4. package/dist/core/pervertmonkey.core.umd.js +57 -46
  5. package/dist/core/pervertmonkey.core.umd.js.map +1 -1
  6. package/dist/userscripts/3hentai.user.js +9 -3
  7. package/dist/userscripts/camgirlfinder.user.js +2 -2
  8. package/dist/userscripts/camwhores.user.js +2 -2
  9. package/dist/userscripts/e-hentai.user.js +7 -6
  10. package/dist/userscripts/ebalka.user.js +7 -7
  11. package/dist/userscripts/eporner.user.js +5 -2
  12. package/dist/userscripts/erome.user.js +7 -11
  13. package/dist/userscripts/eroprofile.user.js +2 -2
  14. package/dist/userscripts/javhdporn.user.js +2 -2
  15. package/dist/userscripts/missav.user.js +2 -2
  16. package/dist/userscripts/motherless.user.js +3 -3
  17. package/dist/userscripts/namethatporn.user.js +4 -4
  18. package/dist/userscripts/nhentai.user.js +2 -2
  19. package/dist/userscripts/obmenvsem.user.js +3 -2
  20. package/dist/userscripts/pornhub.user.js +2 -2
  21. package/dist/userscripts/spankbang.user.js +5 -5
  22. package/dist/userscripts/thisvid.user.js +5 -5
  23. package/dist/userscripts/xhamster.user.js +6 -6
  24. package/dist/userscripts/xvideos.user.js +8 -8
  25. package/package.json +1 -1
  26. package/src/core/data-handler/data-filter-fn-defaults.ts +8 -8
  27. package/src/core/data-handler/data-filter-fn.ts +10 -8
  28. package/src/core/data-handler/data-filter.ts +10 -8
  29. package/src/core/data-handler/data-manager.ts +29 -15
  30. package/src/core/parsers/thumb-data-parser.ts +11 -4
  31. package/src/userscripts/scripts/3hentai.ts +4 -2
  32. package/src/userscripts/scripts/camgirlfinder.ts +1 -1
  33. package/src/userscripts/scripts/camwhores.ts +1 -1
  34. package/src/userscripts/scripts/e-hentai.ts +9 -7
  35. package/src/userscripts/scripts/ebalka.ts +6 -6
  36. package/src/userscripts/scripts/eporner.ts +4 -1
  37. package/src/userscripts/scripts/erome.ts +6 -12
  38. package/src/userscripts/scripts/eroprofile.ts +1 -1
  39. package/src/userscripts/scripts/javhdporn.ts +1 -1
  40. package/src/userscripts/scripts/missav.ts +1 -1
  41. package/src/userscripts/scripts/motherless.ts +4 -3
  42. package/src/userscripts/scripts/namethatporn.ts +3 -3
  43. package/src/userscripts/scripts/nhentai.ts +1 -1
  44. package/src/userscripts/scripts/obmenvsem.ts +6 -2
  45. package/src/userscripts/scripts/pornhub.ts +1 -1
  46. package/src/userscripts/scripts/spankbang.ts +4 -4
  47. package/src/userscripts/scripts/thisvid.ts +3 -3
  48. package/src/userscripts/scripts/xhamster.ts +5 -5
  49. package/src/userscripts/scripts/xvideos.ts +7 -7
  50. package/src/utils/dom/dom-observers.ts +3 -3
  51. package/src/utils/dom/index.ts +1 -1
@@ -26,13 +26,13 @@ export declare type DataElement = {
26
26
  export declare class DataFilter {
27
27
  private rules;
28
28
  filters: Map<string, () => DataFilterFnRendered>;
29
+ filterMapping: Record<string, string>;
29
30
  constructor(rules: Rules);
30
- static isFiltered(el: HTMLElement): boolean;
31
- applyCSSFilters(wrapper?: (cssRule: string) => string): void;
31
+ static isFiltered(e: HTMLElement): boolean;
32
+ createCssFilters(wrapper?: (cssRule: string) => string): void;
32
33
  customDataFilterFns: Record<string, DataFilterFnFrom<any>>;
33
34
  registerFilters(customFilters: (Record<string, DataFilterFnFrom<any>> | string)[]): void;
34
35
  registerFilter(customSelectorName: string): void;
35
- filterMapping: Record<string, string>;
36
36
  selectFilters(filters: {
37
37
  [key: string]: boolean;
38
38
  }): (() => DataFilterFnRendered)[];
@@ -43,7 +43,8 @@ declare class DataFilterFn<R> {
43
43
  deps: string[];
44
44
  name: string;
45
45
  $preDefine?: ((state: StoreState) => R) | undefined;
46
- private tag;
46
+ static prefix: string;
47
+ static setPrefix(name: string): string;
47
48
  constructor(handle: DataFilterFnHandle<R>, deps: string[] | undefined, name: string, $preDefine?: ((state: StoreState) => R) | undefined);
48
49
  static from<R>(options: DataFilterFnFrom<R>, name: string): DataFilterFn<R>;
49
50
  renderFn(state: StoreState): () => DataFilterFnRendered;
@@ -56,7 +57,7 @@ declare type DataFilterFnHandle<R> = (el: DataElement, state: StoreState, $preDe
56
57
  declare type DataFilterFnRendered = (v: DataElement) => DataFilterFnRenderedResult;
57
58
 
58
59
  declare type DataFilterFnRenderedResult = {
59
- tag: string;
60
+ name: string;
60
61
  condition: boolean;
61
62
  };
62
63
 
@@ -68,6 +69,8 @@ export declare class DataManager {
68
69
  dataFilter: DataFilter;
69
70
  constructor(rules: Rules, containerHomogenity?: Parameters<typeof checkHomogenity>[2] | undefined);
70
71
  applyFilters: (filters?: Record<string, boolean>, offset?: number) => Promise<void>;
72
+ layoutStylePaintEnabled: boolean;
73
+ private layoutStylePaint;
71
74
  filterAll: (offset?: number) => Promise<void>;
72
75
  parseData: (html: HTMLElement, container?: HTMLElement, removeDuplicates?: boolean, shouldLazify?: boolean) => void;
73
76
  sortBy<K extends keyof DataElement>(key: K, direction?: boolean): void;
@@ -380,8 +383,6 @@ export declare function parseUrl(s: HTMLAnchorElement | Location | URL | string)
380
383
 
381
384
  declare type Primitive = string | number | boolean;
382
385
 
383
- declare type PrimitiveString = 'boolean' | 'string' | 'number' | 'float' | 'duration';
384
-
385
386
  export declare function querySelectorLast<T extends Element = HTMLElement>(root: ParentNode | undefined, selector: string): T | undefined;
386
387
 
387
388
  export declare function querySelectorLastNumber(selector: string, e?: ParentNode): number;
@@ -472,7 +473,7 @@ export declare class ThumbDataParser {
472
473
  declare type ThumbDataSelector = {
473
474
  name: string;
474
475
  selector: string;
475
- type: PrimitiveString;
476
+ type: 'boolean' | 'string' | 'number' | 'float' | 'duration';
476
477
  };
477
478
 
478
479
  declare type ThumbDataSelectorsRaw = Record<string, string | Pick<ThumbDataSelector, 'selector' | 'type'>>;
@@ -11,21 +11,23 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
11
11
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
12
  var _i2, _n2, _t, _e2, _s2, _l2, _o2, _d, _p2, _g, _C_instances, r_fn, R_fn, b_fn, u_fn, m_fn, a_fn, P_fn, E_fn, S_fn, O_fn, k_fn, x_fn, h_fn, f_fn, T_fn, A_fn, y_fn, w_fn, c_fn, C_fn, _a, _i3, _n3, _t2, _e3, _s3, _l3, _b;
13
13
  import { GM_addStyle } from "vite-plugin-monkey/dist/client";
14
- class DataFilterFn {
14
+ const _DataFilterFn = class _DataFilterFn {
15
15
  constructor(handle, deps = [], name, $preDefine) {
16
- __publicField(this, "tag");
17
16
  this.handle = handle;
18
17
  this.deps = deps;
19
18
  this.name = name;
20
19
  this.$preDefine = $preDefine;
21
- this.tag = `filter-${name}`;
20
+ this.name = _DataFilterFn.setPrefix(name);
21
+ }
22
+ static setPrefix(name) {
23
+ return `${_DataFilterFn.prefix}${name}`;
22
24
  }
23
25
  static from(options, name) {
24
26
  if (typeof options === "function") {
25
27
  const deps = [name];
26
- return new DataFilterFn(options, deps, name);
28
+ return new _DataFilterFn(options, deps, name);
27
29
  }
28
- return new DataFilterFn(
30
+ return new _DataFilterFn(
29
31
  options.handle,
30
32
  options.deps,
31
33
  name,
@@ -33,20 +35,19 @@ class DataFilterFn {
33
35
  );
34
36
  }
35
37
  renderFn(state) {
36
- const tag = this.tag;
38
+ const name = this.name;
37
39
  return () => {
38
40
  var _a3;
39
41
  const preDefined = (_a3 = this.$preDefine) == null ? void 0 : _a3.call(this, state);
40
42
  return (a2) => {
41
43
  const condition = this.handle(a2, state, preDefined);
42
- return {
43
- condition,
44
- tag
45
- };
44
+ return { condition, name };
46
45
  };
47
46
  };
48
47
  }
49
- }
48
+ };
49
+ __publicField(_DataFilterFn, "prefix", "filter-");
50
+ let DataFilterFn = _DataFilterFn;
50
51
  function chunks(arr, size) {
51
52
  return Array.from(
52
53
  { length: Math.ceil(arr.length / size) },
@@ -117,10 +118,10 @@ function sanitizeStr(s) {
117
118
  }
118
119
  function waitForElementToAppear(parent, selector, callback) {
119
120
  const observer = new MutationObserver((_mutations) => {
120
- const el2 = parent.querySelector(selector);
121
- if (el2) {
121
+ const e = parent.querySelector(selector);
122
+ if (e) {
122
123
  observer.disconnect();
123
- callback(el2);
124
+ callback(e);
124
125
  }
125
126
  });
126
127
  observer.observe(document.body, { childList: true, subtree: true });
@@ -219,7 +220,7 @@ function removeClassesAndDataAttributes(element, keyword) {
219
220
  });
220
221
  }
221
222
  function getCommonParents(elements) {
222
- const parents = Array.from(elements).map((el2) => el2.parentElement).filter((parent) => parent !== null);
223
+ const parents = Array.from(elements).map((e) => e.parentElement).filter((parent) => parent !== null);
223
224
  return [...new Set(parents)];
224
225
  }
225
226
  function findNextSibling(e) {
@@ -468,9 +469,9 @@ function parseCssUrl(s) {
468
469
  function createTextFilter(filterName, dataPropName, positive) {
469
470
  const filterNameValue = `${filterName}Words`;
470
471
  return {
471
- handle(el2, state, searchFilter) {
472
+ handle(e, state, searchFilter) {
472
473
  if (!Object.hasOwn(state, filterName) || !state[filterName]) return false;
473
- return !(searchFilter == null ? void 0 : searchFilter(el2[dataPropName]));
474
+ return !(searchFilter == null ? void 0 : searchFilter(e[dataPropName]));
474
475
  },
475
476
  $preDefine: (state) => {
476
477
  const r = new RegexFilter(state[filterNameValue]);
@@ -481,9 +482,9 @@ function createTextFilter(filterName, dataPropName, positive) {
481
482
  };
482
483
  }
483
484
  const filterDuration = {
484
- handle(el2, state, notInRange) {
485
+ handle(e, state, notInRange) {
485
486
  if (!state.filterDuration) return false;
486
- return !!(notInRange == null ? void 0 : notInRange(el2.duration));
487
+ return !!(notInRange == null ? void 0 : notInRange(e.duration));
487
488
  },
488
489
  $preDefine: (state) => {
489
490
  const from = state.filterDurationFrom;
@@ -501,26 +502,27 @@ const defaultDataFilterFns = {
501
502
  filterInclude: createTextFilter("filterInclude", "title", true),
502
503
  filterUploaderExclude: createTextFilter("filterUploaderExclude", "uploader", false),
503
504
  filterUploaderInclude: createTextFilter("filterUploaderInclude", "uploader", true),
504
- filterHD: (el2, state) => state.filterHD && !el2.hd,
505
- filterNonHD: (el2, state) => state.filterNonHD && el2.hd,
506
- filterPrivate: (el2, state) => state.filterPrivate && el2.private,
507
- filterPublic: (el2, state) => state.filterPublic && !el2.private
505
+ filterHD: (e, state) => state.filterHD && !e.hd,
506
+ filterNonHD: (e, state) => state.filterNonHD && e.hd,
507
+ filterPrivate: (e, state) => state.filterPrivate && e.private,
508
+ filterPublic: (e, state) => state.filterPublic && !e.private
508
509
  };
509
510
  class DataFilter {
510
511
  constructor(rules) {
511
512
  __publicField(this, "filters", /* @__PURE__ */ new Map());
512
- __publicField(this, "customDataFilterFns", {});
513
513
  __publicField(this, "filterMapping", {});
514
+ __publicField(this, "customDataFilterFns", {});
514
515
  this.rules = rules;
515
516
  this.registerFilters(rules.customDataFilterFns);
516
- this.applyCSSFilters();
517
+ this.createCssFilters();
517
518
  }
518
- static isFiltered(el2) {
519
- return el2.className.includes("filter-");
519
+ static isFiltered(e) {
520
+ return e.className.includes(DataFilterFn.prefix);
520
521
  }
521
- applyCSSFilters(wrapper) {
522
+ createCssFilters(wrapper) {
522
523
  this.filters.forEach((_2, name) => {
523
- const cssRule = `.filter-${name} { display: none !important; }`;
524
+ const className = DataFilterFn.setPrefix(name);
525
+ const cssRule = `.${className} { display: none !important; }`;
524
526
  GM_addStyle(wrapper ? wrapper(cssRule) : cssRule);
525
527
  });
526
528
  }
@@ -533,12 +535,12 @@ class DataFilter {
533
535
  });
534
536
  }
535
537
  registerFilter(customSelectorName) {
536
- var _a3;
537
538
  const dataFilterFn = DataFilterFn.from(
538
539
  this.customDataFilterFns[customSelectorName],
539
540
  customSelectorName
540
541
  );
541
- (_a3 = [customSelectorName, ...dataFilterFn.deps]) == null ? void 0 : _a3.forEach((name) => {
542
+ dataFilterFn.deps.push(customSelectorName);
543
+ dataFilterFn.deps.forEach((name) => {
542
544
  Object.assign(this.filterMapping, { [name]: customSelectorName });
543
545
  });
544
546
  this.filters.set(customSelectorName, dataFilterFn.renderFn(this.rules.store.state));
@@ -568,8 +570,8 @@ class DataManager {
568
570
  finished = !!done;
569
571
  if (done) break;
570
572
  for (const f of filtersToApply) {
571
- const { tag, condition } = f()(value);
572
- updates.push({ e: value.element, tag, condition });
573
+ const { name, condition } = f()(value);
574
+ updates.push({ e: value.element, name, condition });
573
575
  }
574
576
  }
575
577
  if (!finished) {
@@ -580,13 +582,14 @@ class DataManager {
580
582
  }
581
583
  requestIdleCallback(runBatch);
582
584
  });
583
- const parents = new Set(updates.map((u) => u.e.parentElement));
585
+ const parents = [...new Set(updates.map((u) => u.e.parentElement))].filter(
586
+ (_2) => _2 !== null
587
+ );
584
588
  requestAnimationFrame(() => {
585
- const revertDisplayStyle = [...parents].map((p) => {
586
- const display = p == null ? void 0 : p.style.display;
587
- if (!display) return void 0;
589
+ const revertDisplayStyle = parents.map((p) => {
590
+ const display = p.style.display;
588
591
  p.style.display = "none";
589
- p.style.contain = "layout style paint";
592
+ this.layoutStylePaint(p);
590
593
  p.style.willChange = "contents";
591
594
  return () => {
592
595
  p.style.display = display;
@@ -596,13 +599,14 @@ class DataManager {
596
599
  };
597
600
  });
598
601
  updates.forEach((u) => {
599
- u.e.classList.toggle(u.tag, u.condition);
602
+ u.e.classList.toggle(u.name, u.condition);
600
603
  });
601
604
  revertDisplayStyle.forEach((f) => {
602
605
  f == null ? void 0 : f();
603
606
  });
604
607
  });
605
608
  });
609
+ __publicField(this, "layoutStylePaintEnabled", false);
606
610
  __publicField(this, "filterAll", async (offset) => {
607
611
  const keys = Array.from(this.dataFilter.filters.keys());
608
612
  const filters = Object.fromEntries(
@@ -616,10 +620,6 @@ class DataManager {
616
620
  const fragment = document.createDocumentFragment();
617
621
  const parent = container || this.rules.container;
618
622
  const homogenity = !!this.containerHomogenity;
619
- if (parent) {
620
- parent.style.contain = "layout style paint";
621
- parent.style.willChange = "contents";
622
- }
623
623
  for (const thumbElement of thumbs) {
624
624
  const url = this.rules.thumbDataParser.getUrl(thumbElement);
625
625
  if (!url || this.data.has(url) || parent !== container && (parent == null ? void 0 : parent.contains(thumbElement)) || homogenity && !checkHomogenity(
@@ -639,8 +639,13 @@ class DataManager {
639
639
  fragment.append(thumbElement);
640
640
  }
641
641
  this.filterAll(dataOffset).then(() => {
642
+ if (!parent) return;
643
+ parent.style.willChange = "contents";
642
644
  requestAnimationFrame(() => {
643
645
  parent == null ? void 0 : parent.appendChild(fragment);
646
+ requestAnimationFrame(() => {
647
+ parent.style.willChange = "auto";
648
+ });
644
649
  });
645
650
  });
646
651
  });
@@ -648,12 +653,16 @@ class DataManager {
648
653
  this.containerHomogenity = containerHomogenity;
649
654
  this.dataFilter = new DataFilter(this.rules);
650
655
  }
656
+ layoutStylePaint(e) {
657
+ if (!this.layoutStylePaintEnabled) return;
658
+ e.style.contain = "layout style paint";
659
+ }
651
660
  sortBy(key, direction = true) {
652
661
  if (this.data.size < 2) return;
653
662
  const elements = this.data.values().toArray().filter((e) => e.element.parentElement !== null).map((e) => e);
654
663
  const containers = new Set(elements.map((e) => e.element.parentElement));
655
664
  containers.forEach((c) => {
656
- c.style.contain = "layout style paint";
665
+ this.layoutStylePaint(c);
657
666
  c.style.willChange = "contents";
658
667
  });
659
668
  const elementsByContainers = /* @__PURE__ */ new Map();
@@ -3075,8 +3084,10 @@ class ThumbDataParser {
3075
3084
  }
3076
3085
  autoParseText(thumb) {
3077
3086
  var _a3;
3078
- const title = sanitizeStr(thumb.innerText);
3079
- const duration = timeToSeconds(((_a3 = title.match(/\d+m|\d+:\d+/)) == null ? void 0 : _a3[0]) || "");
3087
+ let title = sanitizeStr(thumb.innerText);
3088
+ const durationStr = ((_a3 = title.match(/(\d+:\d+:?\d+?)|\d+m/)) == null ? void 0 : _a3[0]) || "";
3089
+ const duration = timeToSeconds(durationStr);
3090
+ title = title.replaceAll(durationStr, "");
3080
3091
  return { title, duration };
3081
3092
  }
3082
3093
  getUrl(thumb) {