pervert-monkey 1.0.0 → 1.0.1
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 +0 -3
- package/dist/core/pervertmonkey.core.es.d.ts +4 -4
- package/dist/core/pervertmonkey.core.es.js +24 -1
- package/dist/core/pervertmonkey.core.es.js.map +1 -1
- package/dist/core/pervertmonkey.core.umd.js +24 -1
- package/dist/core/pervertmonkey.core.umd.js.map +1 -1
- package/dist/userscripts/3hentai.user.js +1045 -1049
- package/dist/userscripts/camgirlfinder.user.js +38 -42
- package/dist/userscripts/camwhores.user.js +1429 -1433
- package/dist/userscripts/e-hentai.user.js +1077 -1081
- package/dist/userscripts/ebalka.user.js +1092 -1096
- package/dist/userscripts/eporner.user.js +1129 -1133
- package/dist/userscripts/erome.user.js +1109 -1113
- package/dist/userscripts/eroprofile.user.js +1062 -1066
- package/dist/userscripts/javhdporn.user.js +1046 -1050
- package/dist/userscripts/missav.user.js +1047 -1051
- package/dist/userscripts/motherless.user.js +1223 -1227
- package/dist/userscripts/namethatporn.user.js +1083 -1087
- package/dist/userscripts/nhentai.user.js +1123 -1127
- package/dist/userscripts/pornhub.user.js +1065 -1069
- package/dist/userscripts/spankbang.user.js +1097 -1101
- package/dist/userscripts/thisvid.user.js +2660 -0
- package/dist/userscripts/xhamster.user.js +1224 -1228
- package/dist/userscripts/xvideos.user.js +1116 -1120
- package/package.json +9 -9
- package/src/core/index.ts +4 -0
- package/src/index.ts +2 -42
- package/src/userscripts/scripts/3hentai.ts +1 -1
- package/src/userscripts/scripts/camwhores.ts +8 -9
- package/src/userscripts/scripts/e-hentai.ts +2 -2
- package/src/userscripts/scripts/ebalka.ts +2 -3
- package/src/userscripts/scripts/eporner.ts +2 -2
- package/src/userscripts/scripts/erome.ts +1 -1
- package/src/userscripts/scripts/eroprofile.ts +1 -1
- package/src/userscripts/scripts/javhdporn.ts +1 -1
- package/src/userscripts/scripts/missav.ts +1 -1
- package/src/userscripts/scripts/motherless.ts +2 -4
- package/src/userscripts/scripts/namethatporn.ts +1 -1
- package/src/userscripts/scripts/nhentai.ts +2 -2
- package/src/userscripts/scripts/pornhub.ts +1 -1
- package/src/userscripts/scripts/spankbang.ts +4 -5
- package/src/userscripts/scripts/xhamster.ts +5 -5
- package/src/userscripts/scripts/xvideos.ts +2 -3
- package/src/utils/index.ts +39 -0
- package/src/vite-env.d.ts +1 -1
- package/src/userscripts/scripts/thisvid.ts +0 -716
|
@@ -21,1162 +21,1158 @@
|
|
|
21
21
|
// @run-at document-idle
|
|
22
22
|
// ==/UserScript==
|
|
23
23
|
|
|
24
|
-
(function () {
|
|
24
|
+
(function (jabroniOutfit) {
|
|
25
25
|
'use strict';
|
|
26
26
|
|
|
27
|
-
(
|
|
27
|
+
var _GM_addStyle = (() => typeof GM_addStyle != "undefined" ? GM_addStyle : undefined)();
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
function memoize(fn) {
|
|
30
|
+
const cache = new Map();
|
|
31
|
+
const memoizedFunction = ((...args) => {
|
|
32
|
+
const key = JSON.stringify(args);
|
|
33
|
+
if (cache.has(key)) {
|
|
34
|
+
return cache.get(key);
|
|
35
|
+
}
|
|
36
|
+
const result = fn(...args);
|
|
37
|
+
cache.set(key, result);
|
|
38
|
+
return result;
|
|
39
|
+
});
|
|
40
|
+
return memoizedFunction;
|
|
41
|
+
}
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
44
|
-
return observer;
|
|
45
|
-
}
|
|
43
|
+
function splitWith(s, c = ",") {
|
|
44
|
+
return s.split(c).map((s2) => s2.trim()).filter(Boolean);
|
|
45
|
+
}
|
|
46
|
+
function sanitizeStr(s) {
|
|
47
|
+
return s?.replace(/\n|\t/g, " ").replace(/ {2,}/g, " ").trim() || "";
|
|
48
|
+
}
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
function querySelectorText(e, selector) {
|
|
52
|
-
if (typeof selector !== "string") return "";
|
|
53
|
-
const text = e.querySelector(selector)?.innerText || "";
|
|
54
|
-
return sanitizeStr(text);
|
|
55
|
-
}
|
|
56
|
-
function parseHtml(html) {
|
|
57
|
-
const parsed = new DOMParser().parseFromString(html, "text/html").body;
|
|
58
|
-
if (parsed.children.length > 1) return parsed;
|
|
59
|
-
return parsed.firstElementChild;
|
|
60
|
-
}
|
|
61
|
-
function removeClassesAndDataAttributes(element, keyword) {
|
|
62
|
-
Array.from(element.classList).forEach((className) => {
|
|
63
|
-
if (className.includes(keyword)) {
|
|
64
|
-
element.classList.remove(className);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
Array.from(element.attributes).forEach((attr) => {
|
|
68
|
-
if (attr.name.startsWith("data-") && attr.name.includes(keyword)) {
|
|
69
|
-
element.removeAttribute(attr.name);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
function getCommonParents(elements) {
|
|
74
|
-
const parents = Array.from(elements).map((el) => el.parentElement).filter((parent) => parent !== null);
|
|
75
|
-
return [...new Set(parents)];
|
|
50
|
+
class RegexFilter {
|
|
51
|
+
regexes;
|
|
52
|
+
constructor(str, flags = "gi") {
|
|
53
|
+
this.regexes = memoize(this.compileSearchRegex)(str, flags);
|
|
76
54
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
55
|
+
compileSearchRegex(str, flags) {
|
|
56
|
+
try {
|
|
57
|
+
if (str.startsWith("r:")) return [new RegExp(str.slice(2), flags)];
|
|
58
|
+
const regexes = splitWith(str).map(
|
|
59
|
+
(s) => s.replace(/f:(\w+)/g, (_, w) => `(^|\\ |,)${w}($|\\ |,)`)
|
|
60
|
+
).map((_) => new RegExp(_, flags));
|
|
61
|
+
return regexes;
|
|
62
|
+
} catch (_) {
|
|
63
|
+
return [];
|
|
88
64
|
}
|
|
89
|
-
return true;
|
|
90
65
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const pad = (num) => num.toString().padStart(2, "0");
|
|
94
|
-
const h = timeStr.match(/(\d+)\s*h/)?.[1] || "0";
|
|
95
|
-
const m = timeStr.match(/(\d+)\s*mi?n/)?.[1] || "0";
|
|
96
|
-
const s = timeStr.match(/(\d+)\s*sec/)?.[1] || "0";
|
|
97
|
-
return `${pad(+h)}:${pad(+m)}:${pad(+s)}`;
|
|
66
|
+
hasEvery(str) {
|
|
67
|
+
return this.regexes.every((r) => r.test(str));
|
|
98
68
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return normalized.split(":").reverse().reduce((total, unit, index) => total + parseInt(unit, 10) * 60 ** index, 0);
|
|
69
|
+
hasNone(str) {
|
|
70
|
+
return this.regexes.every((r) => !r.test(str));
|
|
102
71
|
}
|
|
72
|
+
}
|
|
103
73
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (parsed) {
|
|
110
|
-
const [, key, value] = parsed;
|
|
111
|
-
if (value) {
|
|
112
|
-
key.split("+").forEach((p) => {
|
|
113
|
-
acc[p] = value;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return acc;
|
|
118
|
-
},
|
|
119
|
-
{}
|
|
120
|
-
);
|
|
74
|
+
class DataFilter {
|
|
75
|
+
constructor(rules) {
|
|
76
|
+
this.rules = rules;
|
|
77
|
+
this.registerFilters(rules.customDataSelectorFns);
|
|
78
|
+
this.applyCSSFilters();
|
|
121
79
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
function memoize(fn) {
|
|
126
|
-
const cache = new Map();
|
|
127
|
-
const memoizedFunction = ((...args) => {
|
|
128
|
-
const key = JSON.stringify(args);
|
|
129
|
-
if (cache.has(key)) {
|
|
130
|
-
return cache.get(key);
|
|
131
|
-
}
|
|
132
|
-
const result = fn(...args);
|
|
133
|
-
cache.set(key, result);
|
|
134
|
-
return result;
|
|
135
|
-
});
|
|
136
|
-
return memoizedFunction;
|
|
80
|
+
filters = new Map();
|
|
81
|
+
static isFiltered(el) {
|
|
82
|
+
return el.className.includes("filter-");
|
|
137
83
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
if (str.startsWith("r:")) return [new RegExp(str.slice(2), flags)];
|
|
147
|
-
const regexes = splitWith(str).map(
|
|
148
|
-
(s) => s.replace(/f:(\w+)/g, (_, w) => `(^|\\ |,)${w}($|\\ |,)`)
|
|
149
|
-
).map((_) => new RegExp(_, flags));
|
|
150
|
-
return regexes;
|
|
151
|
-
} catch (_) {
|
|
152
|
-
return [];
|
|
84
|
+
applyCSSFilters(wrapper) {
|
|
85
|
+
this.filters.forEach((_, name) => {
|
|
86
|
+
const cssRule = `.filter-${name} { display: none !important; }`;
|
|
87
|
+
if (wrapper) {
|
|
88
|
+
_GM_addStyle(wrapper(cssRule));
|
|
89
|
+
} else {
|
|
90
|
+
_GM_addStyle(cssRule);
|
|
153
91
|
}
|
|
154
|
-
}
|
|
155
|
-
hasEvery(str) {
|
|
156
|
-
return this.regexes.every((r) => r.test(str));
|
|
157
|
-
}
|
|
158
|
-
hasNone(str) {
|
|
159
|
-
return this.regexes.every((r) => !r.test(str));
|
|
160
|
-
}
|
|
92
|
+
});
|
|
161
93
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
filters = new Map();
|
|
170
|
-
static isFiltered(el) {
|
|
171
|
-
return el.className.includes("filter-");
|
|
172
|
-
}
|
|
173
|
-
applyCSSFilters(wrapper) {
|
|
174
|
-
this.filters.forEach((_, name) => {
|
|
175
|
-
const cssRule = `.filter-${name} { display: none !important; }`;
|
|
176
|
-
if (wrapper) {
|
|
177
|
-
_GM_addStyle(wrapper(cssRule));
|
|
178
|
-
} else {
|
|
179
|
-
_GM_addStyle(cssRule);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
customDataSelectorFns = {};
|
|
184
|
-
registerFilters(customFilters) {
|
|
185
|
-
customFilters.forEach((o) => {
|
|
186
|
-
if (typeof o === "string") {
|
|
187
|
-
this.customDataSelectorFns[o] = DataFilter.customDataSelectorFnsDefault[o];
|
|
188
|
-
this.registerFilter(o);
|
|
189
|
-
} else {
|
|
190
|
-
const k = Object.keys(o)[0];
|
|
191
|
-
this.customDataSelectorFns[k] = o[k];
|
|
192
|
-
this.registerFilter(k);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
customSelectorParser(name, selector) {
|
|
197
|
-
if ("handle" in selector) {
|
|
198
|
-
return selector;
|
|
94
|
+
customDataSelectorFns = {};
|
|
95
|
+
registerFilters(customFilters) {
|
|
96
|
+
customFilters.forEach((o) => {
|
|
97
|
+
if (typeof o === "string") {
|
|
98
|
+
this.customDataSelectorFns[o] = DataFilter.customDataSelectorFnsDefault[o];
|
|
99
|
+
this.registerFilter(o);
|
|
199
100
|
} else {
|
|
200
|
-
|
|
101
|
+
const k = Object.keys(o)[0];
|
|
102
|
+
this.customDataSelectorFns[k] = o[k];
|
|
103
|
+
this.registerFilter(k);
|
|
201
104
|
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
customSelectorParser(name, selector) {
|
|
108
|
+
if ("handle" in selector) {
|
|
109
|
+
return selector;
|
|
110
|
+
} else {
|
|
111
|
+
return { handle: selector, deps: [name] };
|
|
202
112
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
113
|
+
}
|
|
114
|
+
registerFilter(customSelectorName) {
|
|
115
|
+
const handler = this.customSelectorParser(
|
|
116
|
+
customSelectorName,
|
|
117
|
+
this.customDataSelectorFns[customSelectorName]
|
|
118
|
+
);
|
|
119
|
+
const tag = `filter-${customSelectorName}`;
|
|
120
|
+
[customSelectorName, ...handler.deps || []]?.forEach((name) => {
|
|
121
|
+
Object.assign(this.filterMapping, { [name]: customSelectorName });
|
|
122
|
+
});
|
|
123
|
+
const fn = () => {
|
|
124
|
+
const preDefined = handler.$preDefine?.(this.rules.store.state);
|
|
125
|
+
return (v) => {
|
|
126
|
+
const condition = handler.handle(v, this.rules.store.state, preDefined);
|
|
127
|
+
return {
|
|
128
|
+
condition,
|
|
129
|
+
tag
|
|
220
130
|
};
|
|
221
131
|
};
|
|
222
|
-
this.filters.set(customSelectorName, fn);
|
|
223
|
-
}
|
|
224
|
-
filterMapping = {};
|
|
225
|
-
selectFilters(filters) {
|
|
226
|
-
const selectedFilters = Object.keys(filters).filter((k) => k in this.filterMapping).map((k) => this.filterMapping[k]).map((k) => this.filters.get(k));
|
|
227
|
-
return selectedFilters;
|
|
228
|
-
}
|
|
229
|
-
static customDataSelectorFnsDefault = {
|
|
230
|
-
filterDuration: {
|
|
231
|
-
handle(el, state, notInRange) {
|
|
232
|
-
return state.filterDuration && notInRange(el.duration);
|
|
233
|
-
},
|
|
234
|
-
$preDefine: (state) => {
|
|
235
|
-
const from = state.filterDurationFrom;
|
|
236
|
-
const to = state.filterDurationTo;
|
|
237
|
-
function notInRange(d) {
|
|
238
|
-
return d < from || d > to;
|
|
239
|
-
}
|
|
240
|
-
return notInRange;
|
|
241
|
-
},
|
|
242
|
-
deps: ["filterDurationFrom", "filterDurationTo"]
|
|
243
|
-
},
|
|
244
|
-
filterExclude: {
|
|
245
|
-
handle(el, state, searchFilter) {
|
|
246
|
-
if (!state.filterExclude) return false;
|
|
247
|
-
return !searchFilter.hasNone(el.title);
|
|
248
|
-
},
|
|
249
|
-
$preDefine: (state) => new RegexFilter(state.filterExcludeWords),
|
|
250
|
-
deps: ["filterExcludeWords"]
|
|
251
|
-
},
|
|
252
|
-
filterInclude: {
|
|
253
|
-
handle(el, state, searchFilter) {
|
|
254
|
-
if (!state.filterInclude) return false;
|
|
255
|
-
return !searchFilter.hasEvery(el.title);
|
|
256
|
-
},
|
|
257
|
-
$preDefine: (state) => new RegexFilter(state.filterIncludeWords),
|
|
258
|
-
deps: ["filterIncludeWords"]
|
|
259
|
-
}
|
|
260
132
|
};
|
|
133
|
+
this.filters.set(customSelectorName, fn);
|
|
261
134
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
135
|
+
filterMapping = {};
|
|
136
|
+
selectFilters(filters) {
|
|
137
|
+
const selectedFilters = Object.keys(filters).filter((k) => k in this.filterMapping).map((k) => this.filterMapping[k]).map((k) => this.filters.get(k));
|
|
138
|
+
return selectedFilters;
|
|
139
|
+
}
|
|
140
|
+
static customDataSelectorFnsDefault = {
|
|
141
|
+
filterDuration: {
|
|
142
|
+
handle(el, state, notInRange) {
|
|
143
|
+
return state.filterDuration && notInRange(el.duration);
|
|
144
|
+
},
|
|
145
|
+
$preDefine: (state) => {
|
|
146
|
+
const from = state.filterDurationFrom;
|
|
147
|
+
const to = state.filterDurationTo;
|
|
148
|
+
function notInRange(d) {
|
|
149
|
+
return d < from || d > to;
|
|
270
150
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
151
|
+
return notInRange;
|
|
152
|
+
},
|
|
153
|
+
deps: ["filterDurationFrom", "filterDurationTo"]
|
|
154
|
+
},
|
|
155
|
+
filterExclude: {
|
|
156
|
+
handle(el, state, searchFilter) {
|
|
157
|
+
if (!state.filterExclude) return false;
|
|
158
|
+
return !searchFilter.hasNone(el.title);
|
|
159
|
+
},
|
|
160
|
+
$preDefine: (state) => new RegexFilter(state.filterExcludeWords),
|
|
161
|
+
deps: ["filterExcludeWords"]
|
|
162
|
+
},
|
|
163
|
+
filterInclude: {
|
|
164
|
+
handle(el, state, searchFilter) {
|
|
165
|
+
if (!state.filterInclude) return false;
|
|
166
|
+
return !searchFilter.hasEvery(el.title);
|
|
167
|
+
},
|
|
168
|
+
$preDefine: (state) => new RegexFilter(state.filterIncludeWords),
|
|
169
|
+
deps: ["filterIncludeWords"]
|
|
278
170
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
target.src = target.getAttribute(this.attributeName);
|
|
282
|
-
target.removeAttribute(this.attributeName);
|
|
283
|
-
};
|
|
284
|
-
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
285
173
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
observer;
|
|
292
|
-
timeout;
|
|
293
|
-
observe(target) {
|
|
294
|
-
this.observer.observe(target);
|
|
295
|
-
}
|
|
296
|
-
throttle(target, throttleTime) {
|
|
297
|
-
this.observer.unobserve(target);
|
|
298
|
-
this.timeout = window.setTimeout(() => this.observer.observe(target), throttleTime);
|
|
174
|
+
function waitForElementToDisappear(observable, callback) {
|
|
175
|
+
const observer = new MutationObserver((_mutations) => {
|
|
176
|
+
if (!observable.isConnected) {
|
|
177
|
+
observer.disconnect();
|
|
178
|
+
callback();
|
|
299
179
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
180
|
+
});
|
|
181
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
182
|
+
return observer;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function querySelectorLast(root = document, selector) {
|
|
186
|
+
const nodes = root.querySelectorAll(selector);
|
|
187
|
+
return nodes.length > 0 ? nodes[nodes.length - 1] : void 0;
|
|
188
|
+
}
|
|
189
|
+
function querySelectorText(e, selector) {
|
|
190
|
+
if (typeof selector !== "string") return "";
|
|
191
|
+
const text = e.querySelector(selector)?.innerText || "";
|
|
192
|
+
return sanitizeStr(text);
|
|
193
|
+
}
|
|
194
|
+
function parseHtml(html) {
|
|
195
|
+
const parsed = new DOMParser().parseFromString(html, "text/html").body;
|
|
196
|
+
if (parsed.children.length > 1) return parsed;
|
|
197
|
+
return parsed.firstElementChild;
|
|
198
|
+
}
|
|
199
|
+
function removeClassesAndDataAttributes(element, keyword) {
|
|
200
|
+
Array.from(element.classList).forEach((className) => {
|
|
201
|
+
if (className.includes(keyword)) {
|
|
202
|
+
element.classList.remove(className);
|
|
306
203
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
204
|
+
});
|
|
205
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
206
|
+
if (attr.name.startsWith("data-") && attr.name.includes(keyword)) {
|
|
207
|
+
element.removeAttribute(attr.name);
|
|
310
208
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function getCommonParents(elements) {
|
|
212
|
+
const parents = Array.from(elements).map((el) => el.parentElement).filter((parent) => parent !== null);
|
|
213
|
+
return [...new Set(parents)];
|
|
214
|
+
}
|
|
215
|
+
function checkHomogenity(a, b, options) {
|
|
216
|
+
if (!a || !b) return false;
|
|
217
|
+
if (options.id) {
|
|
218
|
+
if (a.id !== b.id) return false;
|
|
219
|
+
}
|
|
220
|
+
if (options.className) {
|
|
221
|
+
const ca = a.className;
|
|
222
|
+
const cb = b.className;
|
|
223
|
+
if (!(ca.length > cb.length ? ca.includes(cb) : cb.includes(ca))) {
|
|
224
|
+
return false;
|
|
318
225
|
}
|
|
319
226
|
}
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
320
229
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
(target) => !DataFilter.isFiltered(target)
|
|
329
|
-
);
|
|
330
|
-
dataFilter;
|
|
331
|
-
applyFilters = async (filters = {}, offset = 0) => {
|
|
332
|
-
const filtersToApply = this.dataFilter.selectFilters(filters);
|
|
333
|
-
if (filtersToApply.length === 0) return;
|
|
334
|
-
const iterator = this.data.values().drop(offset);
|
|
335
|
-
let finished = false;
|
|
336
|
-
await new Promise((resolve) => {
|
|
337
|
-
function runBatch(deadline) {
|
|
338
|
-
const updates = [];
|
|
339
|
-
while (deadline.timeRemaining() > 0) {
|
|
340
|
-
const { value, done } = iterator.next();
|
|
341
|
-
finished = !!done;
|
|
342
|
-
if (done) break;
|
|
343
|
-
for (const f of filtersToApply) {
|
|
344
|
-
const { tag, condition } = f()(value);
|
|
345
|
-
updates.push({ e: value.element, tag, condition });
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
if (updates.length > 0) {
|
|
349
|
-
requestAnimationFrame(() => {
|
|
350
|
-
updates.forEach((u) => {
|
|
351
|
-
u.e.classList.toggle(u.tag, u.condition);
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
if (!finished) {
|
|
356
|
-
requestIdleCallback(runBatch);
|
|
357
|
-
} else {
|
|
358
|
-
resolve(true);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
requestIdleCallback(runBatch);
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
filterAll = async (offset) => {
|
|
365
|
-
const keys = Array.from(this.dataFilter.filters.keys());
|
|
366
|
-
const filters = Object.fromEntries(
|
|
367
|
-
keys.map((k) => [k, this.rules.store.state[k]])
|
|
368
|
-
);
|
|
369
|
-
await this.applyFilters(filters, offset);
|
|
370
|
-
};
|
|
371
|
-
parseDataParentHomogenity;
|
|
372
|
-
parseData = (html, container, removeDuplicates = false, shouldLazify = true) => {
|
|
373
|
-
const thumbs = this.rules.getThumbs(html);
|
|
374
|
-
const dataOffset = this.data.size;
|
|
375
|
-
const fragment = document.createDocumentFragment();
|
|
376
|
-
const parent = container || this.rules.container;
|
|
377
|
-
const homogenity = !!this.parseDataParentHomogenity;
|
|
378
|
-
for (const thumbElement of thumbs) {
|
|
379
|
-
const url = this.rules.getThumbUrl(thumbElement);
|
|
380
|
-
if (!url || this.data.has(url) || parent !== container && parent?.contains(thumbElement) || homogenity && !checkHomogenity(
|
|
381
|
-
parent,
|
|
382
|
-
thumbElement.parentElement,
|
|
383
|
-
this.parseDataParentHomogenity
|
|
384
|
-
)) {
|
|
385
|
-
if (removeDuplicates) thumbElement.remove();
|
|
386
|
-
continue;
|
|
387
|
-
}
|
|
388
|
-
const data = this.rules.getThumbData(thumbElement);
|
|
389
|
-
this.data.set(url, { element: thumbElement, ...data });
|
|
390
|
-
if (shouldLazify) {
|
|
391
|
-
const { img, imgSrc } = this.rules.getThumbImgData(thumbElement);
|
|
392
|
-
this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
|
|
393
|
-
}
|
|
394
|
-
fragment.append(thumbElement);
|
|
230
|
+
class LazyImgLoader {
|
|
231
|
+
lazyImgObserver;
|
|
232
|
+
attributeName = "data-lazy-load";
|
|
233
|
+
constructor(shouldDelazify) {
|
|
234
|
+
this.lazyImgObserver = new Observer((target) => {
|
|
235
|
+
if (shouldDelazify(target)) {
|
|
236
|
+
this.delazify(target);
|
|
395
237
|
}
|
|
396
|
-
|
|
397
|
-
requestAnimationFrame(() => {
|
|
398
|
-
parent.appendChild(fragment);
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
};
|
|
402
|
-
sortBy(key, direction = true) {
|
|
403
|
-
if (this.data.size < 2) return;
|
|
404
|
-
let sorted = this.data.values().toArray().sort((a, b) => {
|
|
405
|
-
return a[key] - b[key];
|
|
406
|
-
});
|
|
407
|
-
if (!direction) sorted = sorted.reverse();
|
|
408
|
-
const container = sorted[0].element.parentElement;
|
|
409
|
-
container.style.visibility = "hidden";
|
|
410
|
-
sorted.forEach((s) => {
|
|
411
|
-
container.append(s.element);
|
|
412
|
-
});
|
|
413
|
-
container.style.visibility = "visible";
|
|
414
|
-
}
|
|
238
|
+
});
|
|
415
239
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
240
|
+
lazify(_target, img, imgSrc) {
|
|
241
|
+
if (!img || !imgSrc) return;
|
|
242
|
+
img.setAttribute(this.attributeName, imgSrc);
|
|
243
|
+
img.src = "";
|
|
244
|
+
this.lazyImgObserver.observe(img);
|
|
419
245
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
"AppleWebKit/537.36 (KHTML, like Gecko)",
|
|
425
|
-
"Chrome/114.0.0.0 Mobile Safari/537.36"
|
|
426
|
-
].join(" ")
|
|
246
|
+
delazify = (target) => {
|
|
247
|
+
this.lazyImgObserver.observer.unobserve(target);
|
|
248
|
+
target.src = target.getAttribute(this.attributeName);
|
|
249
|
+
target.removeAttribute(this.attributeName);
|
|
427
250
|
};
|
|
428
|
-
|
|
429
|
-
const requestInit = options.init || {};
|
|
430
|
-
if (options.mobile) {
|
|
431
|
-
Object.assign(requestInit, { headers: new Headers(MOBILE_UA) });
|
|
432
|
-
}
|
|
433
|
-
const r = await fetch(input, requestInit).then((r2) => r2);
|
|
434
|
-
return parseHtml(await r.text());
|
|
435
|
-
}
|
|
436
|
-
const fetchHtml = (input) => fetchWith(input, { });
|
|
251
|
+
}
|
|
437
252
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
253
|
+
class Observer {
|
|
254
|
+
constructor(callback) {
|
|
255
|
+
this.callback = callback;
|
|
256
|
+
this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
|
|
257
|
+
}
|
|
258
|
+
observer;
|
|
259
|
+
timeout;
|
|
260
|
+
observe(target) {
|
|
261
|
+
this.observer.observe(target);
|
|
262
|
+
}
|
|
263
|
+
throttle(target, throttleTime) {
|
|
264
|
+
this.observer.unobserve(target);
|
|
265
|
+
this.timeout = window.setTimeout(() => this.observer.observe(target), throttleTime);
|
|
266
|
+
}
|
|
267
|
+
handleIntersection(entries) {
|
|
268
|
+
for (const entry of entries) {
|
|
269
|
+
if (entry.isIntersecting) {
|
|
270
|
+
this.callback(entry.target);
|
|
451
271
|
}
|
|
452
|
-
this.paginationGenerator = this.rules.customGenerator || InfiniteScroller.generatorForPaginationStrategy(this.rules.paginationStrategy);
|
|
453
|
-
this.setObserver(this.rules.observable);
|
|
454
|
-
this.setAutoScroll();
|
|
455
|
-
}
|
|
456
|
-
dispose() {
|
|
457
|
-
if (this.observer) this.observer.dispose();
|
|
458
|
-
}
|
|
459
|
-
setObserver(observable) {
|
|
460
|
-
if (this.observer) this.observer.dispose();
|
|
461
|
-
this.observer = Observer.observeWhile(
|
|
462
|
-
observable,
|
|
463
|
-
this.generatorConsumer,
|
|
464
|
-
this.rules.store.state.delay
|
|
465
|
-
);
|
|
466
|
-
return this;
|
|
467
|
-
}
|
|
468
|
-
onScrollCBs = [];
|
|
469
|
-
onScroll(callback, initCall = false) {
|
|
470
|
-
if (initCall) callback(this);
|
|
471
|
-
this.onScrollCBs.push(callback);
|
|
472
|
-
return this;
|
|
473
272
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
273
|
+
}
|
|
274
|
+
dispose() {
|
|
275
|
+
if (this.timeout) clearTimeout(this.timeout);
|
|
276
|
+
this.observer.disconnect();
|
|
277
|
+
}
|
|
278
|
+
static observeWhile(target, callback, throttleTime) {
|
|
279
|
+
const observer_ = new Observer(async (target2) => {
|
|
280
|
+
const condition = await callback();
|
|
281
|
+
if (condition) observer_.throttle(target2, throttleTime);
|
|
282
|
+
});
|
|
283
|
+
observer_.observe(target);
|
|
284
|
+
return observer_;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
class DataManager {
|
|
289
|
+
constructor(rules) {
|
|
290
|
+
this.rules = rules;
|
|
291
|
+
this.dataFilter = new DataFilter(this.rules);
|
|
292
|
+
}
|
|
293
|
+
data = new Map();
|
|
294
|
+
lazyImgLoader = new LazyImgLoader(
|
|
295
|
+
(target) => !DataFilter.isFiltered(target)
|
|
296
|
+
);
|
|
297
|
+
dataFilter;
|
|
298
|
+
applyFilters = async (filters = {}, offset = 0) => {
|
|
299
|
+
const filtersToApply = this.dataFilter.selectFilters(filters);
|
|
300
|
+
if (filtersToApply.length === 0) return;
|
|
301
|
+
const iterator = this.data.values().drop(offset);
|
|
302
|
+
let finished = false;
|
|
303
|
+
await new Promise((resolve) => {
|
|
304
|
+
function runBatch(deadline) {
|
|
305
|
+
const updates = [];
|
|
306
|
+
while (deadline.timeRemaining() > 0) {
|
|
307
|
+
const { value, done } = iterator.next();
|
|
308
|
+
finished = !!done;
|
|
309
|
+
if (done) break;
|
|
310
|
+
for (const f of filtersToApply) {
|
|
311
|
+
const { tag, condition } = f()(value);
|
|
312
|
+
updates.push({ e: value.element, tag, condition });
|
|
313
|
+
}
|
|
485
314
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
315
|
+
if (updates.length > 0) {
|
|
316
|
+
requestAnimationFrame(() => {
|
|
317
|
+
updates.forEach((u) => {
|
|
318
|
+
u.e.classList.toggle(u.tag, u.condition);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (!finished) {
|
|
323
|
+
requestIdleCallback(runBatch);
|
|
324
|
+
} else {
|
|
325
|
+
resolve(true);
|
|
491
326
|
}
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
generatorConsumer = async () => {
|
|
495
|
-
if (!this.enabled) return false;
|
|
496
|
-
const {
|
|
497
|
-
value: { url, offset },
|
|
498
|
-
done
|
|
499
|
-
} = await this.paginationGenerator.next();
|
|
500
|
-
if (!done && url) {
|
|
501
|
-
await this.doScroll(url, offset);
|
|
502
327
|
}
|
|
503
|
-
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
328
|
+
requestIdleCallback(runBatch);
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
filterAll = async (offset) => {
|
|
332
|
+
const keys = Array.from(this.dataFilter.filters.keys());
|
|
333
|
+
const filters = Object.fromEntries(
|
|
334
|
+
keys.map((k) => [k, this.rules.store.state[k]])
|
|
335
|
+
);
|
|
336
|
+
await this.applyFilters(filters, offset);
|
|
337
|
+
};
|
|
338
|
+
parseDataParentHomogenity;
|
|
339
|
+
parseData = (html, container, removeDuplicates = false, shouldLazify = true) => {
|
|
340
|
+
const thumbs = this.rules.getThumbs(html);
|
|
341
|
+
const dataOffset = this.data.size;
|
|
342
|
+
const fragment = document.createDocumentFragment();
|
|
343
|
+
const parent = container || this.rules.container;
|
|
344
|
+
const homogenity = !!this.parseDataParentHomogenity;
|
|
345
|
+
for (const thumbElement of thumbs) {
|
|
346
|
+
const url = this.rules.getThumbUrl(thumbElement);
|
|
347
|
+
if (!url || this.data.has(url) || parent !== container && parent?.contains(thumbElement) || homogenity && !checkHomogenity(
|
|
348
|
+
parent,
|
|
349
|
+
thumbElement.parentElement,
|
|
350
|
+
this.parseDataParentHomogenity
|
|
351
|
+
)) {
|
|
352
|
+
if (removeDuplicates) thumbElement.remove();
|
|
353
|
+
continue;
|
|
517
354
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
for (let offset = _offset; offset <= end; offset++) {
|
|
524
|
-
const url = await urlGenerator(offset);
|
|
525
|
-
yield { url, offset };
|
|
355
|
+
const data = this.rules.getThumbData(thumbElement);
|
|
356
|
+
this.data.set(url, { element: thumbElement, ...data });
|
|
357
|
+
if (shouldLazify) {
|
|
358
|
+
const { img, imgSrc } = this.rules.getThumbImgData(thumbElement);
|
|
359
|
+
this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
|
|
526
360
|
}
|
|
361
|
+
fragment.append(thumbElement);
|
|
527
362
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const infiniteScroller = new InfiniteScroller({
|
|
532
|
-
enabled,
|
|
533
|
-
parseData: rules.dataManager.parseData,
|
|
534
|
-
rules
|
|
535
|
-
}).onScroll(({ paginationOffset }) => {
|
|
536
|
-
rules.store.state.$paginationOffset = paginationOffset;
|
|
537
|
-
}, true);
|
|
538
|
-
rules.store.stateSubject.subscribe(() => {
|
|
539
|
-
infiniteScroller.enabled = rules.store.state.infiniteScrollEnabled;
|
|
363
|
+
this.filterAll(dataOffset).then(() => {
|
|
364
|
+
requestAnimationFrame(() => {
|
|
365
|
+
parent.appendChild(fragment);
|
|
540
366
|
});
|
|
541
|
-
|
|
542
|
-
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
sortBy(key, direction = true) {
|
|
370
|
+
if (this.data.size < 2) return;
|
|
371
|
+
let sorted = this.data.values().toArray().sort((a, b) => {
|
|
372
|
+
return a[key] - b[key];
|
|
373
|
+
});
|
|
374
|
+
if (!direction) sorted = sorted.reverse();
|
|
375
|
+
const container = sorted[0].element.parentElement;
|
|
376
|
+
container.style.visibility = "hidden";
|
|
377
|
+
sorted.forEach((s) => {
|
|
378
|
+
container.append(s.element);
|
|
379
|
+
});
|
|
380
|
+
container.style.visibility = "visible";
|
|
543
381
|
}
|
|
382
|
+
}
|
|
544
383
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
collapsed: true,
|
|
549
|
-
content: [
|
|
550
|
-
{ filterExclude: false, label: "exclude" },
|
|
551
|
-
{
|
|
552
|
-
filterExcludeWords: "",
|
|
553
|
-
label: "keywords",
|
|
554
|
-
watch: "filterExclude",
|
|
555
|
-
placeholder: "word, f:full_word, r:RegEx..."
|
|
556
|
-
},
|
|
557
|
-
{ filterInclude: false, label: "include" },
|
|
558
|
-
{
|
|
559
|
-
filterIncludeWords: "",
|
|
560
|
-
label: "keywords",
|
|
561
|
-
watch: "filterInclude",
|
|
562
|
-
placeholder: "word, f:full_word, r:RegEx..."
|
|
563
|
-
}
|
|
564
|
-
]
|
|
565
|
-
},
|
|
566
|
-
{
|
|
567
|
-
title: "Duration Filter",
|
|
568
|
-
collapsed: true,
|
|
569
|
-
content: [
|
|
570
|
-
{ filterDuration: false, label: "enable" },
|
|
571
|
-
{
|
|
572
|
-
filterDurationFrom: 0,
|
|
573
|
-
watch: "filterDuration",
|
|
574
|
-
label: "from",
|
|
575
|
-
type: "time"
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
filterDurationTo: 600,
|
|
579
|
-
watch: "filterDuration",
|
|
580
|
-
label: "to",
|
|
581
|
-
type: "time"
|
|
582
|
-
}
|
|
583
|
-
]
|
|
584
|
-
},
|
|
585
|
-
{
|
|
586
|
-
title: "Sort By",
|
|
587
|
-
content: [
|
|
588
|
-
{
|
|
589
|
-
"sort by views": () => {
|
|
590
|
-
}
|
|
591
|
-
},
|
|
592
|
-
{
|
|
593
|
-
"sort by duration": () => {
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
]
|
|
597
|
-
},
|
|
598
|
-
{
|
|
599
|
-
title: "Privacy Filter",
|
|
600
|
-
content: [
|
|
601
|
-
{ filterPrivate: false, label: "private" },
|
|
602
|
-
{ filterPublic: false, label: "public" },
|
|
603
|
-
{ "check access 🔓": () => {
|
|
604
|
-
} }
|
|
605
|
-
]
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
title: "Advanced",
|
|
609
|
-
content: [
|
|
610
|
-
{
|
|
611
|
-
infiniteScrollEnabled: true,
|
|
612
|
-
label: "infinite scroll"
|
|
613
|
-
},
|
|
614
|
-
{
|
|
615
|
-
autoScroll: false,
|
|
616
|
-
label: "auto scroll"
|
|
617
|
-
},
|
|
618
|
-
{
|
|
619
|
-
delay: 250,
|
|
620
|
-
label: "scroll delay"
|
|
621
|
-
},
|
|
622
|
-
{
|
|
623
|
-
writeHistory: false,
|
|
624
|
-
label: "write history"
|
|
625
|
-
}
|
|
626
|
-
]
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
title: "Badge",
|
|
630
|
-
content: [
|
|
631
|
-
{
|
|
632
|
-
text: "return `${state.$paginationOffset}/${state.$paginationLast}`",
|
|
633
|
-
vif: "return state.$paginationLast > 1"
|
|
634
|
-
}
|
|
635
|
-
]
|
|
636
|
-
}
|
|
637
|
-
];
|
|
638
|
-
|
|
639
|
-
const StoreStateDefault = {
|
|
640
|
-
enabled: true,
|
|
641
|
-
collapsed: false,
|
|
642
|
-
darkmode: true,
|
|
643
|
-
$paginationLast: 1,
|
|
644
|
-
$paginationOffset: 1
|
|
645
|
-
};
|
|
384
|
+
function wait(milliseconds) {
|
|
385
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
386
|
+
}
|
|
646
387
|
|
|
647
|
-
var Pe=Object.defineProperty;var a=(e,t)=>Pe(e,"name",{value:t,configurable:true});var P=class{type=3;name="";prefix="";value="";suffix="";modifier=3;constructor(t,r,n,c,l,f){this.type=t,this.name=r,this.prefix=n,this.value=c,this.suffix=l,this.modifier=f;}hasCustomName(){return this.name!==""&&typeof this.name!="number"}};a(P,"Part");var Re=/[$_\p{ID_Start}]/u,Ee=/[$_\u200C\u200D\p{ID_Continue}]/u,v=".*";function Oe(e,t){return (t?/^[\x00-\xFF]*$/:/^[\x00-\x7F]*$/).test(e)}a(Oe,"isASCII");function D(e,t=false){let r=[],n=0;for(;n<e.length;){let c=e[n],l=a(function(f){if(!t)throw new TypeError(f);r.push({type:"INVALID_CHAR",index:n,value:e[n++]});},"ErrorOrInvalid");if(c==="*"){r.push({type:"ASTERISK",index:n,value:e[n++]});continue}if(c==="+"||c==="?"){r.push({type:"OTHER_MODIFIER",index:n,value:e[n++]});continue}if(c==="\\"){r.push({type:"ESCAPED_CHAR",index:n++,value:e[n++]});continue}if(c==="{"){r.push({type:"OPEN",index:n,value:e[n++]});continue}if(c==="}"){r.push({type:"CLOSE",index:n,value:e[n++]});continue}if(c===":"){let f="",s=n+1;for(;s<e.length;){let i=e.substr(s,1);if(s===n+1&&Re.test(i)||s!==n+1&&Ee.test(i)){f+=e[s++];continue}break}if(!f){l(`Missing parameter name at ${n}`);continue}r.push({type:"NAME",index:n,value:f}),n=s;continue}if(c==="("){let f=1,s="",i=n+1,o=false;if(e[i]==="?"){l(`Pattern cannot start with "?" at ${i}`);continue}for(;i<e.length;){if(!Oe(e[i],false)){l(`Invalid character '${e[i]}' at ${i}.`),o=true;break}if(e[i]==="\\"){s+=e[i++]+e[i++];continue}if(e[i]===")"){if(f--,f===0){i++;break}}else if(e[i]==="("&&(f++,e[i+1]!=="?")){l(`Capturing groups are not allowed at ${i}`),o=true;break}s+=e[i++];}if(o)continue;if(f){l(`Unbalanced pattern at ${n}`);continue}if(!s){l(`Missing pattern at ${n}`);continue}r.push({type:"REGEX",index:n,value:s}),n=i;continue}r.push({type:"CHAR",index:n,value:e[n++]});}return r.push({type:"END",index:n,value:""}),r}a(D,"lexer");function F(e,t={}){let r=D(e);t.delimiter??="/#?",t.prefixes??="./";let n=`[^${x(t.delimiter)}]+?`,c=[],l=0,f=0,i=new Set,o=a(u=>{if(f<r.length&&r[f].type===u)return r[f++].value},"tryConsume"),h=a(()=>o("OTHER_MODIFIER")??o("ASTERISK"),"tryConsumeModifier"),p=a(u=>{let d=o(u);if(d!==void 0)return d;let{type:g,index:y}=r[f];throw new TypeError(`Unexpected ${g} at ${y}, expected ${u}`)},"mustConsume"),A=a(()=>{let u="",d;for(;d=o("CHAR")??o("ESCAPED_CHAR");)u+=d;return u},"consumeText"),xe=a(u=>u,"DefaultEncodePart"),N=t.encodePart||xe,H="",$=a(u=>{H+=u;},"appendToPendingFixedValue"),M=a(()=>{H.length&&(c.push(new P(3,"","",N(H),"",3)),H="");},"maybeAddPartFromPendingFixedValue"),X=a((u,d,g,y,Z)=>{let m=3;switch(Z){case "?":m=1;break;case "*":m=0;break;case "+":m=2;break}if(!d&&!g&&m===3){$(u);return}if(M(),!d&&!g){if(!u)return;c.push(new P(3,"","",N(u),"",m));return}let S;g?g==="*"?S=v:S=g:S=n;let k=2;S===n?(k=1,S=""):S===v&&(k=0,S="");let E;if(d?E=d:g&&(E=l++),i.has(E))throw new TypeError(`Duplicate name '${E}'.`);i.add(E),c.push(new P(k,E,N(u),S,N(y),m));},"addPart");for(;f<r.length;){let u=o("CHAR"),d=o("NAME"),g=o("REGEX");if(!d&&!g&&(g=o("ASTERISK")),d||g){let m=u??"";t.prefixes.indexOf(m)===-1&&($(m),m=""),M();let S=h();X(m,d,g,"",S);continue}let y=u??o("ESCAPED_CHAR");if(y){$(y);continue}if(o("OPEN")){let m=A(),S=o("NAME"),k=o("REGEX");!S&&!k&&(k=o("ASTERISK"));let E=A();p("CLOSE");let be=h();X(m,S,k,E,be);continue}M(),p("END");}return c}a(F,"parse");function x(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(x,"escapeString");function B(e){return e&&e.ignoreCase?"ui":"u"}a(B,"flags");function q(e,t,r){return W(F(e,r),t,r)}a(q,"stringToRegexp");function T(e){switch(e){case 0:return "*";case 1:return "?";case 2:return "+";case 3:return ""}}a(T,"modifierToString");function W(e,t,r={}){r.delimiter??="/#?",r.prefixes??="./",r.sensitive??=false,r.strict??=false,r.end??=true,r.start??=true,r.endsWith="";let n=r.start?"^":"";for(let s of e){if(s.type===3){s.modifier===3?n+=x(s.value):n+=`(?:${x(s.value)})${T(s.modifier)}`;continue}t&&t.push(s.name);let i=`[^${x(r.delimiter)}]+?`,o=s.value;if(s.type===1?o=i:s.type===0&&(o=v),!s.prefix.length&&!s.suffix.length){s.modifier===3||s.modifier===1?n+=`(${o})${T(s.modifier)}`:n+=`((?:${o})${T(s.modifier)})`;continue}if(s.modifier===3||s.modifier===1){n+=`(?:${x(s.prefix)}(${o})${x(s.suffix)})`,n+=T(s.modifier);continue}n+=`(?:${x(s.prefix)}`,n+=`((?:${o})(?:`,n+=x(s.suffix),n+=x(s.prefix),n+=`(?:${o}))*)${x(s.suffix)})`,s.modifier===0&&(n+="?");}let c=`[${x(r.endsWith)}]|$`,l=`[${x(r.delimiter)}]`;if(r.end)return r.strict||(n+=`${l}?`),r.endsWith.length?n+=`(?=${c})`:n+="$",new RegExp(n,B(r));r.strict||(n+=`(?:${l}(?=${c}))?`);let f=false;if(e.length){let s=e[e.length-1];s.type===3&&s.modifier===3&&(f=r.delimiter.indexOf(s)>-1);}return f||(n+=`(?=${l}|${c})`),new RegExp(n,B(r))}a(W,"partsToRegexp");var b={delimiter:"",prefixes:"",sensitive:true,strict:true},J={delimiter:".",prefixes:"",sensitive:true,strict:true},Q={delimiter:"/",prefixes:"/",sensitive:true,strict:true};function ee(e,t){return e.length?e[0]==="/"?true:!t||e.length<2?false:(e[0]=="\\"||e[0]=="{")&&e[1]=="/":false}a(ee,"isAbsolutePathname");function te(e,t){return e.startsWith(t)?e.substring(t.length,e.length):e}a(te,"maybeStripPrefix");function ke(e,t){return e.endsWith(t)?e.substr(0,e.length-t.length):e}a(ke,"maybeStripSuffix");function _(e){return !e||e.length<2?false:e[0]==="["||(e[0]==="\\"||e[0]==="{")&&e[1]==="["}a(_,"treatAsIPv6Hostname");var re=["ftp","file","http","https","ws","wss"];function U(e){if(!e)return true;for(let t of re)if(e.test(t))return true;return false}a(U,"isSpecialScheme");function ne(e,t){if(e=te(e,"#"),t||e==="")return e;let r=new URL("https://example.com");return r.hash=e,r.hash?r.hash.substring(1,r.hash.length):""}a(ne,"canonicalizeHash");function se(e,t){if(e=te(e,"?"),t||e==="")return e;let r=new URL("https://example.com");return r.search=e,r.search?r.search.substring(1,r.search.length):""}a(se,"canonicalizeSearch");function ie(e,t){return t||e===""?e:_(e)?K(e):j(e)}a(ie,"canonicalizeHostname");function ae(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.password=e,r.password}a(ae,"canonicalizePassword");function oe(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.username=e,r.username}a(oe,"canonicalizeUsername");function ce(e,t,r){if(r||e==="")return e;if(t&&!re.includes(t))return new URL(`${t}:${e}`).pathname;let n=e[0]=="/";return e=new URL(n?e:"/-"+e,"https://example.com").pathname,n||(e=e.substring(2,e.length)),e}a(ce,"canonicalizePathname");function le(e,t,r){return z(t)===e&&(e=""),r||e===""?e:G(e)}a(le,"canonicalizePort");function fe(e,t){return e=ke(e,":"),t||e===""?e:w(e)}a(fe,"canonicalizeProtocol");function z(e){switch(e){case "ws":case "http":return "80";case "wws":case "https":return "443";case "ftp":return "21";default:return ""}}a(z,"defaultPortForProtocol");function w(e){if(e==="")return e;if(/^[-+.A-Za-z0-9]*$/.test(e))return e.toLowerCase();throw new TypeError(`Invalid protocol '${e}'.`)}a(w,"protocolEncodeCallback");function he(e){if(e==="")return e;let t=new URL("https://example.com");return t.username=e,t.username}a(he,"usernameEncodeCallback");function ue(e){if(e==="")return e;let t=new URL("https://example.com");return t.password=e,t.password}a(ue,"passwordEncodeCallback");function j(e){if(e==="")return e;if(/[\t\n\r #%/:<>?@[\]^\\|]/g.test(e))throw new TypeError(`Invalid hostname '${e}'`);let t=new URL("https://example.com");return t.hostname=e,t.hostname}a(j,"hostnameEncodeCallback");function K(e){if(e==="")return e;if(/[^0-9a-fA-F[\]:]/g.test(e))throw new TypeError(`Invalid IPv6 hostname '${e}'`);return e.toLowerCase()}a(K,"ipv6HostnameEncodeCallback");function G(e){if(e===""||/^[0-9]*$/.test(e)&&parseInt(e)<=65535)return e;throw new TypeError(`Invalid port '${e}'.`)}a(G,"portEncodeCallback");function de(e){if(e==="")return e;let t=new URL("https://example.com");return t.pathname=e[0]!=="/"?"/-"+e:e,e[0]!=="/"?t.pathname.substring(2,t.pathname.length):t.pathname}a(de,"standardURLPathnameEncodeCallback");function pe(e){return e===""?e:new URL(`data:${e}`).pathname}a(pe,"pathURLPathnameEncodeCallback");function ge(e){if(e==="")return e;let t=new URL("https://example.com");return t.search=e,t.search.substring(1,t.search.length)}a(ge,"searchEncodeCallback");function me(e){if(e==="")return e;let t=new URL("https://example.com");return t.hash=e,t.hash.substring(1,t.hash.length)}a(me,"hashEncodeCallback");var C=class{#i;#n=[];#t={};#e=0;#s=1;#l=0;#o=0;#d=0;#p=0;#g=false;constructor(t){this.#i=t;}get result(){return this.#t}parse(){for(this.#n=D(this.#i,true);this.#e<this.#n.length;this.#e+=this.#s){if(this.#s=1,this.#n[this.#e].type==="END"){if(this.#o===0){this.#b(),this.#f()?this.#r(9,1):this.#h()?this.#r(8,1):this.#r(7,0);continue}else if(this.#o===2){this.#u(5);continue}this.#r(10,0);break}if(this.#d>0)if(this.#A())this.#d-=1;else continue;if(this.#T()){this.#d+=1;continue}switch(this.#o){case 0:this.#P()&&this.#u(1);break;case 1:if(this.#P()){this.#C();let t=7,r=1;this.#E()?(t=2,r=3):this.#g&&(t=2),this.#r(t,r);}break;case 2:this.#S()?this.#u(3):(this.#x()||this.#h()||this.#f())&&this.#u(5);break;case 3:this.#O()?this.#r(4,1):this.#S()&&this.#r(5,1);break;case 4:this.#S()&&this.#r(5,1);break;case 5:this.#y()?this.#p+=1:this.#w()&&(this.#p-=1),this.#k()&&!this.#p?this.#r(6,1):this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 6:this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 7:this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 8:this.#f()&&this.#r(9,1);break;}}this.#t.hostname!==void 0&&this.#t.port===void 0&&(this.#t.port="");}#r(t,r){switch(this.#o){case 0:break;case 1:this.#t.protocol=this.#c();break;case 2:break;case 3:this.#t.username=this.#c();break;case 4:this.#t.password=this.#c();break;case 5:this.#t.hostname=this.#c();break;case 6:this.#t.port=this.#c();break;case 7:this.#t.pathname=this.#c();break;case 8:this.#t.search=this.#c();break;case 9:this.#t.hash=this.#c();break;}this.#o!==0&&t!==10&&([1,2,3,4].includes(this.#o)&&[6,7,8,9].includes(t)&&(this.#t.hostname??=""),[1,2,3,4,5,6].includes(this.#o)&&[8,9].includes(t)&&(this.#t.pathname??=this.#g?"/":""),[1,2,3,4,5,6,7].includes(this.#o)&&t===9&&(this.#t.search??="")),this.#R(t,r);}#R(t,r){this.#o=t,this.#l=this.#e+r,this.#e+=r,this.#s=0;}#b(){this.#e=this.#l,this.#s=0;}#u(t){this.#b(),this.#o=t;}#m(t){return t<0&&(t=this.#n.length-t),t<this.#n.length?this.#n[t]:this.#n[this.#n.length-1]}#a(t,r){let n=this.#m(t);return n.value===r&&(n.type==="CHAR"||n.type==="ESCAPED_CHAR"||n.type==="INVALID_CHAR")}#P(){return this.#a(this.#e,":")}#E(){return this.#a(this.#e+1,"/")&&this.#a(this.#e+2,"/")}#S(){return this.#a(this.#e,"@")}#O(){return this.#a(this.#e,":")}#k(){return this.#a(this.#e,":")}#x(){return this.#a(this.#e,"/")}#h(){if(this.#a(this.#e,"?"))return true;if(this.#n[this.#e].value!=="?")return false;let t=this.#m(this.#e-1);return t.type!=="NAME"&&t.type!=="REGEX"&&t.type!=="CLOSE"&&t.type!=="ASTERISK"}#f(){return this.#a(this.#e,"#")}#T(){return this.#n[this.#e].type=="OPEN"}#A(){return this.#n[this.#e].type=="CLOSE"}#y(){return this.#a(this.#e,"[")}#w(){return this.#a(this.#e,"]")}#c(){let t=this.#n[this.#e],r=this.#m(this.#l).index;return this.#i.substring(r,t.index)}#C(){let t={};Object.assign(t,b),t.encodePart=w;let r=q(this.#c(),void 0,t);this.#g=U(r);}};a(C,"Parser");var V=["protocol","username","password","hostname","port","pathname","search","hash"],O="*";function Se(e,t){if(typeof e!="string")throw new TypeError("parameter 1 is not of type 'string'.");let r=new URL(e,t);return {protocol:r.protocol.substring(0,r.protocol.length-1),username:r.username,password:r.password,hostname:r.hostname,port:r.port,pathname:r.pathname,search:r.search!==""?r.search.substring(1,r.search.length):void 0,hash:r.hash!==""?r.hash.substring(1,r.hash.length):void 0}}a(Se,"extractValues");function R(e,t){return t?I(e):e}a(R,"processBaseURLString");function L(e,t,r){let n;if(typeof t.baseURL=="string")try{n=new URL(t.baseURL),t.protocol===void 0&&(e.protocol=R(n.protocol.substring(0,n.protocol.length-1),r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&(e.username=R(n.username,r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&t.password===void 0&&(e.password=R(n.password,r)),t.protocol===void 0&&t.hostname===void 0&&(e.hostname=R(n.hostname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&(e.port=R(n.port,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&(e.pathname=R(n.pathname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&(e.search=R(n.search.substring(1,n.search.length),r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&t.hash===void 0&&(e.hash=R(n.hash.substring(1,n.hash.length),r));}catch{throw new TypeError(`invalid baseURL '${t.baseURL}'.`)}if(typeof t.protocol=="string"&&(e.protocol=fe(t.protocol,r)),typeof t.username=="string"&&(e.username=oe(t.username,r)),typeof t.password=="string"&&(e.password=ae(t.password,r)),typeof t.hostname=="string"&&(e.hostname=ie(t.hostname,r)),typeof t.port=="string"&&(e.port=le(t.port,e.protocol,r)),typeof t.pathname=="string"){if(e.pathname=t.pathname,n&&!ee(e.pathname,r)){let c=n.pathname.lastIndexOf("/");c>=0&&(e.pathname=R(n.pathname.substring(0,c+1),r)+e.pathname);}e.pathname=ce(e.pathname,e.protocol,r);}return typeof t.search=="string"&&(e.search=se(t.search,r)),typeof t.hash=="string"&&(e.hash=ne(t.hash,r)),e}a(L,"applyInit");function I(e){return e.replace(/([+*?:{}()\\])/g,"\\$1")}a(I,"escapePatternString");function Te(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(Te,"escapeRegexpString");function Ae(e,t){t.delimiter??="/#?",t.prefixes??="./",t.sensitive??=false,t.strict??=false,t.end??=true,t.start??=true,t.endsWith="";let r=".*",n=`[^${Te(t.delimiter)}]+?`,c=/[$_\u200C\u200D\p{ID_Continue}]/u,l="";for(let f=0;f<e.length;++f){let s=e[f];if(s.type===3){if(s.modifier===3){l+=I(s.value);continue}l+=`{${I(s.value)}}${T(s.modifier)}`;continue}let i=s.hasCustomName(),o=!!s.suffix.length||!!s.prefix.length&&(s.prefix.length!==1||!t.prefixes.includes(s.prefix)),h=f>0?e[f-1]:null,p=f<e.length-1?e[f+1]:null;if(!o&&i&&s.type===1&&s.modifier===3&&p&&!p.prefix.length&&!p.suffix.length)if(p.type===3){let A=p.value.length>0?p.value[0]:"";o=c.test(A);}else o=!p.hasCustomName();if(!o&&!s.prefix.length&&h&&h.type===3){let A=h.value[h.value.length-1];o=t.prefixes.includes(A);}o&&(l+="{"),l+=I(s.prefix),i&&(l+=`:${s.name}`),s.type===2?l+=`(${s.value})`:s.type===1?i||(l+=`(${n})`):s.type===0&&(!i&&(!h||h.type===3||h.modifier!==3||o||s.prefix!=="")?l+="*":l+=`(${r})`),s.type===1&&i&&s.suffix.length&&c.test(s.suffix[0])&&(l+="\\"),l+=I(s.suffix),o&&(l+="}"),s.modifier!==3&&(l+=T(s.modifier));}return l}a(Ae,"partsToPattern");var Y=class{#i;#n={};#t={};#e={};#s={};#l=false;constructor(t={},r,n){try{let c;if(typeof r=="string"?c=r:n=r,typeof t=="string"){let i=new C(t);if(i.parse(),t=i.result,c===void 0&&typeof t.protocol!="string")throw new TypeError("A base URL must be provided for a relative constructor string.");t.baseURL=c;}else {if(!t||typeof t!="object")throw new TypeError("parameter 1 is not of type 'string' and cannot convert to dictionary.");if(c)throw new TypeError("parameter 1 is not of type 'string'.")}typeof n>"u"&&(n={ignoreCase:!1});let l={ignoreCase:n.ignoreCase===!0},f={pathname:O,protocol:O,username:O,password:O,hostname:O,port:O,search:O,hash:O};this.#i=L(f,t,!0),z(this.#i.protocol)===this.#i.port&&(this.#i.port="");let s;for(s of V){if(!(s in this.#i))continue;let i={},o=this.#i[s];switch(this.#t[s]=[],s){case "protocol":Object.assign(i,b),i.encodePart=w;break;case "username":Object.assign(i,b),i.encodePart=he;break;case "password":Object.assign(i,b),i.encodePart=ue;break;case "hostname":Object.assign(i,J),_(o)?i.encodePart=K:i.encodePart=j;break;case "port":Object.assign(i,b),i.encodePart=G;break;case "pathname":U(this.#n.protocol)?(Object.assign(i,Q,l),i.encodePart=de):(Object.assign(i,b,l),i.encodePart=pe);break;case "search":Object.assign(i,b,l),i.encodePart=ge;break;case "hash":Object.assign(i,b,l),i.encodePart=me;break}try{this.#s[s]=F(o,i),this.#n[s]=W(this.#s[s],this.#t[s],i),this.#e[s]=Ae(this.#s[s],i),this.#l=this.#l||this.#s[s].some(h=>h.type===2);}catch{throw new TypeError(`invalid ${s} pattern '${this.#i[s]}'.`)}}}catch(c){throw new TypeError(`Failed to construct 'URLPattern': ${c.message}`)}}get[Symbol.toStringTag](){return "URLPattern"}test(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return false;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return false}let c;for(c of V)if(!this.#n[c].exec(n[c]))return false;return true}exec(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return null}let c={};r?c.inputs=[t,r]:c.inputs=[t];let l;for(l of V){let f=this.#n[l].exec(n[l]);if(!f)return null;let s={};for(let[i,o]of this.#t[l].entries())if(typeof o=="string"||typeof o=="number"){let h=f[i+1];s[o]=h;}c[l]={input:n[l]??"",groups:s};}return c}static compareComponent(t,r,n){let c=a((i,o)=>{for(let h of ["type","modifier","prefix","value","suffix"]){if(i[h]<o[h])return -1;if(i[h]===o[h])continue;return 1}return 0},"comparePart"),l=new P(3,"","","","",3),f=new P(0,"","","","",3),s=a((i,o)=>{let h=0;for(;h<Math.min(i.length,o.length);++h){let p=c(i[h],o[h]);if(p)return p}return i.length===o.length?0:c(i[h]??l,o[h]??l)},"comparePartList");return !r.#e[t]&&!n.#e[t]?0:r.#e[t]&&!n.#e[t]?s(r.#s[t],[f]):!r.#e[t]&&n.#e[t]?s([f],n.#s[t]):s(r.#s[t],n.#s[t])}get protocol(){return this.#e.protocol}get username(){return this.#e.username}get password(){return this.#e.password}get hostname(){return this.#e.hostname}get port(){return this.#e.port}get pathname(){return this.#e.pathname}get search(){return this.#e.search}get hash(){return this.#e.hash}get hasRegExpGroups(){return this.#l}};a(Y,"URLPattern");
|
|
388
|
+
const MOBILE_UA = {
|
|
389
|
+
"User-Agent": [
|
|
390
|
+
"Mozilla/5.0 (Linux; Android 10; K)",
|
|
391
|
+
"AppleWebKit/537.36 (KHTML, like Gecko)",
|
|
392
|
+
"Chrome/114.0.0.0 Mobile Safari/537.36"
|
|
393
|
+
].join(" ")
|
|
394
|
+
};
|
|
395
|
+
async function fetchWith(input, options) {
|
|
396
|
+
const requestInit = options.init || {};
|
|
397
|
+
if (options.mobile) {
|
|
398
|
+
Object.assign(requestInit, { headers: new Headers(MOBILE_UA) });
|
|
399
|
+
}
|
|
400
|
+
const r = await fetch(input, requestInit).then((r2) => r2);
|
|
401
|
+
return parseHtml(await r.text());
|
|
402
|
+
}
|
|
403
|
+
const fetchHtml = (input) => fetchWith(input, { });
|
|
648
404
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
return pageLinks.filter((h) => {
|
|
667
|
-
return urlPattern.test(new URL(h, host));
|
|
668
|
-
});
|
|
405
|
+
class InfiniteScroller {
|
|
406
|
+
enabled = true;
|
|
407
|
+
paginationOffset = 1;
|
|
408
|
+
parseData;
|
|
409
|
+
rules;
|
|
410
|
+
observer;
|
|
411
|
+
paginationGenerator;
|
|
412
|
+
constructor(options) {
|
|
413
|
+
this.rules = options.rules;
|
|
414
|
+
this.paginationOffset = this.rules.paginationStrategy.getPaginationOffset();
|
|
415
|
+
Object.assign(this, options);
|
|
416
|
+
if (this.rules.getPaginationData) {
|
|
417
|
+
this.getPaginationData = this.rules.getPaginationData;
|
|
418
|
+
}
|
|
419
|
+
this.paginationGenerator = this.rules.customGenerator || InfiniteScroller.generatorForPaginationStrategy(this.rules.paginationStrategy);
|
|
420
|
+
this.setObserver(this.rules.observable);
|
|
421
|
+
this.setAutoScroll();
|
|
669
422
|
}
|
|
670
|
-
|
|
671
|
-
if (
|
|
672
|
-
|
|
673
|
-
|
|
423
|
+
dispose() {
|
|
424
|
+
if (this.observer) this.observer.dispose();
|
|
425
|
+
}
|
|
426
|
+
setObserver(observable) {
|
|
427
|
+
if (this.observer) this.observer.dispose();
|
|
428
|
+
this.observer = Observer.observeWhile(
|
|
429
|
+
observable,
|
|
430
|
+
this.generatorConsumer,
|
|
431
|
+
this.rules.store.state.delay
|
|
674
432
|
);
|
|
675
|
-
|
|
676
|
-
const last = linksDepaginated.at(-1);
|
|
677
|
-
if (last.pathname !== curr.pathname) curr.pathname = last.pathname;
|
|
678
|
-
return curr;
|
|
433
|
+
return this;
|
|
679
434
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
435
|
+
onScrollCBs = [];
|
|
436
|
+
onScroll(callback, initCall = false) {
|
|
437
|
+
if (initCall) callback(this);
|
|
438
|
+
this.onScrollCBs.push(callback);
|
|
439
|
+
return this;
|
|
440
|
+
}
|
|
441
|
+
_onScroll() {
|
|
442
|
+
this.onScrollCBs.forEach((cb) => {
|
|
443
|
+
cb(this);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
setAutoScroll() {
|
|
447
|
+
const autoScrollWrapper = async () => {
|
|
448
|
+
if (this.rules.store.state.autoScroll) {
|
|
449
|
+
await wait(this.rules.store.state.delay);
|
|
450
|
+
await this.generatorConsumer();
|
|
451
|
+
await autoScrollWrapper();
|
|
696
452
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
453
|
+
};
|
|
454
|
+
autoScrollWrapper();
|
|
455
|
+
this.rules.store.stateSubject.subscribe((type) => {
|
|
456
|
+
if (type?.autoScroll) {
|
|
457
|
+
autoScrollWrapper();
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
generatorConsumer = async () => {
|
|
462
|
+
if (!this.enabled) return false;
|
|
463
|
+
const {
|
|
464
|
+
value: { url, offset },
|
|
465
|
+
done
|
|
466
|
+
} = await this.paginationGenerator.next();
|
|
467
|
+
if (!done && url) {
|
|
468
|
+
await this.doScroll(url, offset);
|
|
469
|
+
}
|
|
470
|
+
return !done;
|
|
471
|
+
};
|
|
472
|
+
async getPaginationData(url) {
|
|
473
|
+
return await fetchHtml(url);
|
|
474
|
+
}
|
|
475
|
+
async doScroll(url, offset) {
|
|
476
|
+
const nextPageHtml = await this.getPaginationData(url);
|
|
477
|
+
const prevScrollPos = document.documentElement.scrollTop;
|
|
478
|
+
this.paginationOffset = Math.max(this.paginationOffset, offset);
|
|
479
|
+
this.parseData?.(nextPageHtml);
|
|
480
|
+
this._onScroll();
|
|
481
|
+
window.scrollTo(0, prevScrollPos);
|
|
482
|
+
if (this.rules.store.state.writeHistory) {
|
|
483
|
+
history.replaceState({}, "", url);
|
|
711
484
|
}
|
|
712
|
-
|
|
713
|
-
|
|
485
|
+
}
|
|
486
|
+
static async *generatorForPaginationStrategy(pstrategy) {
|
|
487
|
+
const _offset = pstrategy.getPaginationOffset();
|
|
488
|
+
const end = pstrategy.getPaginationLast();
|
|
489
|
+
const urlGenerator = pstrategy.getPaginationUrlGenerator();
|
|
490
|
+
for (let offset = _offset; offset <= end; offset++) {
|
|
491
|
+
const url = await urlGenerator(offset);
|
|
492
|
+
yield { url, offset };
|
|
714
493
|
}
|
|
715
494
|
}
|
|
495
|
+
static create(rules) {
|
|
496
|
+
const enabled = rules.store.state.infiniteScrollEnabled;
|
|
497
|
+
rules.store.state.$paginationLast = rules.paginationStrategy.getPaginationLast();
|
|
498
|
+
const infiniteScroller = new InfiniteScroller({
|
|
499
|
+
enabled,
|
|
500
|
+
parseData: rules.dataManager.parseData,
|
|
501
|
+
rules
|
|
502
|
+
}).onScroll(({ paginationOffset }) => {
|
|
503
|
+
rules.store.state.$paginationOffset = paginationOffset;
|
|
504
|
+
}, true);
|
|
505
|
+
rules.store.stateSubject.subscribe(() => {
|
|
506
|
+
infiniteScroller.enabled = rules.store.state.infiniteScrollEnabled;
|
|
507
|
+
});
|
|
508
|
+
return infiniteScroller;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
var Pe=Object.defineProperty;var a=(e,t)=>Pe(e,"name",{value:t,configurable:true});var P=class{type=3;name="";prefix="";value="";suffix="";modifier=3;constructor(t,r,n,c,l,f){this.type=t,this.name=r,this.prefix=n,this.value=c,this.suffix=l,this.modifier=f;}hasCustomName(){return this.name!==""&&typeof this.name!="number"}};a(P,"Part");var Re=/[$_\p{ID_Start}]/u,Ee=/[$_\u200C\u200D\p{ID_Continue}]/u,v=".*";function Oe(e,t){return (t?/^[\x00-\xFF]*$/:/^[\x00-\x7F]*$/).test(e)}a(Oe,"isASCII");function D(e,t=false){let r=[],n=0;for(;n<e.length;){let c=e[n],l=a(function(f){if(!t)throw new TypeError(f);r.push({type:"INVALID_CHAR",index:n,value:e[n++]});},"ErrorOrInvalid");if(c==="*"){r.push({type:"ASTERISK",index:n,value:e[n++]});continue}if(c==="+"||c==="?"){r.push({type:"OTHER_MODIFIER",index:n,value:e[n++]});continue}if(c==="\\"){r.push({type:"ESCAPED_CHAR",index:n++,value:e[n++]});continue}if(c==="{"){r.push({type:"OPEN",index:n,value:e[n++]});continue}if(c==="}"){r.push({type:"CLOSE",index:n,value:e[n++]});continue}if(c===":"){let f="",s=n+1;for(;s<e.length;){let i=e.substr(s,1);if(s===n+1&&Re.test(i)||s!==n+1&&Ee.test(i)){f+=e[s++];continue}break}if(!f){l(`Missing parameter name at ${n}`);continue}r.push({type:"NAME",index:n,value:f}),n=s;continue}if(c==="("){let f=1,s="",i=n+1,o=false;if(e[i]==="?"){l(`Pattern cannot start with "?" at ${i}`);continue}for(;i<e.length;){if(!Oe(e[i],false)){l(`Invalid character '${e[i]}' at ${i}.`),o=true;break}if(e[i]==="\\"){s+=e[i++]+e[i++];continue}if(e[i]===")"){if(f--,f===0){i++;break}}else if(e[i]==="("&&(f++,e[i+1]!=="?")){l(`Capturing groups are not allowed at ${i}`),o=true;break}s+=e[i++];}if(o)continue;if(f){l(`Unbalanced pattern at ${n}`);continue}if(!s){l(`Missing pattern at ${n}`);continue}r.push({type:"REGEX",index:n,value:s}),n=i;continue}r.push({type:"CHAR",index:n,value:e[n++]});}return r.push({type:"END",index:n,value:""}),r}a(D,"lexer");function F(e,t={}){let r=D(e);t.delimiter??="/#?",t.prefixes??="./";let n=`[^${x(t.delimiter)}]+?`,c=[],l=0,f=0,i=new Set,o=a(u=>{if(f<r.length&&r[f].type===u)return r[f++].value},"tryConsume"),h=a(()=>o("OTHER_MODIFIER")??o("ASTERISK"),"tryConsumeModifier"),p=a(u=>{let d=o(u);if(d!==void 0)return d;let{type:g,index:y}=r[f];throw new TypeError(`Unexpected ${g} at ${y}, expected ${u}`)},"mustConsume"),A=a(()=>{let u="",d;for(;d=o("CHAR")??o("ESCAPED_CHAR");)u+=d;return u},"consumeText"),xe=a(u=>u,"DefaultEncodePart"),N=t.encodePart||xe,H="",$=a(u=>{H+=u;},"appendToPendingFixedValue"),M=a(()=>{H.length&&(c.push(new P(3,"","",N(H),"",3)),H="");},"maybeAddPartFromPendingFixedValue"),X=a((u,d,g,y,Z)=>{let m=3;switch(Z){case "?":m=1;break;case "*":m=0;break;case "+":m=2;break}if(!d&&!g&&m===3){$(u);return}if(M(),!d&&!g){if(!u)return;c.push(new P(3,"","",N(u),"",m));return}let S;g?g==="*"?S=v:S=g:S=n;let k=2;S===n?(k=1,S=""):S===v&&(k=0,S="");let E;if(d?E=d:g&&(E=l++),i.has(E))throw new TypeError(`Duplicate name '${E}'.`);i.add(E),c.push(new P(k,E,N(u),S,N(y),m));},"addPart");for(;f<r.length;){let u=o("CHAR"),d=o("NAME"),g=o("REGEX");if(!d&&!g&&(g=o("ASTERISK")),d||g){let m=u??"";t.prefixes.indexOf(m)===-1&&($(m),m=""),M();let S=h();X(m,d,g,"",S);continue}let y=u??o("ESCAPED_CHAR");if(y){$(y);continue}if(o("OPEN")){let m=A(),S=o("NAME"),k=o("REGEX");!S&&!k&&(k=o("ASTERISK"));let E=A();p("CLOSE");let be=h();X(m,S,k,E,be);continue}M(),p("END");}return c}a(F,"parse");function x(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(x,"escapeString");function B(e){return e&&e.ignoreCase?"ui":"u"}a(B,"flags");function q(e,t,r){return W(F(e,r),t,r)}a(q,"stringToRegexp");function T(e){switch(e){case 0:return "*";case 1:return "?";case 2:return "+";case 3:return ""}}a(T,"modifierToString");function W(e,t,r={}){r.delimiter??="/#?",r.prefixes??="./",r.sensitive??=false,r.strict??=false,r.end??=true,r.start??=true,r.endsWith="";let n=r.start?"^":"";for(let s of e){if(s.type===3){s.modifier===3?n+=x(s.value):n+=`(?:${x(s.value)})${T(s.modifier)}`;continue}t&&t.push(s.name);let i=`[^${x(r.delimiter)}]+?`,o=s.value;if(s.type===1?o=i:s.type===0&&(o=v),!s.prefix.length&&!s.suffix.length){s.modifier===3||s.modifier===1?n+=`(${o})${T(s.modifier)}`:n+=`((?:${o})${T(s.modifier)})`;continue}if(s.modifier===3||s.modifier===1){n+=`(?:${x(s.prefix)}(${o})${x(s.suffix)})`,n+=T(s.modifier);continue}n+=`(?:${x(s.prefix)}`,n+=`((?:${o})(?:`,n+=x(s.suffix),n+=x(s.prefix),n+=`(?:${o}))*)${x(s.suffix)})`,s.modifier===0&&(n+="?");}let c=`[${x(r.endsWith)}]|$`,l=`[${x(r.delimiter)}]`;if(r.end)return r.strict||(n+=`${l}?`),r.endsWith.length?n+=`(?=${c})`:n+="$",new RegExp(n,B(r));r.strict||(n+=`(?:${l}(?=${c}))?`);let f=false;if(e.length){let s=e[e.length-1];s.type===3&&s.modifier===3&&(f=r.delimiter.indexOf(s)>-1);}return f||(n+=`(?=${l}|${c})`),new RegExp(n,B(r))}a(W,"partsToRegexp");var b={delimiter:"",prefixes:"",sensitive:true,strict:true},J={delimiter:".",prefixes:"",sensitive:true,strict:true},Q={delimiter:"/",prefixes:"/",sensitive:true,strict:true};function ee(e,t){return e.length?e[0]==="/"?true:!t||e.length<2?false:(e[0]=="\\"||e[0]=="{")&&e[1]=="/":false}a(ee,"isAbsolutePathname");function te(e,t){return e.startsWith(t)?e.substring(t.length,e.length):e}a(te,"maybeStripPrefix");function ke(e,t){return e.endsWith(t)?e.substr(0,e.length-t.length):e}a(ke,"maybeStripSuffix");function _(e){return !e||e.length<2?false:e[0]==="["||(e[0]==="\\"||e[0]==="{")&&e[1]==="["}a(_,"treatAsIPv6Hostname");var re=["ftp","file","http","https","ws","wss"];function U(e){if(!e)return true;for(let t of re)if(e.test(t))return true;return false}a(U,"isSpecialScheme");function ne(e,t){if(e=te(e,"#"),t||e==="")return e;let r=new URL("https://example.com");return r.hash=e,r.hash?r.hash.substring(1,r.hash.length):""}a(ne,"canonicalizeHash");function se(e,t){if(e=te(e,"?"),t||e==="")return e;let r=new URL("https://example.com");return r.search=e,r.search?r.search.substring(1,r.search.length):""}a(se,"canonicalizeSearch");function ie(e,t){return t||e===""?e:_(e)?K(e):j(e)}a(ie,"canonicalizeHostname");function ae(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.password=e,r.password}a(ae,"canonicalizePassword");function oe(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.username=e,r.username}a(oe,"canonicalizeUsername");function ce(e,t,r){if(r||e==="")return e;if(t&&!re.includes(t))return new URL(`${t}:${e}`).pathname;let n=e[0]=="/";return e=new URL(n?e:"/-"+e,"https://example.com").pathname,n||(e=e.substring(2,e.length)),e}a(ce,"canonicalizePathname");function le(e,t,r){return z(t)===e&&(e=""),r||e===""?e:G(e)}a(le,"canonicalizePort");function fe(e,t){return e=ke(e,":"),t||e===""?e:w(e)}a(fe,"canonicalizeProtocol");function z(e){switch(e){case "ws":case "http":return "80";case "wws":case "https":return "443";case "ftp":return "21";default:return ""}}a(z,"defaultPortForProtocol");function w(e){if(e==="")return e;if(/^[-+.A-Za-z0-9]*$/.test(e))return e.toLowerCase();throw new TypeError(`Invalid protocol '${e}'.`)}a(w,"protocolEncodeCallback");function he(e){if(e==="")return e;let t=new URL("https://example.com");return t.username=e,t.username}a(he,"usernameEncodeCallback");function ue(e){if(e==="")return e;let t=new URL("https://example.com");return t.password=e,t.password}a(ue,"passwordEncodeCallback");function j(e){if(e==="")return e;if(/[\t\n\r #%/:<>?@[\]^\\|]/g.test(e))throw new TypeError(`Invalid hostname '${e}'`);let t=new URL("https://example.com");return t.hostname=e,t.hostname}a(j,"hostnameEncodeCallback");function K(e){if(e==="")return e;if(/[^0-9a-fA-F[\]:]/g.test(e))throw new TypeError(`Invalid IPv6 hostname '${e}'`);return e.toLowerCase()}a(K,"ipv6HostnameEncodeCallback");function G(e){if(e===""||/^[0-9]*$/.test(e)&&parseInt(e)<=65535)return e;throw new TypeError(`Invalid port '${e}'.`)}a(G,"portEncodeCallback");function de(e){if(e==="")return e;let t=new URL("https://example.com");return t.pathname=e[0]!=="/"?"/-"+e:e,e[0]!=="/"?t.pathname.substring(2,t.pathname.length):t.pathname}a(de,"standardURLPathnameEncodeCallback");function pe(e){return e===""?e:new URL(`data:${e}`).pathname}a(pe,"pathURLPathnameEncodeCallback");function ge(e){if(e==="")return e;let t=new URL("https://example.com");return t.search=e,t.search.substring(1,t.search.length)}a(ge,"searchEncodeCallback");function me(e){if(e==="")return e;let t=new URL("https://example.com");return t.hash=e,t.hash.substring(1,t.hash.length)}a(me,"hashEncodeCallback");var C=class{#i;#n=[];#t={};#e=0;#s=1;#l=0;#o=0;#d=0;#p=0;#g=false;constructor(t){this.#i=t;}get result(){return this.#t}parse(){for(this.#n=D(this.#i,true);this.#e<this.#n.length;this.#e+=this.#s){if(this.#s=1,this.#n[this.#e].type==="END"){if(this.#o===0){this.#b(),this.#f()?this.#r(9,1):this.#h()?this.#r(8,1):this.#r(7,0);continue}else if(this.#o===2){this.#u(5);continue}this.#r(10,0);break}if(this.#d>0)if(this.#A())this.#d-=1;else continue;if(this.#T()){this.#d+=1;continue}switch(this.#o){case 0:this.#P()&&this.#u(1);break;case 1:if(this.#P()){this.#C();let t=7,r=1;this.#E()?(t=2,r=3):this.#g&&(t=2),this.#r(t,r);}break;case 2:this.#S()?this.#u(3):(this.#x()||this.#h()||this.#f())&&this.#u(5);break;case 3:this.#O()?this.#r(4,1):this.#S()&&this.#r(5,1);break;case 4:this.#S()&&this.#r(5,1);break;case 5:this.#y()?this.#p+=1:this.#w()&&(this.#p-=1),this.#k()&&!this.#p?this.#r(6,1):this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 6:this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 7:this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 8:this.#f()&&this.#r(9,1);break;}}this.#t.hostname!==void 0&&this.#t.port===void 0&&(this.#t.port="");}#r(t,r){switch(this.#o){case 0:break;case 1:this.#t.protocol=this.#c();break;case 2:break;case 3:this.#t.username=this.#c();break;case 4:this.#t.password=this.#c();break;case 5:this.#t.hostname=this.#c();break;case 6:this.#t.port=this.#c();break;case 7:this.#t.pathname=this.#c();break;case 8:this.#t.search=this.#c();break;case 9:this.#t.hash=this.#c();break;}this.#o!==0&&t!==10&&([1,2,3,4].includes(this.#o)&&[6,7,8,9].includes(t)&&(this.#t.hostname??=""),[1,2,3,4,5,6].includes(this.#o)&&[8,9].includes(t)&&(this.#t.pathname??=this.#g?"/":""),[1,2,3,4,5,6,7].includes(this.#o)&&t===9&&(this.#t.search??="")),this.#R(t,r);}#R(t,r){this.#o=t,this.#l=this.#e+r,this.#e+=r,this.#s=0;}#b(){this.#e=this.#l,this.#s=0;}#u(t){this.#b(),this.#o=t;}#m(t){return t<0&&(t=this.#n.length-t),t<this.#n.length?this.#n[t]:this.#n[this.#n.length-1]}#a(t,r){let n=this.#m(t);return n.value===r&&(n.type==="CHAR"||n.type==="ESCAPED_CHAR"||n.type==="INVALID_CHAR")}#P(){return this.#a(this.#e,":")}#E(){return this.#a(this.#e+1,"/")&&this.#a(this.#e+2,"/")}#S(){return this.#a(this.#e,"@")}#O(){return this.#a(this.#e,":")}#k(){return this.#a(this.#e,":")}#x(){return this.#a(this.#e,"/")}#h(){if(this.#a(this.#e,"?"))return true;if(this.#n[this.#e].value!=="?")return false;let t=this.#m(this.#e-1);return t.type!=="NAME"&&t.type!=="REGEX"&&t.type!=="CLOSE"&&t.type!=="ASTERISK"}#f(){return this.#a(this.#e,"#")}#T(){return this.#n[this.#e].type=="OPEN"}#A(){return this.#n[this.#e].type=="CLOSE"}#y(){return this.#a(this.#e,"[")}#w(){return this.#a(this.#e,"]")}#c(){let t=this.#n[this.#e],r=this.#m(this.#l).index;return this.#i.substring(r,t.index)}#C(){let t={};Object.assign(t,b),t.encodePart=w;let r=q(this.#c(),void 0,t);this.#g=U(r);}};a(C,"Parser");var V=["protocol","username","password","hostname","port","pathname","search","hash"],O="*";function Se(e,t){if(typeof e!="string")throw new TypeError("parameter 1 is not of type 'string'.");let r=new URL(e,t);return {protocol:r.protocol.substring(0,r.protocol.length-1),username:r.username,password:r.password,hostname:r.hostname,port:r.port,pathname:r.pathname,search:r.search!==""?r.search.substring(1,r.search.length):void 0,hash:r.hash!==""?r.hash.substring(1,r.hash.length):void 0}}a(Se,"extractValues");function R(e,t){return t?I(e):e}a(R,"processBaseURLString");function L(e,t,r){let n;if(typeof t.baseURL=="string")try{n=new URL(t.baseURL),t.protocol===void 0&&(e.protocol=R(n.protocol.substring(0,n.protocol.length-1),r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&(e.username=R(n.username,r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&t.password===void 0&&(e.password=R(n.password,r)),t.protocol===void 0&&t.hostname===void 0&&(e.hostname=R(n.hostname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&(e.port=R(n.port,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&(e.pathname=R(n.pathname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&(e.search=R(n.search.substring(1,n.search.length),r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&t.hash===void 0&&(e.hash=R(n.hash.substring(1,n.hash.length),r));}catch{throw new TypeError(`invalid baseURL '${t.baseURL}'.`)}if(typeof t.protocol=="string"&&(e.protocol=fe(t.protocol,r)),typeof t.username=="string"&&(e.username=oe(t.username,r)),typeof t.password=="string"&&(e.password=ae(t.password,r)),typeof t.hostname=="string"&&(e.hostname=ie(t.hostname,r)),typeof t.port=="string"&&(e.port=le(t.port,e.protocol,r)),typeof t.pathname=="string"){if(e.pathname=t.pathname,n&&!ee(e.pathname,r)){let c=n.pathname.lastIndexOf("/");c>=0&&(e.pathname=R(n.pathname.substring(0,c+1),r)+e.pathname);}e.pathname=ce(e.pathname,e.protocol,r);}return typeof t.search=="string"&&(e.search=se(t.search,r)),typeof t.hash=="string"&&(e.hash=ne(t.hash,r)),e}a(L,"applyInit");function I(e){return e.replace(/([+*?:{}()\\])/g,"\\$1")}a(I,"escapePatternString");function Te(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(Te,"escapeRegexpString");function Ae(e,t){t.delimiter??="/#?",t.prefixes??="./",t.sensitive??=false,t.strict??=false,t.end??=true,t.start??=true,t.endsWith="";let r=".*",n=`[^${Te(t.delimiter)}]+?`,c=/[$_\u200C\u200D\p{ID_Continue}]/u,l="";for(let f=0;f<e.length;++f){let s=e[f];if(s.type===3){if(s.modifier===3){l+=I(s.value);continue}l+=`{${I(s.value)}}${T(s.modifier)}`;continue}let i=s.hasCustomName(),o=!!s.suffix.length||!!s.prefix.length&&(s.prefix.length!==1||!t.prefixes.includes(s.prefix)),h=f>0?e[f-1]:null,p=f<e.length-1?e[f+1]:null;if(!o&&i&&s.type===1&&s.modifier===3&&p&&!p.prefix.length&&!p.suffix.length)if(p.type===3){let A=p.value.length>0?p.value[0]:"";o=c.test(A);}else o=!p.hasCustomName();if(!o&&!s.prefix.length&&h&&h.type===3){let A=h.value[h.value.length-1];o=t.prefixes.includes(A);}o&&(l+="{"),l+=I(s.prefix),i&&(l+=`:${s.name}`),s.type===2?l+=`(${s.value})`:s.type===1?i||(l+=`(${n})`):s.type===0&&(!i&&(!h||h.type===3||h.modifier!==3||o||s.prefix!=="")?l+="*":l+=`(${r})`),s.type===1&&i&&s.suffix.length&&c.test(s.suffix[0])&&(l+="\\"),l+=I(s.suffix),o&&(l+="}"),s.modifier!==3&&(l+=T(s.modifier));}return l}a(Ae,"partsToPattern");var Y=class{#i;#n={};#t={};#e={};#s={};#l=false;constructor(t={},r,n){try{let c;if(typeof r=="string"?c=r:n=r,typeof t=="string"){let i=new C(t);if(i.parse(),t=i.result,c===void 0&&typeof t.protocol!="string")throw new TypeError("A base URL must be provided for a relative constructor string.");t.baseURL=c;}else {if(!t||typeof t!="object")throw new TypeError("parameter 1 is not of type 'string' and cannot convert to dictionary.");if(c)throw new TypeError("parameter 1 is not of type 'string'.")}typeof n>"u"&&(n={ignoreCase:!1});let l={ignoreCase:n.ignoreCase===!0},f={pathname:O,protocol:O,username:O,password:O,hostname:O,port:O,search:O,hash:O};this.#i=L(f,t,!0),z(this.#i.protocol)===this.#i.port&&(this.#i.port="");let s;for(s of V){if(!(s in this.#i))continue;let i={},o=this.#i[s];switch(this.#t[s]=[],s){case "protocol":Object.assign(i,b),i.encodePart=w;break;case "username":Object.assign(i,b),i.encodePart=he;break;case "password":Object.assign(i,b),i.encodePart=ue;break;case "hostname":Object.assign(i,J),_(o)?i.encodePart=K:i.encodePart=j;break;case "port":Object.assign(i,b),i.encodePart=G;break;case "pathname":U(this.#n.protocol)?(Object.assign(i,Q,l),i.encodePart=de):(Object.assign(i,b,l),i.encodePart=pe);break;case "search":Object.assign(i,b,l),i.encodePart=ge;break;case "hash":Object.assign(i,b,l),i.encodePart=me;break}try{this.#s[s]=F(o,i),this.#n[s]=W(this.#s[s],this.#t[s],i),this.#e[s]=Ae(this.#s[s],i),this.#l=this.#l||this.#s[s].some(h=>h.type===2);}catch{throw new TypeError(`invalid ${s} pattern '${this.#i[s]}'.`)}}}catch(c){throw new TypeError(`Failed to construct 'URLPattern': ${c.message}`)}}get[Symbol.toStringTag](){return "URLPattern"}test(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return false;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return false}let c;for(c of V)if(!this.#n[c].exec(n[c]))return false;return true}exec(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return null}let c={};r?c.inputs=[t,r]:c.inputs=[t];let l;for(l of V){let f=this.#n[l].exec(n[l]);if(!f)return null;let s={};for(let[i,o]of this.#t[l].entries())if(typeof o=="string"||typeof o=="number"){let h=f[i+1];s[o]=h;}c[l]={input:n[l]??"",groups:s};}return c}static compareComponent(t,r,n){let c=a((i,o)=>{for(let h of ["type","modifier","prefix","value","suffix"]){if(i[h]<o[h])return -1;if(i[h]===o[h])continue;return 1}return 0},"comparePart"),l=new P(3,"","","","",3),f=new P(0,"","","","",3),s=a((i,o)=>{let h=0;for(;h<Math.min(i.length,o.length);++h){let p=c(i[h],o[h]);if(p)return p}return i.length===o.length?0:c(i[h]??l,o[h]??l)},"comparePartList");return !r.#e[t]&&!n.#e[t]?0:r.#e[t]&&!n.#e[t]?s(r.#s[t],[f]):!r.#e[t]&&n.#e[t]?s([f],n.#s[t]):s(r.#s[t],n.#s[t])}get protocol(){return this.#e.protocol}get username(){return this.#e.username}get password(){return this.#e.password}get hostname(){return this.#e.hostname}get port(){return this.#e.port}get pathname(){return this.#e.pathname}get search(){return this.#e.search}get hash(){return this.#e.hash}get hasRegExpGroups(){return this.#l}};a(Y,"URLPattern");
|
|
513
|
+
|
|
514
|
+
function parseUrl(s) {
|
|
515
|
+
return new URL(typeof s === "string" ? s : s.href);
|
|
516
|
+
}
|
|
517
|
+
function depaginatePathname(url, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
|
|
518
|
+
const newUrl = new URL(url.toString());
|
|
519
|
+
newUrl.pathname = newUrl.pathname.replace(pathnamePaginationSelector, "/");
|
|
520
|
+
return newUrl;
|
|
521
|
+
}
|
|
522
|
+
function getPaginationLinks(doc = document, url = location.href, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
|
|
523
|
+
const baseUrl = depaginatePathname(parseUrl(url), pathnamePaginationSelector);
|
|
524
|
+
const pathnameStrict = doc instanceof Document;
|
|
525
|
+
const host = doc.baseURI || baseUrl.origin;
|
|
526
|
+
const urlPattern = new Y({
|
|
527
|
+
pathname: pathnameStrict ? `${baseUrl.pathname}*` : "*",
|
|
528
|
+
hostname: baseUrl.hostname
|
|
529
|
+
});
|
|
530
|
+
const pageLinks = [...doc.querySelectorAll("a[href]")].map((a) => a.href).filter((h) => URL.canParse(h));
|
|
531
|
+
return pageLinks.filter((h) => {
|
|
532
|
+
return urlPattern.test(new URL(h, host));
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
function upgradePathname(curr, links, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
|
|
536
|
+
if (pathnamePaginationSelector.test(curr.pathname) || links.length < 1) return curr;
|
|
537
|
+
const linksDepaginated = links.map(
|
|
538
|
+
(l) => depaginatePathname(l, pathnamePaginationSelector)
|
|
539
|
+
);
|
|
540
|
+
if (linksDepaginated.some((l) => l.pathname === curr.pathname)) return curr;
|
|
541
|
+
const last = linksDepaginated.at(-1);
|
|
542
|
+
if (last.pathname !== curr.pathname) curr.pathname = last.pathname;
|
|
543
|
+
return curr;
|
|
544
|
+
}
|
|
716
545
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
546
|
+
class PaginationStrategy {
|
|
547
|
+
doc = document;
|
|
548
|
+
url;
|
|
549
|
+
paginationSelector = ".pagination";
|
|
550
|
+
searchParamSelector = "page";
|
|
551
|
+
static _pathnameSelector = /\/(page\/)?\d+\/?$/;
|
|
552
|
+
pathnameSelector = /\/(\d+)\/?$/;
|
|
553
|
+
dataparamSelector = "[data-parameters *= from]";
|
|
554
|
+
overwritePaginationLast;
|
|
555
|
+
offsetMin = 1;
|
|
556
|
+
constructor(options) {
|
|
557
|
+
if (options) {
|
|
558
|
+
Object.entries(options).forEach(([k, v]) => {
|
|
559
|
+
Object.assign(this, { [k]: v });
|
|
724
560
|
});
|
|
725
|
-
const lastPage = Math.max(...pages, this.offsetMin);
|
|
726
|
-
if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
|
|
727
|
-
return lastPage;
|
|
728
561
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
562
|
+
this.url = parseUrl(options?.url || this.doc.URL);
|
|
563
|
+
}
|
|
564
|
+
getPaginationElement() {
|
|
565
|
+
return this.doc.querySelector(this.paginationSelector);
|
|
566
|
+
}
|
|
567
|
+
get hasPagination() {
|
|
568
|
+
return !!this.getPaginationElement();
|
|
569
|
+
}
|
|
570
|
+
getPaginationOffset() {
|
|
571
|
+
return this.offsetMin;
|
|
572
|
+
}
|
|
573
|
+
getPaginationLast() {
|
|
574
|
+
if (this.overwritePaginationLast) return this.overwritePaginationLast(1);
|
|
575
|
+
return 1;
|
|
576
|
+
}
|
|
577
|
+
getPaginationUrlGenerator() {
|
|
578
|
+
return (_) => this.url.href;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function formatTimeToHHMMSS(timeStr) {
|
|
583
|
+
const pad = (num) => num.toString().padStart(2, "0");
|
|
584
|
+
const h = timeStr.match(/(\d+)\s*h/)?.[1] || "0";
|
|
585
|
+
const m = timeStr.match(/(\d+)\s*mi?n/)?.[1] || "0";
|
|
586
|
+
const s = timeStr.match(/(\d+)\s*sec/)?.[1] || "0";
|
|
587
|
+
return `${pad(+h)}:${pad(+m)}:${pad(+s)}`;
|
|
588
|
+
}
|
|
589
|
+
function timeToSeconds(timeStr) {
|
|
590
|
+
const normalized = /[a-zA-Z]/.test(timeStr) ? formatTimeToHHMMSS(timeStr) : timeStr;
|
|
591
|
+
return normalized.split(":").reverse().reduce((total, unit, index) => total + parseInt(unit, 10) * 60 ** index, 0);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function parseDataParams(str) {
|
|
595
|
+
const paramsStr = decodeURI(str.trim()).split(";");
|
|
596
|
+
return paramsStr.reduce(
|
|
597
|
+
(acc, s) => {
|
|
598
|
+
const parsed = s.match(/([+\w]+):([\w\- ]+)?/);
|
|
599
|
+
if (parsed) {
|
|
600
|
+
const [, key, value] = parsed;
|
|
601
|
+
if (value) {
|
|
602
|
+
key.split("+").forEach((p) => {
|
|
603
|
+
acc[p] = value;
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return acc;
|
|
608
|
+
},
|
|
609
|
+
{}
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
class PaginationStrategyDataParams extends PaginationStrategy {
|
|
614
|
+
getPaginationLast() {
|
|
615
|
+
const links = this.getPaginationElement()?.querySelectorAll(this.dataparamSelector);
|
|
616
|
+
const pages = Array.from(links || [], (l) => {
|
|
617
|
+
const p = l.getAttribute("data-parameters");
|
|
735
618
|
const v = p?.match(/from\w*:(\d+)/)?.[1] || this.offsetMin.toString();
|
|
736
619
|
return parseInt(v);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
620
|
+
});
|
|
621
|
+
const lastPage = Math.max(...pages, this.offsetMin);
|
|
622
|
+
if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
|
|
623
|
+
return lastPage;
|
|
624
|
+
}
|
|
625
|
+
getPaginationOffset() {
|
|
626
|
+
const link = this.getPaginationElement()?.querySelector(
|
|
627
|
+
".prev[data-parameters *= from], .prev [data-parameters *= from]"
|
|
628
|
+
);
|
|
629
|
+
if (!link) return this.offsetMin;
|
|
630
|
+
const p = link.getAttribute("data-parameters");
|
|
631
|
+
const v = p?.match(/from\w*:(\d+)/)?.[1] || this.offsetMin.toString();
|
|
632
|
+
return parseInt(v);
|
|
633
|
+
}
|
|
634
|
+
getPaginationUrlGenerator() {
|
|
635
|
+
const url = new URL(this.url.href);
|
|
636
|
+
const parametersElement = this.getPaginationElement()?.querySelector(
|
|
637
|
+
"a[data-block-id][data-parameters]"
|
|
638
|
+
);
|
|
639
|
+
const block_id = parametersElement?.getAttribute("data-block-id") || "";
|
|
640
|
+
const parameters = parseDataParams(
|
|
641
|
+
parametersElement?.getAttribute("data-parameters") || ""
|
|
642
|
+
);
|
|
643
|
+
const attrs = {
|
|
644
|
+
block_id,
|
|
645
|
+
function: "get_block",
|
|
646
|
+
mode: "async",
|
|
647
|
+
...parameters
|
|
648
|
+
};
|
|
649
|
+
Object.keys(attrs).forEach((k) => {
|
|
650
|
+
url.searchParams.set(k, attrs[k]);
|
|
651
|
+
});
|
|
652
|
+
const paginationUrlGenerator = (n) => {
|
|
753
653
|
Object.keys(attrs).forEach((k) => {
|
|
754
|
-
url.searchParams.set(k,
|
|
654
|
+
k.includes("from") && url.searchParams.set(k, n.toString());
|
|
755
655
|
});
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
url.searchParams.set("_", Date.now().toString());
|
|
761
|
-
return url.href;
|
|
762
|
-
};
|
|
763
|
-
return paginationUrlGenerator;
|
|
764
|
-
}
|
|
765
|
-
static testLinks(doc = document) {
|
|
766
|
-
const dataParamLinks = Array.from(
|
|
767
|
-
doc.querySelectorAll("[data-parameters *= from]")
|
|
768
|
-
);
|
|
769
|
-
return dataParamLinks.length > 0;
|
|
770
|
-
}
|
|
656
|
+
url.searchParams.set("_", Date.now().toString());
|
|
657
|
+
return url.href;
|
|
658
|
+
};
|
|
659
|
+
return paginationUrlGenerator;
|
|
771
660
|
}
|
|
661
|
+
static testLinks(doc = document) {
|
|
662
|
+
const dataParamLinks = Array.from(
|
|
663
|
+
doc.querySelectorAll("[data-parameters *= from]")
|
|
664
|
+
);
|
|
665
|
+
return dataParamLinks.length > 0;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
772
668
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
669
|
+
class PaginationStrategyPathnameParams extends PaginationStrategy {
|
|
670
|
+
extractPage = (a) => {
|
|
671
|
+
const href = typeof a === "string" ? a : a.href;
|
|
672
|
+
const { pathname } = new URL(href, this.doc.baseURI || this.url.origin);
|
|
673
|
+
return parseInt(
|
|
674
|
+
pathname.match(this.pathnameSelector)?.pop() || this.offsetMin.toString()
|
|
675
|
+
);
|
|
676
|
+
};
|
|
677
|
+
static checkLink(link, pathnameSelector = PaginationStrategy._pathnameSelector) {
|
|
678
|
+
return pathnameSelector.test(link.pathname);
|
|
679
|
+
}
|
|
680
|
+
static testLinks(links, options) {
|
|
681
|
+
const result = links.some(
|
|
682
|
+
(h) => PaginationStrategyPathnameParams.checkLink(h, options.pathnameSelector)
|
|
683
|
+
);
|
|
684
|
+
if (result) {
|
|
685
|
+
const pathnamesMatched = links.filter(
|
|
786
686
|
(h) => PaginationStrategyPathnameParams.checkLink(h, options.pathnameSelector)
|
|
787
687
|
);
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
);
|
|
792
|
-
options.url = upgradePathname(
|
|
793
|
-
parseUrl(options.url),
|
|
794
|
-
pathnamesMatched
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
return result;
|
|
798
|
-
}
|
|
799
|
-
getPaginationLast() {
|
|
800
|
-
const links = getPaginationLinks(
|
|
801
|
-
this.getPaginationElement() || document,
|
|
802
|
-
this.url.href,
|
|
803
|
-
this.pathnameSelector
|
|
688
|
+
options.url = upgradePathname(
|
|
689
|
+
parseUrl(options.url),
|
|
690
|
+
pathnamesMatched
|
|
804
691
|
);
|
|
805
|
-
const pages = Array.from(links, this.extractPage);
|
|
806
|
-
const lastPage = Math.max(...pages, this.offsetMin);
|
|
807
|
-
if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
|
|
808
|
-
return lastPage;
|
|
809
|
-
}
|
|
810
|
-
getPaginationOffset() {
|
|
811
|
-
return this.extractPage(this.url.href);
|
|
812
|
-
}
|
|
813
|
-
getPaginationUrlGenerator(url_ = this.url) {
|
|
814
|
-
const url = new URL(url_.href);
|
|
815
|
-
const pathnameSelectorPlaceholder = this.pathnameSelector.toString().replace(/[/|\\|$|?|(|)]+/g, "/");
|
|
816
|
-
if (!this.pathnameSelector.test(url.pathname)) {
|
|
817
|
-
url.pathname = url.pathname.concat(pathnameSelectorPlaceholder.replace(/d\+/, this.offsetMin.toString())).replace(/\/{2,}/g, "/");
|
|
818
|
-
}
|
|
819
|
-
const paginationUrlGenerator = (offset) => {
|
|
820
|
-
url.pathname = url.pathname.replace(
|
|
821
|
-
this.pathnameSelector,
|
|
822
|
-
pathnameSelectorPlaceholder.replace(/d\+/, offset.toString())
|
|
823
|
-
);
|
|
824
|
-
return url.href;
|
|
825
|
-
};
|
|
826
|
-
return paginationUrlGenerator;
|
|
827
692
|
}
|
|
693
|
+
return result;
|
|
828
694
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
`a.active[href *= "${this.searchParamSelector}="]`
|
|
854
|
-
);
|
|
855
|
-
return this.extractPage(link);
|
|
856
|
-
}
|
|
857
|
-
getPaginationUrlGenerator() {
|
|
858
|
-
const url = new URL(this.url.href);
|
|
859
|
-
const paginationUrlGenerator = (offset) => {
|
|
860
|
-
url.searchParams.set(this.searchParamSelector, offset.toString());
|
|
861
|
-
return url.href;
|
|
862
|
-
};
|
|
863
|
-
return paginationUrlGenerator;
|
|
864
|
-
}
|
|
865
|
-
static checkLink(link, searchParamSelector) {
|
|
866
|
-
const searchParamSelectors = ["page", "p"];
|
|
867
|
-
if (searchParamSelector) searchParamSelectors.push(searchParamSelector);
|
|
868
|
-
return searchParamSelectors.some((p) => link.searchParams.get(p) !== null);
|
|
869
|
-
}
|
|
870
|
-
static testLinks(links, searchParamSelector) {
|
|
871
|
-
return links.some(
|
|
872
|
-
(h) => PaginationStrategySearchParams.checkLink(h, searchParamSelector)
|
|
695
|
+
getPaginationLast() {
|
|
696
|
+
const links = getPaginationLinks(
|
|
697
|
+
this.getPaginationElement() || document,
|
|
698
|
+
this.url.href,
|
|
699
|
+
this.pathnameSelector
|
|
700
|
+
);
|
|
701
|
+
const pages = Array.from(links, this.extractPage);
|
|
702
|
+
const lastPage = Math.max(...pages, this.offsetMin);
|
|
703
|
+
if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
|
|
704
|
+
return lastPage;
|
|
705
|
+
}
|
|
706
|
+
getPaginationOffset() {
|
|
707
|
+
return this.extractPage(this.url.href);
|
|
708
|
+
}
|
|
709
|
+
getPaginationUrlGenerator(url_ = this.url) {
|
|
710
|
+
const url = new URL(url_.href);
|
|
711
|
+
const pathnameSelectorPlaceholder = this.pathnameSelector.toString().replace(/[/|\\|$|?|(|)]+/g, "/");
|
|
712
|
+
if (!this.pathnameSelector.test(url.pathname)) {
|
|
713
|
+
url.pathname = url.pathname.concat(pathnameSelectorPlaceholder.replace(/d\+/, this.offsetMin.toString())).replace(/\/{2,}/g, "/");
|
|
714
|
+
}
|
|
715
|
+
const paginationUrlGenerator = (offset) => {
|
|
716
|
+
url.pathname = url.pathname.replace(
|
|
717
|
+
this.pathnameSelector,
|
|
718
|
+
pathnameSelectorPlaceholder.replace(/d\+/, offset.toString())
|
|
873
719
|
);
|
|
874
|
-
|
|
720
|
+
return url.href;
|
|
721
|
+
};
|
|
722
|
+
return paginationUrlGenerator;
|
|
875
723
|
}
|
|
724
|
+
}
|
|
876
725
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
726
|
+
class PaginationStrategySearchParams extends PaginationStrategy {
|
|
727
|
+
extractPage = (a) => {
|
|
728
|
+
const href = typeof a === "string" ? a : a.href;
|
|
729
|
+
const p = new URL(href).searchParams.get(this.searchParamSelector);
|
|
730
|
+
return parseInt(p) || this.offsetMin;
|
|
731
|
+
};
|
|
732
|
+
getPaginationLast() {
|
|
733
|
+
const links = getPaginationLinks(
|
|
734
|
+
this.getPaginationElement() || document,
|
|
735
|
+
this.url.href
|
|
736
|
+
).filter(
|
|
737
|
+
(h) => PaginationStrategySearchParams.checkLink(new URL(h), this.searchParamSelector)
|
|
738
|
+
);
|
|
739
|
+
const pages = links.map(this.extractPage);
|
|
740
|
+
const lastPage = Math.max(...pages, this.offsetMin);
|
|
741
|
+
if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
|
|
742
|
+
return lastPage;
|
|
743
|
+
}
|
|
744
|
+
getPaginationOffset() {
|
|
745
|
+
if (this.doc === document) {
|
|
746
|
+
return this.extractPage(this.url);
|
|
887
747
|
}
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
899
|
-
console.error("Found No Strategy");
|
|
900
|
-
return PaginationStrategy;
|
|
748
|
+
const link = this.getPaginationElement()?.querySelector(
|
|
749
|
+
`a.active[href *= "${this.searchParamSelector}="]`
|
|
750
|
+
);
|
|
751
|
+
return this.extractPage(link);
|
|
752
|
+
}
|
|
753
|
+
getPaginationUrlGenerator() {
|
|
754
|
+
const url = new URL(this.url.href);
|
|
755
|
+
const paginationUrlGenerator = (offset) => {
|
|
756
|
+
url.searchParams.set(this.searchParamSelector, offset.toString());
|
|
757
|
+
return url.href;
|
|
901
758
|
};
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
759
|
+
return paginationUrlGenerator;
|
|
760
|
+
}
|
|
761
|
+
static checkLink(link, searchParamSelector) {
|
|
762
|
+
const searchParamSelectors = ["page", "p"];
|
|
763
|
+
if (searchParamSelector) searchParamSelectors.push(searchParamSelector);
|
|
764
|
+
return searchParamSelectors.some((p) => link.searchParams.get(p) !== null);
|
|
765
|
+
}
|
|
766
|
+
static testLinks(links, searchParamSelector) {
|
|
767
|
+
return links.some(
|
|
768
|
+
(h) => PaginationStrategySearchParams.checkLink(h, searchParamSelector)
|
|
769
|
+
);
|
|
905
770
|
}
|
|
771
|
+
}
|
|
906
772
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
773
|
+
function getPaginationStrategy(options) {
|
|
774
|
+
const _paginationStrategy = new PaginationStrategy(options);
|
|
775
|
+
const pagination = _paginationStrategy.getPaginationElement();
|
|
776
|
+
Object.assign(options, { ..._paginationStrategy });
|
|
777
|
+
const { url, searchParamSelector } = options;
|
|
778
|
+
if (!pagination) {
|
|
779
|
+
return _paginationStrategy;
|
|
780
|
+
}
|
|
781
|
+
if (typeof options.getPaginationUrlGenerator === "function") {
|
|
782
|
+
return new PaginationStrategy(options);
|
|
783
|
+
}
|
|
784
|
+
const pageLinks = getPaginationLinks(pagination, url).map((l) => new URL(l));
|
|
785
|
+
const selectStrategy = () => {
|
|
786
|
+
if (PaginationStrategyDataParams.testLinks(pagination)) {
|
|
787
|
+
return PaginationStrategyDataParams;
|
|
912
788
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
thumbData.title = `${thumbData.title} user:${uploader}`;
|
|
789
|
+
if (PaginationStrategySearchParams.testLinks(pageLinks, searchParamSelector)) {
|
|
790
|
+
return PaginationStrategySearchParams;
|
|
791
|
+
}
|
|
792
|
+
if (PaginationStrategyPathnameParams.testLinks(pageLinks, options)) {
|
|
793
|
+
return PaginationStrategyPathnameParams;
|
|
794
|
+
}
|
|
795
|
+
console.error("Found No Strategy");
|
|
796
|
+
return PaginationStrategy;
|
|
797
|
+
};
|
|
798
|
+
const PaginationStrategyConstructor = selectStrategy();
|
|
799
|
+
const paginationStrategy = new PaginationStrategyConstructor(options);
|
|
800
|
+
return paginationStrategy;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const DefaultScheme = [
|
|
804
|
+
{
|
|
805
|
+
title: "Text Filter",
|
|
806
|
+
collapsed: true,
|
|
807
|
+
content: [
|
|
808
|
+
{ filterExclude: false, label: "exclude" },
|
|
809
|
+
{
|
|
810
|
+
filterExcludeWords: "",
|
|
811
|
+
label: "keywords",
|
|
812
|
+
watch: "filterExclude",
|
|
813
|
+
placeholder: "word, f:full_word, r:RegEx..."
|
|
814
|
+
},
|
|
815
|
+
{ filterInclude: false, label: "include" },
|
|
816
|
+
{
|
|
817
|
+
filterIncludeWords: "",
|
|
818
|
+
label: "keywords",
|
|
819
|
+
watch: "filterInclude",
|
|
820
|
+
placeholder: "word, f:full_word, r:RegEx..."
|
|
946
821
|
}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
822
|
+
]
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
title: "Duration Filter",
|
|
826
|
+
collapsed: true,
|
|
827
|
+
content: [
|
|
828
|
+
{ filterDuration: false, label: "enable" },
|
|
829
|
+
{
|
|
830
|
+
filterDurationFrom: 0,
|
|
831
|
+
watch: "filterDuration",
|
|
832
|
+
label: "from",
|
|
833
|
+
type: "time"
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
filterDurationTo: 600,
|
|
837
|
+
watch: "filterDuration",
|
|
838
|
+
label: "to",
|
|
839
|
+
type: "time"
|
|
950
840
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
841
|
+
]
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
title: "Sort By",
|
|
845
|
+
content: [
|
|
846
|
+
{
|
|
847
|
+
"sort by views": () => {
|
|
955
848
|
}
|
|
956
|
-
|
|
957
|
-
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
"sort by duration": () => {
|
|
958
852
|
}
|
|
959
|
-
return Number.parseInt(querySelectorText(thumb, selector));
|
|
960
853
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
854
|
+
]
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
title: "Privacy Filter",
|
|
858
|
+
content: [
|
|
859
|
+
{ filterPrivate: false, label: "private" },
|
|
860
|
+
{ filterPublic: false, label: "public" },
|
|
861
|
+
{ "check access 🔓": () => {
|
|
862
|
+
} }
|
|
863
|
+
]
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
title: "Advanced",
|
|
867
|
+
content: [
|
|
868
|
+
{
|
|
869
|
+
infiniteScrollEnabled: true,
|
|
870
|
+
label: "infinite scroll"
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
autoScroll: false,
|
|
874
|
+
label: "auto scroll"
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
delay: 250,
|
|
878
|
+
label: "scroll delay"
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
writeHistory: false,
|
|
882
|
+
label: "write history"
|
|
966
883
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
const img = thumb.querySelector("img");
|
|
976
|
-
if (!img) return {};
|
|
977
|
-
result.img = img;
|
|
978
|
-
if (typeof this.getThumbImgDataAttrSelector === "function") {
|
|
979
|
-
result.imgSrc = this.getThumbImgDataAttrSelector(img);
|
|
980
|
-
} else {
|
|
981
|
-
const possibleAttrs = this.getThumbImgDataAttrSelector ? [this.getThumbImgDataAttrSelector].flat() : ["data-src", "src"];
|
|
982
|
-
for (const attr of possibleAttrs) {
|
|
983
|
-
const imgSrc = img.getAttribute(attr);
|
|
984
|
-
if (imgSrc) {
|
|
985
|
-
result.imgSrc = imgSrc;
|
|
986
|
-
img.removeAttribute(attr);
|
|
987
|
-
break;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
if (this.getThumbImgDataAttrDelete) {
|
|
992
|
-
if (this.getThumbImgDataAttrDelete === "auto") {
|
|
993
|
-
removeClassesAndDataAttributes(img, "lazy");
|
|
994
|
-
} else {
|
|
995
|
-
if (this.getThumbImgDataAttrDelete.startsWith(".")) {
|
|
996
|
-
img.classList.remove(this.getThumbImgDataAttrDelete.slice(1));
|
|
997
|
-
} else {
|
|
998
|
-
img.removeAttribute(this.getThumbImgDataAttrDelete);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
if (img.src.includes("data:image")) {
|
|
1002
|
-
result.img.src = "";
|
|
1003
|
-
}
|
|
1004
|
-
if (img.complete && img.naturalWidth > 0) {
|
|
1005
|
-
return {};
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
884
|
+
]
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
title: "Badge",
|
|
888
|
+
content: [
|
|
889
|
+
{
|
|
890
|
+
text: "return `${state.$paginationOffset}/${state.$paginationLast}`",
|
|
891
|
+
vif: "return state.$paginationLast > 1"
|
|
1008
892
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
893
|
+
]
|
|
894
|
+
}
|
|
895
|
+
];
|
|
896
|
+
|
|
897
|
+
const StoreStateDefault = {
|
|
898
|
+
enabled: true,
|
|
899
|
+
collapsed: false,
|
|
900
|
+
darkmode: true,
|
|
901
|
+
$paginationLast: 1,
|
|
902
|
+
$paginationOffset: 1
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
class RulesGlobal {
|
|
906
|
+
delay;
|
|
907
|
+
customGenerator;
|
|
908
|
+
getThumbUrl(thumb) {
|
|
909
|
+
return (thumb.querySelector("a[href]") || thumb).href;
|
|
910
|
+
}
|
|
911
|
+
titleSelector;
|
|
912
|
+
uploaderSelector;
|
|
913
|
+
durationSelector;
|
|
914
|
+
customThumbDataSelectors;
|
|
915
|
+
getThumbDataStrategy = "default";
|
|
916
|
+
getThumbDataCallback;
|
|
917
|
+
getThumbData(thumb) {
|
|
918
|
+
let { titleSelector, uploaderSelector, durationSelector } = this;
|
|
919
|
+
const thumbData = { title: "" };
|
|
920
|
+
if (this.getThumbDataStrategy === "auto-text") {
|
|
921
|
+
const text = sanitizeStr(thumb.innerText);
|
|
922
|
+
thumbData.title = text;
|
|
923
|
+
thumbData.duration = timeToSeconds(text.match(/\d+m|\d+:\d+/)?.[0] || "");
|
|
924
|
+
return thumbData;
|
|
1019
925
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (typeof this.containerSelector === "string") {
|
|
1025
|
-
return document.querySelector(this.containerSelector);
|
|
1026
|
-
}
|
|
1027
|
-
return this.containerSelector();
|
|
926
|
+
if (this.getThumbDataStrategy === "auto-select") {
|
|
927
|
+
titleSelector = "[class *= title],[title]";
|
|
928
|
+
durationSelector = "[class *= duration]";
|
|
929
|
+
uploaderSelector = "[class *= uploader], [class *= user], [class *= name]";
|
|
1028
930
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (this.getThumbsStrategy === "auto") {
|
|
1036
|
-
if (typeof this.containerSelector !== "string") return [];
|
|
1037
|
-
const container = html.querySelector(this.containerSelector);
|
|
1038
|
-
thumbs = [...container?.children || []];
|
|
1039
|
-
}
|
|
1040
|
-
thumbs = Array.from(html.querySelectorAll(this.thumbsSelector));
|
|
1041
|
-
if (typeof this.getThumbsTransform === "function") {
|
|
1042
|
-
thumbs.forEach(this.getThumbsTransform);
|
|
931
|
+
if (this.getThumbDataStrategy === "auto-select") {
|
|
932
|
+
const selected = querySelectorLast(thumb, titleSelector);
|
|
933
|
+
if (selected) {
|
|
934
|
+
thumbData.title = sanitizeStr(selected.innerText);
|
|
935
|
+
} else {
|
|
936
|
+
thumbData.title = sanitizeStr(thumb.innerText);
|
|
1043
937
|
}
|
|
1044
|
-
|
|
938
|
+
} else {
|
|
939
|
+
thumbData.title = querySelectorText(thumb, titleSelector);
|
|
1045
940
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
"filterInclude",
|
|
1050
|
-
"filterExclude",
|
|
1051
|
-
"filterDuration"
|
|
1052
|
-
];
|
|
1053
|
-
animatePreview;
|
|
1054
|
-
storeOptions;
|
|
1055
|
-
createStore() {
|
|
1056
|
-
const config = { ...StoreStateDefault, ...this.storeOptions };
|
|
1057
|
-
this.store = new jabroniOutfit.JabronioStore(config);
|
|
1058
|
-
return this.store;
|
|
941
|
+
if (uploaderSelector) {
|
|
942
|
+
const uploader = querySelectorText(thumb, uploaderSelector);
|
|
943
|
+
thumbData.title = `${thumbData.title} user:${uploader}`;
|
|
1059
944
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
this.schemeOptions,
|
|
1064
|
-
DefaultScheme
|
|
1065
|
-
);
|
|
1066
|
-
this.gui = new jabroniOutfit.JabronioGUI(scheme, this.store);
|
|
1067
|
-
return this.gui;
|
|
945
|
+
if (durationSelector) {
|
|
946
|
+
const duration = timeToSeconds(querySelectorText(thumb, durationSelector));
|
|
947
|
+
thumbData.duration = duration;
|
|
1068
948
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
getPaginationData;
|
|
1074
|
-
resetInfiniteScroller() {
|
|
1075
|
-
this.infiniteScroller?.dispose();
|
|
1076
|
-
if (!this.paginationStrategy.hasPagination) return;
|
|
1077
|
-
this.infiniteScroller = InfiniteScroller.create(this);
|
|
1078
|
-
}
|
|
1079
|
-
gropeStrategy = "all-in-one";
|
|
1080
|
-
gropeInit() {
|
|
1081
|
-
if (!this.gropeStrategy) return;
|
|
1082
|
-
if (this.gropeStrategy === "all-in-one") {
|
|
1083
|
-
this.dataManager?.parseData(this.container, this.container);
|
|
949
|
+
this.getThumbDataCallback?.(thumb, thumbData);
|
|
950
|
+
function getCustomThumbData(selector, type) {
|
|
951
|
+
if (type === "boolean") {
|
|
952
|
+
return !!thumb.querySelector(selector);
|
|
1084
953
|
}
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1087
|
-
this.dataManager.parseData(c, c, true);
|
|
1088
|
-
});
|
|
954
|
+
if (type === "string") {
|
|
955
|
+
return querySelectorText(thumb, selector);
|
|
1089
956
|
}
|
|
957
|
+
return Number.parseInt(querySelectorText(thumb, selector));
|
|
1090
958
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
959
|
+
if (this.customThumbDataSelectors) {
|
|
960
|
+
Object.entries(this.customThumbDataSelectors).forEach(([name, x]) => {
|
|
961
|
+
const data = getCustomThumbData(x.selector, x.type);
|
|
962
|
+
Object.assign(thumbData, { [name]: data });
|
|
963
|
+
});
|
|
1093
964
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
965
|
+
return thumbData;
|
|
966
|
+
}
|
|
967
|
+
getThumbImgDataAttrSelector;
|
|
968
|
+
getThumbImgDataAttrDelete;
|
|
969
|
+
getThumbImgDataStrategy = "default";
|
|
970
|
+
getThumbImgData(thumb) {
|
|
971
|
+
const result = {};
|
|
972
|
+
if (this.getThumbImgDataStrategy === "auto") {
|
|
973
|
+
const img = thumb.querySelector("img");
|
|
974
|
+
if (!img) return {};
|
|
975
|
+
result.img = img;
|
|
976
|
+
if (typeof this.getThumbImgDataAttrSelector === "function") {
|
|
977
|
+
result.imgSrc = this.getThumbImgDataAttrSelector(img);
|
|
978
|
+
} else {
|
|
979
|
+
const possibleAttrs = this.getThumbImgDataAttrSelector ? [this.getThumbImgDataAttrSelector].flat() : ["data-src", "src"];
|
|
980
|
+
for (const attr of possibleAttrs) {
|
|
981
|
+
const imgSrc = img.getAttribute(attr);
|
|
982
|
+
if (imgSrc) {
|
|
983
|
+
result.imgSrc = imgSrc;
|
|
984
|
+
img.removeAttribute(attr);
|
|
985
|
+
break;
|
|
986
|
+
}
|
|
1098
987
|
}
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
if (event === lastEvent) {
|
|
1104
|
-
direction = !direction;
|
|
988
|
+
}
|
|
989
|
+
if (this.getThumbImgDataAttrDelete) {
|
|
990
|
+
if (this.getThumbImgDataAttrDelete === "auto") {
|
|
991
|
+
removeClassesAndDataAttributes(img, "lazy");
|
|
1105
992
|
} else {
|
|
1106
|
-
|
|
1107
|
-
|
|
993
|
+
if (this.getThumbImgDataAttrDelete.startsWith(".")) {
|
|
994
|
+
img.classList.remove(this.getThumbImgDataAttrDelete.slice(1));
|
|
995
|
+
} else {
|
|
996
|
+
img.removeAttribute(this.getThumbImgDataAttrDelete);
|
|
997
|
+
}
|
|
1108
998
|
}
|
|
1109
|
-
if (
|
|
1110
|
-
|
|
1111
|
-
|
|
999
|
+
if (img.src.includes("data:image")) {
|
|
1000
|
+
result.img.src = "";
|
|
1001
|
+
}
|
|
1002
|
+
if (img.complete && img.naturalWidth > 0) {
|
|
1003
|
+
return {};
|
|
1112
1004
|
}
|
|
1113
|
-
});
|
|
1114
|
-
this.store.stateSubject.subscribe((a) => {
|
|
1115
|
-
this.dataManager.applyFilters(a);
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
dataManagerOptions = {};
|
|
1119
|
-
setupDataManager() {
|
|
1120
|
-
this.dataManager = new DataManager(this);
|
|
1121
|
-
if (this.dataManagerOptions) {
|
|
1122
|
-
Object.assign(this.dataManager, this.dataManagerOptions);
|
|
1123
1005
|
}
|
|
1124
|
-
return this.dataManager;
|
|
1125
1006
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1007
|
+
return result;
|
|
1008
|
+
}
|
|
1009
|
+
containerSelector = ".container";
|
|
1010
|
+
containerSelectorLast;
|
|
1011
|
+
intersectionObservableSelector;
|
|
1012
|
+
get intersectionObservable() {
|
|
1013
|
+
return this.intersectionObservableSelector && document.querySelector(this.intersectionObservableSelector);
|
|
1014
|
+
}
|
|
1015
|
+
get observable() {
|
|
1016
|
+
return this.intersectionObservable || this.paginationStrategy.getPaginationElement();
|
|
1017
|
+
}
|
|
1018
|
+
get container() {
|
|
1019
|
+
if (typeof this.containerSelectorLast === "string") {
|
|
1020
|
+
return querySelectorLast(document, this.containerSelectorLast);
|
|
1021
|
+
}
|
|
1022
|
+
if (typeof this.containerSelector === "string") {
|
|
1023
|
+
return document.querySelector(this.containerSelector);
|
|
1141
1024
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1025
|
+
return this.containerSelector();
|
|
1026
|
+
}
|
|
1027
|
+
thumbsSelector = ".thumb";
|
|
1028
|
+
getThumbsStrategy = "default";
|
|
1029
|
+
getThumbsTransform;
|
|
1030
|
+
getThumbs(html) {
|
|
1031
|
+
if (!html) return [];
|
|
1032
|
+
let thumbs;
|
|
1033
|
+
if (this.getThumbsStrategy === "auto") {
|
|
1034
|
+
if (typeof this.containerSelector !== "string") return [];
|
|
1035
|
+
const container = html.querySelector(this.containerSelector);
|
|
1036
|
+
thumbs = [...container?.children || []];
|
|
1037
|
+
}
|
|
1038
|
+
thumbs = Array.from(html.querySelectorAll(this.thumbsSelector));
|
|
1039
|
+
if (typeof this.getThumbsTransform === "function") {
|
|
1040
|
+
thumbs.forEach(this.getThumbsTransform);
|
|
1041
|
+
}
|
|
1042
|
+
return thumbs;
|
|
1043
|
+
}
|
|
1044
|
+
paginationStrategyOptions = {};
|
|
1045
|
+
paginationStrategy;
|
|
1046
|
+
customDataSelectorFns = [
|
|
1047
|
+
"filterInclude",
|
|
1048
|
+
"filterExclude",
|
|
1049
|
+
"filterDuration"
|
|
1050
|
+
];
|
|
1051
|
+
animatePreview;
|
|
1052
|
+
storeOptions;
|
|
1053
|
+
createStore() {
|
|
1054
|
+
const config = { ...StoreStateDefault, ...this.storeOptions };
|
|
1055
|
+
this.store = new jabroniOutfit.JabronioStore(config);
|
|
1056
|
+
return this.store;
|
|
1057
|
+
}
|
|
1058
|
+
schemeOptions = [];
|
|
1059
|
+
createGui() {
|
|
1060
|
+
const scheme = jabroniOutfit.setupScheme(
|
|
1061
|
+
this.schemeOptions,
|
|
1062
|
+
DefaultScheme
|
|
1063
|
+
);
|
|
1064
|
+
this.gui = new jabroniOutfit.JabronioGUI(scheme, this.store);
|
|
1065
|
+
return this.gui;
|
|
1066
|
+
}
|
|
1067
|
+
store;
|
|
1068
|
+
gui;
|
|
1069
|
+
dataManager;
|
|
1070
|
+
infiniteScroller;
|
|
1071
|
+
getPaginationData;
|
|
1072
|
+
resetInfiniteScroller() {
|
|
1073
|
+
this.infiniteScroller?.dispose();
|
|
1074
|
+
if (!this.paginationStrategy.hasPagination) return;
|
|
1075
|
+
this.infiniteScroller = InfiniteScroller.create(this);
|
|
1076
|
+
}
|
|
1077
|
+
gropeStrategy = "all-in-one";
|
|
1078
|
+
gropeInit() {
|
|
1079
|
+
if (!this.gropeStrategy) return;
|
|
1080
|
+
if (this.gropeStrategy === "all-in-one") {
|
|
1081
|
+
this.dataManager?.parseData(this.container, this.container);
|
|
1082
|
+
}
|
|
1083
|
+
if (this.gropeStrategy === "all-in-all") {
|
|
1084
|
+
getCommonParents(this.getThumbs(document.body)).forEach((c) => {
|
|
1085
|
+
this.dataManager.parseData(c, c, true);
|
|
1146
1086
|
});
|
|
1147
|
-
this.mutationObservers = [];
|
|
1148
|
-
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
1149
|
-
this.setupDataManager();
|
|
1150
|
-
this.setupStoreListeners();
|
|
1151
|
-
this.resetInfiniteScroller();
|
|
1152
|
-
this.container && this.animatePreview?.(this.container);
|
|
1153
|
-
this.gropeInit();
|
|
1154
|
-
this.onResetCallback?.();
|
|
1155
|
-
this.resetOn();
|
|
1156
1087
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1088
|
+
}
|
|
1089
|
+
get isEmbedded() {
|
|
1090
|
+
return window.self !== window.top;
|
|
1091
|
+
}
|
|
1092
|
+
setupStoreListeners() {
|
|
1093
|
+
const eventsMap = {
|
|
1094
|
+
"sort by duration": {
|
|
1095
|
+
action: (direction2) => this.dataManager.sortBy("duration", direction2)
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
let lastEvent;
|
|
1099
|
+
let direction = true;
|
|
1100
|
+
this.store.eventSubject.subscribe((event) => {
|
|
1101
|
+
if (event === lastEvent) {
|
|
1102
|
+
direction = !direction;
|
|
1103
|
+
} else {
|
|
1104
|
+
lastEvent = event;
|
|
1105
|
+
direction = true;
|
|
1106
|
+
}
|
|
1107
|
+
if (event in eventsMap) {
|
|
1108
|
+
const ev = eventsMap[event];
|
|
1109
|
+
ev?.action(direction);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
this.store.stateSubject.subscribe((a) => {
|
|
1113
|
+
this.dataManager.applyFilters(a);
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
dataManagerOptions = {};
|
|
1117
|
+
setupDataManager() {
|
|
1118
|
+
this.dataManager = new DataManager(this);
|
|
1119
|
+
if (this.dataManagerOptions) {
|
|
1120
|
+
Object.assign(this.dataManager, this.dataManagerOptions);
|
|
1165
1121
|
}
|
|
1122
|
+
return this.dataManager;
|
|
1166
1123
|
}
|
|
1124
|
+
mutationObservers = [];
|
|
1125
|
+
resetOnPaginationOrContainerDeath = true;
|
|
1126
|
+
resetOn() {
|
|
1127
|
+
if (!this.resetOnPaginationOrContainerDeath) return;
|
|
1128
|
+
const observables = [
|
|
1129
|
+
this.container,
|
|
1130
|
+
this.intersectionObservable || this.paginationStrategy.getPaginationElement()
|
|
1131
|
+
].filter(Boolean);
|
|
1132
|
+
if (observables.length === 0) return;
|
|
1133
|
+
observables.forEach((o) => {
|
|
1134
|
+
const observer = waitForElementToDisappear(o, () => {
|
|
1135
|
+
this.reset();
|
|
1136
|
+
});
|
|
1137
|
+
this.mutationObservers.push(observer);
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
onResetCallback;
|
|
1141
|
+
reset() {
|
|
1142
|
+
this.mutationObservers.forEach((o) => {
|
|
1143
|
+
o.disconnect();
|
|
1144
|
+
});
|
|
1145
|
+
this.mutationObservers = [];
|
|
1146
|
+
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
1147
|
+
this.setupDataManager();
|
|
1148
|
+
this.setupStoreListeners();
|
|
1149
|
+
this.resetInfiniteScroller();
|
|
1150
|
+
this.container && this.animatePreview?.(this.container);
|
|
1151
|
+
this.gropeInit();
|
|
1152
|
+
this.onResetCallback?.();
|
|
1153
|
+
this.resetOn();
|
|
1154
|
+
}
|
|
1155
|
+
constructor(options) {
|
|
1156
|
+
if (this.isEmbedded) throw Error("Embedded is not supported");
|
|
1157
|
+
Object.assign(this, options);
|
|
1158
|
+
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
1159
|
+
this.store = this.createStore();
|
|
1160
|
+
this.gui = this.createGui();
|
|
1161
|
+
this.dataManager = this.setupDataManager();
|
|
1162
|
+
this.reset();
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1167
1165
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
})(jabronioutfit);
|
|
1166
|
+
new RulesGlobal({
|
|
1167
|
+
paginationStrategyOptions: {
|
|
1168
|
+
paginationSelector: "nav[x-data]"
|
|
1169
|
+
},
|
|
1170
|
+
containerSelector: ".grid[x-data]",
|
|
1171
|
+
thumbsSelector: "div:has(> .thumbnail.group)",
|
|
1172
|
+
getThumbImgDataStrategy: "auto",
|
|
1173
|
+
titleSelector: "div > div > a.text-secondary",
|
|
1174
|
+
durationSelector: "div > a > span.text-xs",
|
|
1175
|
+
schemeOptions: ["Text Filter", "Duration Filter", "Badge", "Advanced"]
|
|
1176
|
+
});
|
|
1181
1177
|
|
|
1182
|
-
})();
|
|
1178
|
+
})(jabronioutfit);
|