pervert-monkey 1.0.15 → 1.0.18
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/dist/core/pervertmonkey.core.es.d.ts +23 -16
- package/dist/core/pervertmonkey.core.es.js +157 -153
- package/dist/core/pervertmonkey.core.es.js.map +1 -1
- package/dist/core/pervertmonkey.core.umd.js +157 -153
- package/dist/core/pervertmonkey.core.umd.js.map +1 -1
- package/dist/userscripts/3hentai.user.js +10 -4
- package/dist/userscripts/camgirlfinder.user.js +2 -2
- package/dist/userscripts/camwhores.user.js +4 -5
- package/dist/userscripts/e-hentai.user.js +7 -6
- package/dist/userscripts/ebalka.user.js +12 -8
- package/dist/userscripts/eporner.user.js +5 -2
- package/dist/userscripts/erome.user.js +7 -11
- package/dist/userscripts/eroprofile.user.js +2 -2
- package/dist/userscripts/javhdporn.user.js +2 -2
- package/dist/userscripts/missav.user.js +3 -8
- package/dist/userscripts/motherless.user.js +3 -3
- package/dist/userscripts/namethatporn.user.js +4 -4
- package/dist/userscripts/nhentai.user.js +2 -2
- package/dist/userscripts/obmenvsem.user.js +3 -2
- package/dist/userscripts/pornhub.user.js +2 -2
- package/dist/userscripts/spankbang.user.js +6 -7
- package/dist/userscripts/thisvid.user.js +7 -8
- package/dist/userscripts/xhamster.user.js +6 -6
- package/dist/userscripts/xvideos.user.js +8 -8
- package/package.json +1 -1
- package/src/core/data-handler/data-filter-fn-defaults.ts +8 -8
- package/src/core/data-handler/data-filter-fn.ts +10 -8
- package/src/core/data-handler/data-filter.ts +10 -8
- package/src/core/data-handler/data-manager.ts +52 -106
- package/src/core/infinite-scroll/index.ts +6 -4
- package/src/core/parsers/thumb-data-parser.ts +11 -4
- package/src/userscripts/index.ts +1 -1
- package/src/userscripts/scripts/3hentai.ts +5 -3
- package/src/userscripts/scripts/camgirlfinder.ts +1 -1
- package/src/userscripts/scripts/camwhores.ts +3 -4
- package/src/userscripts/scripts/e-hentai.ts +9 -7
- package/src/userscripts/scripts/ebalka.ts +15 -8
- package/src/userscripts/scripts/eporner.ts +4 -1
- package/src/userscripts/scripts/erome.ts +6 -12
- package/src/userscripts/scripts/eroprofile.ts +1 -1
- package/src/userscripts/scripts/javhdporn.ts +1 -1
- package/src/userscripts/scripts/missav.ts +2 -7
- package/src/userscripts/scripts/motherless.ts +4 -3
- package/src/userscripts/scripts/namethatporn.ts +3 -3
- package/src/userscripts/scripts/nhentai.ts +1 -1
- package/src/userscripts/scripts/obmenvsem.ts +6 -2
- package/src/userscripts/scripts/pornhub.ts +1 -1
- package/src/userscripts/scripts/spankbang.ts +4 -6
- package/src/userscripts/scripts/thisvid.ts +6 -6
- package/src/userscripts/scripts/xhamster.ts +5 -5
- package/src/userscripts/scripts/xvideos.ts +7 -7
- package/src/utils/dom/dom-observers.ts +3 -3
- package/src/utils/dom/index.ts +10 -7
- package/src/utils/index.ts +4 -22
- 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,13 +28,13 @@ export declare type DataElement = {
|
|
|
26
28
|
export declare class DataFilter {
|
|
27
29
|
private rules;
|
|
28
30
|
filters: Map<string, () => DataFilterFnRendered>;
|
|
31
|
+
filterMapping: Record<string, string>;
|
|
29
32
|
constructor(rules: Rules);
|
|
30
|
-
static isFiltered(
|
|
31
|
-
|
|
33
|
+
static isFiltered(e: HTMLElement): boolean;
|
|
34
|
+
createCssFilters(wrapper?: (cssRule: string) => string): void;
|
|
32
35
|
customDataFilterFns: Record<string, DataFilterFnFrom<any>>;
|
|
33
36
|
registerFilters(customFilters: (Record<string, DataFilterFnFrom<any>> | string)[]): void;
|
|
34
37
|
registerFilter(customSelectorName: string): void;
|
|
35
|
-
filterMapping: Record<string, string>;
|
|
36
38
|
selectFilters(filters: {
|
|
37
39
|
[key: string]: boolean;
|
|
38
40
|
}): (() => DataFilterFnRendered)[];
|
|
@@ -43,7 +45,8 @@ declare class DataFilterFn<R> {
|
|
|
43
45
|
deps: string[];
|
|
44
46
|
name: string;
|
|
45
47
|
$preDefine?: ((state: StoreState) => R) | undefined;
|
|
46
|
-
|
|
48
|
+
static prefix: string;
|
|
49
|
+
static setPrefix(name: string): string;
|
|
47
50
|
constructor(handle: DataFilterFnHandle<R>, deps: string[] | undefined, name: string, $preDefine?: ((state: StoreState) => R) | undefined);
|
|
48
51
|
static from<R>(options: DataFilterFnFrom<R>, name: string): DataFilterFn<R>;
|
|
49
52
|
renderFn(state: StoreState): () => DataFilterFnRendered;
|
|
@@ -56,7 +59,7 @@ declare type DataFilterFnHandle<R> = (el: DataElement, state: StoreState, $preDe
|
|
|
56
59
|
declare type DataFilterFnRendered = (v: DataElement) => DataFilterFnRenderedResult;
|
|
57
60
|
|
|
58
61
|
declare type DataFilterFnRenderedResult = {
|
|
59
|
-
|
|
62
|
+
name: string;
|
|
60
63
|
condition: boolean;
|
|
61
64
|
};
|
|
62
65
|
|
|
@@ -67,9 +70,9 @@ export declare class DataManager {
|
|
|
67
70
|
private lazyImgLoader;
|
|
68
71
|
dataFilter: DataFilter;
|
|
69
72
|
constructor(rules: Rules, containerHomogenity?: Parameters<typeof checkHomogenity>[2] | undefined);
|
|
70
|
-
applyFilters
|
|
71
|
-
filterAll
|
|
72
|
-
parseData
|
|
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>;
|
|
73
76
|
sortBy<K extends keyof DataElement>(key: K, direction?: boolean): void;
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -197,11 +200,11 @@ declare const DefaultScheme: [{
|
|
|
197
200
|
}];
|
|
198
201
|
}];
|
|
199
202
|
|
|
200
|
-
export declare function downloader(options
|
|
201
|
-
append
|
|
202
|
-
after
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
export declare function downloader(options: {
|
|
204
|
+
append?: string;
|
|
205
|
+
after?: string;
|
|
206
|
+
buttonHtml: string;
|
|
207
|
+
doBefore?: () => void;
|
|
205
208
|
}): void;
|
|
206
209
|
|
|
207
210
|
export declare function exterminateVideo(video: HTMLVideoElement): void;
|
|
@@ -220,6 +223,8 @@ export declare function fetchWith<T extends JSON | string | HTMLElement>(input:
|
|
|
220
223
|
|
|
221
224
|
export declare function findNextSibling<T extends Element = HTMLElement>(e: T): Element | null;
|
|
222
225
|
|
|
226
|
+
export declare function findSelfOrChild<T extends HTMLElement>(element: T, selector: string): T | null;
|
|
227
|
+
|
|
223
228
|
/**
|
|
224
229
|
* Converts a duration string (e.g., "1h 22min 3sec") to HH:MM:SS format.
|
|
225
230
|
* @param timeStr - The duration string to format.
|
|
@@ -258,6 +263,8 @@ declare type InfiniteScrollerOptions = Pick<InfiniteScroller, 'rules'> & Partial
|
|
|
258
263
|
|
|
259
264
|
export declare function instantiateTemplate(sourceSelector: string, attributeUpdates: Record<string, string>, contentUpdates: Record<string, string>): string;
|
|
260
265
|
|
|
266
|
+
export declare function irange(start?: number, step?: number): Generator<number, void, unknown>;
|
|
267
|
+
|
|
261
268
|
declare type IScrollerSubject = {
|
|
262
269
|
type: 'scroll';
|
|
263
270
|
scroller: InfiniteScroller;
|
|
@@ -380,8 +387,6 @@ export declare function parseUrl(s: HTMLAnchorElement | Location | URL | string)
|
|
|
380
387
|
|
|
381
388
|
declare type Primitive = string | number | boolean;
|
|
382
389
|
|
|
383
|
-
declare type PrimitiveString = 'boolean' | 'string' | 'number' | 'float' | 'duration';
|
|
384
|
-
|
|
385
390
|
export declare function querySelectorLast<T extends Element = HTMLElement>(root: ParentNode | undefined, selector: string): T | undefined;
|
|
386
391
|
|
|
387
392
|
export declare function querySelectorLastNumber(selector: string, e?: ParentNode): number;
|
|
@@ -444,6 +449,8 @@ export declare class Rules {
|
|
|
444
449
|
constructor(options: Partial<Rules>);
|
|
445
450
|
}
|
|
446
451
|
|
|
452
|
+
export declare function runIdleJob<T>(iterator: Iterator<T>, job: (v: T) => void): Promise<unknown>;
|
|
453
|
+
|
|
447
454
|
export declare function sanitizeStr(s: string): string;
|
|
448
455
|
|
|
449
456
|
declare type SchemeKeys = JabroniTypes.ExtractValuesByKey<typeof DefaultScheme, 'title'>;
|
|
@@ -472,7 +479,7 @@ export declare class ThumbDataParser {
|
|
|
472
479
|
declare type ThumbDataSelector = {
|
|
473
480
|
name: string;
|
|
474
481
|
selector: string;
|
|
475
|
-
type:
|
|
482
|
+
type: 'boolean' | 'string' | 'number' | 'float' | 'duration';
|
|
476
483
|
};
|
|
477
484
|
|
|
478
485
|
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
|
|
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.
|
|
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
|
|
28
|
+
return new _DataFilterFn(options, deps, name);
|
|
27
29
|
}
|
|
28
|
-
return new
|
|
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
|
|
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
|
|
121
|
-
if (
|
|
121
|
+
const e = parent.querySelector(selector);
|
|
122
|
+
if (e) {
|
|
122
123
|
observer.disconnect();
|
|
123
|
-
callback(
|
|
124
|
+
callback(e);
|
|
124
125
|
}
|
|
125
126
|
});
|
|
126
127
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
@@ -171,6 +172,12 @@ function watchDomChangesWithThrottle(element, callback, throttle = 1e3, times =
|
|
|
171
172
|
observer.observe(element, options);
|
|
172
173
|
return observer;
|
|
173
174
|
}
|
|
175
|
+
function findSelfOrChild(element, selector) {
|
|
176
|
+
if (element.matches(selector)) {
|
|
177
|
+
return element;
|
|
178
|
+
}
|
|
179
|
+
return element.querySelector(selector);
|
|
180
|
+
}
|
|
174
181
|
function querySelectorLast(root = document, selector) {
|
|
175
182
|
const nodes = root.querySelectorAll(selector);
|
|
176
183
|
return nodes.length > 0 ? nodes[nodes.length - 1] : void 0;
|
|
@@ -219,7 +226,7 @@ function removeClassesAndDataAttributes(element, keyword) {
|
|
|
219
226
|
});
|
|
220
227
|
}
|
|
221
228
|
function getCommonParents(elements) {
|
|
222
|
-
const parents = Array.from(elements).map((
|
|
229
|
+
const parents = Array.from(elements).map((e) => e.parentElement).filter((parent) => parent !== null);
|
|
223
230
|
return [...new Set(parents)];
|
|
224
231
|
}
|
|
225
232
|
function findNextSibling(e) {
|
|
@@ -263,15 +270,15 @@ function exterminateVideo(video) {
|
|
|
263
270
|
video.load();
|
|
264
271
|
video.remove();
|
|
265
272
|
}
|
|
266
|
-
function downloader(options
|
|
267
|
-
} }) {
|
|
273
|
+
function downloader(options) {
|
|
268
274
|
var _a3, _b2;
|
|
269
|
-
const btn = parseHtml(options.
|
|
275
|
+
const btn = parseHtml(options.buttonHtml);
|
|
270
276
|
if (options.append) (_a3 = document.querySelector(options.append)) == null ? void 0 : _a3.append(btn);
|
|
271
277
|
if (options.after) (_b2 = document.querySelector(options.after)) == null ? void 0 : _b2.after(btn);
|
|
272
|
-
btn.addEventListener("click", (e) => {
|
|
278
|
+
btn == null ? void 0 : btn.addEventListener("click", (e) => {
|
|
279
|
+
var _a4;
|
|
273
280
|
e.preventDefault();
|
|
274
|
-
|
|
281
|
+
(_a4 = options.doBefore) == null ? void 0 : _a4.call(options);
|
|
275
282
|
waitForElementToAppear(document.body, "video", (video) => {
|
|
276
283
|
window.location.href = video.getAttribute("src");
|
|
277
284
|
});
|
|
@@ -465,12 +472,48 @@ function parseDataParams(str) {
|
|
|
465
472
|
function parseCssUrl(s) {
|
|
466
473
|
return s.replace(/url\("|"\).*/g, "");
|
|
467
474
|
}
|
|
475
|
+
function runIdleJob(iterator2, job) {
|
|
476
|
+
return new Promise((resolve) => {
|
|
477
|
+
const scheduler = window.requestIdleCallback || ((cb) => {
|
|
478
|
+
return setTimeout(() => {
|
|
479
|
+
cb({
|
|
480
|
+
didTimeout: true,
|
|
481
|
+
timeRemaining: () => 50
|
|
482
|
+
});
|
|
483
|
+
}, 1);
|
|
484
|
+
});
|
|
485
|
+
function runBatch(deadline) {
|
|
486
|
+
while (deadline.timeRemaining() > 0) {
|
|
487
|
+
const { value, done } = iterator2.next();
|
|
488
|
+
if (done) {
|
|
489
|
+
resolve(true);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
job(value);
|
|
493
|
+
}
|
|
494
|
+
scheduler(runBatch);
|
|
495
|
+
}
|
|
496
|
+
scheduler(runBatch);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
function containMutation(container, callback) {
|
|
500
|
+
container.style.contain = "content";
|
|
501
|
+
try {
|
|
502
|
+
callback();
|
|
503
|
+
} finally {
|
|
504
|
+
requestAnimationFrame(() => {
|
|
505
|
+
requestAnimationFrame(() => {
|
|
506
|
+
container.style.contain = "none";
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
468
511
|
function createTextFilter(filterName, dataPropName, positive) {
|
|
469
512
|
const filterNameValue = `${filterName}Words`;
|
|
470
513
|
return {
|
|
471
|
-
handle(
|
|
514
|
+
handle(e, state, searchFilter) {
|
|
472
515
|
if (!Object.hasOwn(state, filterName) || !state[filterName]) return false;
|
|
473
|
-
return !(searchFilter == null ? void 0 : searchFilter(
|
|
516
|
+
return !(searchFilter == null ? void 0 : searchFilter(e[dataPropName]));
|
|
474
517
|
},
|
|
475
518
|
$preDefine: (state) => {
|
|
476
519
|
const r = new RegexFilter(state[filterNameValue]);
|
|
@@ -481,9 +524,9 @@ function createTextFilter(filterName, dataPropName, positive) {
|
|
|
481
524
|
};
|
|
482
525
|
}
|
|
483
526
|
const filterDuration = {
|
|
484
|
-
handle(
|
|
527
|
+
handle(e, state, notInRange) {
|
|
485
528
|
if (!state.filterDuration) return false;
|
|
486
|
-
return !!(notInRange == null ? void 0 : notInRange(
|
|
529
|
+
return !!(notInRange == null ? void 0 : notInRange(e.duration));
|
|
487
530
|
},
|
|
488
531
|
$preDefine: (state) => {
|
|
489
532
|
const from = state.filterDurationFrom;
|
|
@@ -501,26 +544,27 @@ const defaultDataFilterFns = {
|
|
|
501
544
|
filterInclude: createTextFilter("filterInclude", "title", true),
|
|
502
545
|
filterUploaderExclude: createTextFilter("filterUploaderExclude", "uploader", false),
|
|
503
546
|
filterUploaderInclude: createTextFilter("filterUploaderInclude", "uploader", true),
|
|
504
|
-
filterHD: (
|
|
505
|
-
filterNonHD: (
|
|
506
|
-
filterPrivate: (
|
|
507
|
-
filterPublic: (
|
|
547
|
+
filterHD: (e, state) => state.filterHD && !e.hd,
|
|
548
|
+
filterNonHD: (e, state) => state.filterNonHD && e.hd,
|
|
549
|
+
filterPrivate: (e, state) => state.filterPrivate && e.private,
|
|
550
|
+
filterPublic: (e, state) => state.filterPublic && !e.private
|
|
508
551
|
};
|
|
509
552
|
class DataFilter {
|
|
510
553
|
constructor(rules) {
|
|
511
554
|
__publicField(this, "filters", /* @__PURE__ */ new Map());
|
|
512
|
-
__publicField(this, "customDataFilterFns", {});
|
|
513
555
|
__publicField(this, "filterMapping", {});
|
|
556
|
+
__publicField(this, "customDataFilterFns", {});
|
|
514
557
|
this.rules = rules;
|
|
515
558
|
this.registerFilters(rules.customDataFilterFns);
|
|
516
|
-
this.
|
|
559
|
+
this.createCssFilters();
|
|
517
560
|
}
|
|
518
|
-
static isFiltered(
|
|
519
|
-
return
|
|
561
|
+
static isFiltered(e) {
|
|
562
|
+
return e.className.includes(DataFilterFn.prefix);
|
|
520
563
|
}
|
|
521
|
-
|
|
564
|
+
createCssFilters(wrapper) {
|
|
522
565
|
this.filters.forEach((_2, name) => {
|
|
523
|
-
const
|
|
566
|
+
const className = DataFilterFn.setPrefix(name);
|
|
567
|
+
const cssRule = `.${className} { display: none !important; }`;
|
|
524
568
|
GM_addStyle(wrapper ? wrapper(cssRule) : cssRule);
|
|
525
569
|
});
|
|
526
570
|
}
|
|
@@ -533,12 +577,12 @@ class DataFilter {
|
|
|
533
577
|
});
|
|
534
578
|
}
|
|
535
579
|
registerFilter(customSelectorName) {
|
|
536
|
-
var _a3;
|
|
537
580
|
const dataFilterFn = DataFilterFn.from(
|
|
538
581
|
this.customDataFilterFns[customSelectorName],
|
|
539
582
|
customSelectorName
|
|
540
583
|
);
|
|
541
|
-
|
|
584
|
+
dataFilterFn.deps.push(customSelectorName);
|
|
585
|
+
dataFilterFn.deps.forEach((name) => {
|
|
542
586
|
Object.assign(this.filterMapping, { [name]: customSelectorName });
|
|
543
587
|
});
|
|
544
588
|
this.filters.set(customSelectorName, dataFilterFn.renderFn(this.rules.store.state));
|
|
@@ -555,129 +599,82 @@ class DataManager {
|
|
|
555
599
|
(target) => !DataFilter.isFiltered(target)
|
|
556
600
|
));
|
|
557
601
|
__publicField(this, "dataFilter");
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
resolve(true);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
requestIdleCallback(runBatch);
|
|
582
|
-
});
|
|
583
|
-
const parents = new Set(updates.map((u) => u.e.parentElement));
|
|
584
|
-
requestAnimationFrame(() => {
|
|
585
|
-
const revertDisplayStyle = [...parents].map((p) => {
|
|
586
|
-
const display = p == null ? void 0 : p.style.display;
|
|
587
|
-
if (!display) return void 0;
|
|
588
|
-
p.style.display = "none";
|
|
589
|
-
p.style.contain = "layout style paint";
|
|
590
|
-
p.style.willChange = "contents";
|
|
591
|
-
return () => {
|
|
592
|
-
p.style.display = display;
|
|
593
|
-
requestAnimationFrame(() => {
|
|
594
|
-
p.style.willChange = "auto";
|
|
595
|
-
});
|
|
596
|
-
};
|
|
597
|
-
});
|
|
598
|
-
updates.forEach((u) => {
|
|
599
|
-
u.e.classList.toggle(u.tag, u.condition);
|
|
602
|
+
this.rules = rules;
|
|
603
|
+
this.containerHomogenity = containerHomogenity;
|
|
604
|
+
this.dataFilter = new DataFilter(this.rules);
|
|
605
|
+
}
|
|
606
|
+
async applyFilters(filters = {}, offset = 0) {
|
|
607
|
+
const filtersToApply = this.dataFilter.selectFilters(filters);
|
|
608
|
+
if (filtersToApply.length === 0) return;
|
|
609
|
+
const iterator2 = this.data.values().drop(offset);
|
|
610
|
+
const updates = [];
|
|
611
|
+
await runIdleJob(iterator2, (v2) => {
|
|
612
|
+
for (const f of filtersToApply) {
|
|
613
|
+
const { name, condition } = f()(v2);
|
|
614
|
+
updates.push({ e: v2.element, name, condition });
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
const parents = Map.groupBy(updates, (u) => u.e.parentElement);
|
|
618
|
+
parents.forEach((v2, parent) => {
|
|
619
|
+
const f = () => {
|
|
620
|
+
v2.forEach((u) => {
|
|
621
|
+
u.e.classList.toggle(u.name, u.condition);
|
|
600
622
|
});
|
|
601
|
-
|
|
602
|
-
|
|
623
|
+
};
|
|
624
|
+
if (!parent) {
|
|
625
|
+
f();
|
|
626
|
+
} else {
|
|
627
|
+
requestAnimationFrame(() => {
|
|
628
|
+
containMutation(parent, f);
|
|
603
629
|
});
|
|
604
|
-
}
|
|
630
|
+
}
|
|
605
631
|
});
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
632
|
+
}
|
|
633
|
+
async filterAll(offset) {
|
|
634
|
+
const keys = Array.from(this.dataFilter.filters.keys());
|
|
635
|
+
const filters = Object.fromEntries(
|
|
636
|
+
keys.map((k2) => [k2, this.rules.store.state[k2]])
|
|
637
|
+
);
|
|
638
|
+
await this.applyFilters(filters, offset);
|
|
639
|
+
}
|
|
640
|
+
async parseData(html, container, removeDuplicates = false, shouldLazify = true) {
|
|
641
|
+
const thumbs = this.rules.thumbsParser.getThumbs(html);
|
|
642
|
+
const dataOffset = this.data.size;
|
|
643
|
+
const fragment = document.createDocumentFragment();
|
|
644
|
+
const parent = container || this.rules.container;
|
|
645
|
+
const homogenity = !!this.containerHomogenity;
|
|
646
|
+
for (const thumbElement of thumbs) {
|
|
647
|
+
const url = this.rules.thumbDataParser.getUrl(thumbElement);
|
|
648
|
+
const isHomogenic = homogenity && !checkHomogenity(
|
|
649
|
+
parent,
|
|
650
|
+
thumbElement.parentElement,
|
|
651
|
+
this.containerHomogenity
|
|
610
652
|
);
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
const thumbs = this.rules.thumbsParser.getThumbs(html);
|
|
615
|
-
const dataOffset = this.data.size;
|
|
616
|
-
const fragment = document.createDocumentFragment();
|
|
617
|
-
const parent = container || this.rules.container;
|
|
618
|
-
const homogenity = !!this.containerHomogenity;
|
|
619
|
-
if (parent) {
|
|
620
|
-
parent.style.contain = "layout style paint";
|
|
621
|
-
parent.style.willChange = "contents";
|
|
653
|
+
if (!url || this.data.has(url) || parent !== container && (parent == null ? void 0 : parent.contains(thumbElement)) || isHomogenic) {
|
|
654
|
+
if (removeDuplicates) thumbElement.remove();
|
|
655
|
+
continue;
|
|
622
656
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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);
|
|
657
|
+
const data = this.rules.thumbDataParser.getThumbData(thumbElement);
|
|
658
|
+
this.data.set(url, { element: thumbElement, ...data });
|
|
659
|
+
if (shouldLazify) {
|
|
660
|
+
const { img, imgSrc } = this.rules.thumbImgParser.getImgData(thumbElement);
|
|
661
|
+
this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
|
|
640
662
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
});
|
|
647
|
-
this.rules = rules;
|
|
648
|
-
this.containerHomogenity = containerHomogenity;
|
|
649
|
-
this.dataFilter = new DataFilter(this.rules);
|
|
663
|
+
fragment.append(thumbElement);
|
|
664
|
+
}
|
|
665
|
+
await this.filterAll(dataOffset);
|
|
666
|
+
if (!parent) return;
|
|
667
|
+
containMutation(parent, () => parent == null ? void 0 : parent.appendChild(fragment));
|
|
650
668
|
}
|
|
651
669
|
sortBy(key, direction = true) {
|
|
652
670
|
if (this.data.size < 2) return;
|
|
653
|
-
const
|
|
654
|
-
const
|
|
655
|
-
containers.forEach((c) => {
|
|
656
|
-
c.style.contain = "layout style paint";
|
|
657
|
-
c.style.willChange = "contents";
|
|
658
|
-
});
|
|
659
|
-
const elementsByContainers = /* @__PURE__ */ new Map();
|
|
660
|
-
containers.forEach((c) => {
|
|
661
|
-
elementsByContainers.set(c, []);
|
|
662
|
-
});
|
|
663
|
-
elements.forEach((e) => {
|
|
664
|
-
const parent = e.element.parentElement;
|
|
665
|
-
const container = elementsByContainers.get(parent);
|
|
666
|
-
container == null ? void 0 : container.push(e);
|
|
667
|
-
});
|
|
671
|
+
const ds2 = this.data.values().toArray().filter((e) => e.element.parentElement !== null);
|
|
672
|
+
const byContainers = Map.groupBy(ds2, (e) => e.element.parentElement);
|
|
668
673
|
const dir = direction ? -1 : 1;
|
|
669
|
-
for (const [container, items] of
|
|
674
|
+
for (const [container, items] of byContainers) {
|
|
670
675
|
items.sort((a2, b2) => (a2[key] - b2[key]) * dir);
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
container.style.display = "none";
|
|
674
|
-
container.replaceChildren(...domNodes);
|
|
675
|
-
requestAnimationFrame(() => {
|
|
676
|
-
container.style.display = display;
|
|
677
|
-
requestAnimationFrame(() => {
|
|
678
|
-
container.style.willChange = "auto";
|
|
679
|
-
});
|
|
680
|
-
});
|
|
676
|
+
const children = items.map((e) => e.element);
|
|
677
|
+
containMutation(container, () => container.replaceChildren(...children));
|
|
681
678
|
}
|
|
682
679
|
}
|
|
683
680
|
}
|
|
@@ -2014,10 +2011,8 @@ class InfiniteScroller {
|
|
|
2014
2011
|
}
|
|
2015
2012
|
async doScroll(url, offset) {
|
|
2016
2013
|
const page = await this.getPaginationData(url);
|
|
2017
|
-
const prevScrollPos = document.documentElement.scrollTop;
|
|
2018
2014
|
this.paginationOffset = Math.max(this.paginationOffset, offset);
|
|
2019
2015
|
this.subject.next({ type: "scroll", scroller: this, page });
|
|
2020
|
-
window.scrollTo(0, prevScrollPos);
|
|
2021
2016
|
if (this.rules.store.state.writeHistory) {
|
|
2022
2017
|
history.replaceState({}, "", url);
|
|
2023
2018
|
}
|
|
@@ -2039,7 +2034,10 @@ class InfiniteScroller {
|
|
|
2039
2034
|
infiniteScroller.subject.subscribe((x2) => {
|
|
2040
2035
|
if (x2.type === "scroll") {
|
|
2041
2036
|
rules.store.state.$paginationOffset = x2.scroller.paginationOffset;
|
|
2042
|
-
|
|
2037
|
+
const prevScrollPos = document.documentElement.scrollTop;
|
|
2038
|
+
rules.dataManager.parseData(x2.page).then(() => {
|
|
2039
|
+
window.scrollTo(0, prevScrollPos);
|
|
2040
|
+
});
|
|
2043
2041
|
}
|
|
2044
2042
|
});
|
|
2045
2043
|
rules.store.stateSubject.subscribe(() => {
|
|
@@ -3075,8 +3073,10 @@ class ThumbDataParser {
|
|
|
3075
3073
|
}
|
|
3076
3074
|
autoParseText(thumb) {
|
|
3077
3075
|
var _a3;
|
|
3078
|
-
|
|
3079
|
-
const
|
|
3076
|
+
let title = sanitizeStr(thumb.innerText);
|
|
3077
|
+
const durationStr = ((_a3 = title.match(/(\d+:\d+:?\d+?)|\d+m/)) == null ? void 0 : _a3[0]) || "";
|
|
3078
|
+
const duration = timeToSeconds(durationStr);
|
|
3079
|
+
title = title.replaceAll(durationStr, "");
|
|
3080
3080
|
return { title, duration };
|
|
3081
3081
|
}
|
|
3082
3082
|
getUrl(thumb) {
|
|
@@ -10013,6 +10013,7 @@ export {
|
|
|
10013
10013
|
checkHomogenity,
|
|
10014
10014
|
chunks,
|
|
10015
10015
|
circularShift,
|
|
10016
|
+
containMutation,
|
|
10016
10017
|
copyAttributes,
|
|
10017
10018
|
downloader,
|
|
10018
10019
|
exterminateVideo,
|
|
@@ -10021,10 +10022,12 @@ export {
|
|
|
10021
10022
|
fetchText,
|
|
10022
10023
|
fetchWith,
|
|
10023
10024
|
findNextSibling,
|
|
10025
|
+
findSelfOrChild,
|
|
10024
10026
|
formatTimeToHHMMSS,
|
|
10025
10027
|
getCommonParents,
|
|
10026
10028
|
getPaginationStrategy,
|
|
10027
10029
|
instantiateTemplate,
|
|
10030
|
+
irange,
|
|
10028
10031
|
memoize,
|
|
10029
10032
|
objectToFormData,
|
|
10030
10033
|
parseCssUrl,
|
|
@@ -10039,6 +10042,7 @@ export {
|
|
|
10039
10042
|
range,
|
|
10040
10043
|
removeClassesAndDataAttributes,
|
|
10041
10044
|
replaceElementTag,
|
|
10045
|
+
runIdleJob,
|
|
10042
10046
|
sanitizeStr,
|
|
10043
10047
|
splitWith,
|
|
10044
10048
|
timeToSeconds,
|