billy-herrington-utils 1.5.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +2 -2
  2. package/dist/billy-herrington-utils.es.js +5907 -327
  3. package/dist/billy-herrington-utils.es.js.map +1 -1
  4. package/dist/billy-herrington-utils.umd.js +5911 -331
  5. package/dist/billy-herrington-utils.umd.js.map +1 -1
  6. package/dist/index.d.ts +110 -103
  7. package/package.json +7 -5
  8. package/src/index.ts +18 -5
  9. package/src/types/globals.d.ts +0 -2
  10. package/src/userscripts/data-manager/data-filter.ts +110 -0
  11. package/src/userscripts/data-manager/index.ts +77 -174
  12. package/src/userscripts/infinite-scroll/index.ts +72 -71
  13. package/src/userscripts/pagination-parsing/index.ts +21 -29
  14. package/src/userscripts/pagination-parsing/pagination-strategies/PaginationStrategy.ts +4 -12
  15. package/src/userscripts/pagination-parsing/pagination-strategies/PaginationStrategyDataParams.ts +11 -2
  16. package/src/userscripts/pagination-parsing/pagination-strategies/PaginationStrategyPathnameParams.ts +29 -2
  17. package/src/userscripts/pagination-parsing/pagination-strategies/PaginationStrategySearchParams.ts +15 -7
  18. package/src/userscripts/pagination-parsing/pagination-strategies/PaginationStrategyTrash.ts +9 -12
  19. package/src/userscripts/pagination-parsing/pagination-strategies/index.ts +1 -1
  20. package/src/userscripts/pagination-parsing/pagination-utils/index.ts +36 -7
  21. package/src/userscripts/router/router.ts +71 -0
  22. package/src/userscripts/rules/index.ts +227 -3
  23. package/src/userscripts/types/index.ts +19 -0
  24. package/src/utils/arrays/index.ts +3 -1
  25. package/src/utils/async/index.ts +22 -6
  26. package/src/utils/dom/index.ts +35 -68
  27. package/src/utils/dom/observers.ts +76 -0
  28. package/src/utils/events/index.ts +9 -2
  29. package/src/utils/fetch/index.ts +14 -7
  30. package/src/utils/objects/index.ts +25 -0
  31. package/src/utils/observers/index.ts +8 -2
  32. package/src/utils/parsers/index.ts +18 -11
  33. package/src/utils/strings/index.ts +5 -5
  34. package/src/utils/strings/regexes.ts +31 -0
  35. package/src/utils/userscript/index.ts +10 -0
  36. package/src/userscripts/jabroni-outfit-wrap/index.ts +0 -40
package/dist/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ import { JabronioGUI } from 'jabroni-outfit';
2
+ import { JabronioStore } from 'jabroni-outfit';
3
+ import { JabroniTypes } from 'jabroni-outfit';
4
+ import { setupScheme } from 'jabroni-outfit';
5
+ import { StoreState } from 'jabroni-outfit';
6
+
1
7
  export declare class AsyncPool {
2
8
  private max;
3
9
  private pool;
@@ -24,40 +30,29 @@ export declare function circularShift(n: number, c?: number, s?: number): number
24
30
 
25
31
  export declare function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>): Promise<void[]>;
26
32
 
27
- export declare function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element): void;
28
-
29
- export declare function createInfiniteScroller(store: JabroniStore, parseData: (document: HTMLElement) => void, rules: IRules_2): InfiniteScroller;
30
-
31
- declare interface DataFilterState {
32
- filterPublic: boolean;
33
- filterPrivate: boolean;
34
- filterHD: boolean;
35
- filterDuration: boolean;
36
- filterDurationFrom: number;
37
- filterDurationTo: number;
38
- filterExclude: boolean;
39
- filterExcludeWords: string;
40
- filterInclude: boolean;
41
- filterIncludeWords: string;
42
- }
33
+ export declare function copyAttributes(target: HTMLElement, source: HTMLElement): void;
34
+
35
+ declare type CustomSelector<R> = {
36
+ handle: (el: DataElement, state: StoreState, $preDefineResult?: R) => boolean;
37
+ $preDefine?: (state: StoreState) => R;
38
+ };
39
+
40
+ declare type DataElement = Record<string, string | number | boolean | HTMLElement>;
43
41
 
44
42
  export declare class DataManager {
45
43
  private rules;
46
44
  private state;
47
45
  private data;
48
46
  private lazyImgLoader;
49
- dataFilters: {
50
- [key: string]: () => FilterFunction;
51
- };
52
- constructor(rules: IRules, state: DataFilterState);
53
- static filterDSLToRegex(str: string): RegExp[];
47
+ private dataFilter;
48
+ constructor(rules: RulesGlobal, state: StoreState);
54
49
  isFiltered(el: HTMLElement): boolean;
55
- applyFilters: (filters: {
50
+ applyFilters: (filters?: {
56
51
  [key: string]: boolean;
57
52
  }, offset?: number) => void;
58
53
  filterAll: (offset?: number) => void;
59
54
  parseData: (html: HTMLElement, container?: HTMLElement, removeDuplicates?: boolean, shouldLazify?: boolean) => void;
60
- sort(propName: string): void;
55
+ sortBy<K extends keyof DataElement>(key: K): void;
61
56
  }
62
57
 
63
58
  export declare function downloader(options?: {
@@ -73,117 +68,70 @@ export declare const fetchHtml: (url: string) => Promise<HTMLElement>;
73
68
 
74
69
  export declare const fetchText: (url: string) => Promise<string>;
75
70
 
76
- export declare function fetchWith(url: string, options?: Record<string, boolean>): Promise<string | HTMLElement>;
71
+ export declare function fetchWith(url: string, options?: {
72
+ html?: boolean;
73
+ mobile?: boolean;
74
+ }): Promise<string | HTMLElement>;
77
75
 
78
- declare type FilterFunction = (v: FilterInput) => FilterResult;
76
+ export declare function findNextSibling(el: HTMLElement): Element | null;
79
77
 
80
- declare type FilterInput = Record<string, string | number | boolean | HTMLElement>;
81
-
82
- declare interface FilterResult {
83
- tag: string;
84
- condition: boolean;
85
- }
86
-
87
- export declare function findNextSibling(el: HTMLElement | Element): Element | null;
88
-
89
- declare interface GeneratorResult {
78
+ declare type GeneratorResult = {
90
79
  url: string;
91
80
  offset: number;
92
- }
81
+ };
93
82
 
94
- export declare function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element>;
83
+ export declare function getAllUniqueParents(elements: HTMLCollection | HTMLElement[]): HTMLElement[];
95
84
 
96
- export declare function getPaginationStrategy(options: IPaginationStrategy): PaginationStrategy;
97
-
98
- declare interface IInfiniteScroller {
99
- delay?: number;
100
- enabled?: boolean;
101
- writeHistory?: boolean;
102
- paginationOffset: number;
103
- paginationLast: number;
104
- paginationElement: HTMLElement;
105
- paginationUrlGenerator: (offset: number) => string;
106
- parseData: (document: HTMLElement) => void;
107
- intersectionObservable?: HTMLElement;
108
- alternativeGenerator?: () => OffsetGenerator;
109
- }
85
+ export declare function getPaginationStrategy(options: Partial<PaginationStrategy>): PaginationStrategy;
110
86
 
111
87
  export declare class InfiniteScroller {
112
- paginationGenerator: OffsetGenerator;
113
88
  enabled: boolean;
114
89
  delay: number;
115
90
  paginationOffset: number;
116
- paginationLast: number;
117
91
  writeHistory: boolean;
118
- private parseData;
119
- constructor({ enabled, delay, writeHistory, paginationOffset, paginationLast, paginationElement, paginationUrlGenerator, parseData, alternativeGenerator, intersectionObservable, }: IInfiniteScroller);
92
+ parseData?: (document: HTMLElement) => void;
93
+ rules: RulesGlobal;
94
+ private observer?;
95
+ private paginationGenerator;
96
+ constructor(options: InfiniteScrollerOptions);
97
+ dispose(): void;
98
+ setObserver(observable: HTMLElement): this;
120
99
  private onScrollCBs;
121
100
  onScroll(callback: (scroller: InfiniteScroller) => void, initCall?: boolean): this;
122
101
  private _onScroll;
123
102
  generatorConsumer: () => Promise<boolean>;
124
- static createPaginationGenerator(currentPage: number, totalPages: number, generateURL: (offset: number) => string): OffsetGenerator;
125
- }
126
-
127
- declare interface IPaginationStrategy {
128
- url?: URL | Location | string;
129
- doc?: Document | HTMLElement;
130
- paginationSelector?: string;
131
- fixPaginationLast?: (n: number, offset?: number) => number;
132
- pathnameSelector?: RegExp;
133
- searchParamSelector?: string;
134
- offsetMin?: number;
135
- }
136
-
137
- declare interface IRules {
138
- getThumbs: (html: HTMLElement) => HTMLElement[];
139
- getThumbUrl: (thumbElement: HTMLElement) => string;
140
- getThumbData: (thumbElement: HTMLElement) => {
141
- title: string;
142
- duration: number;
143
- };
144
- getThumbImgData: (thumbElement: HTMLElement) => {
145
- img: HTMLElement;
146
- imgSrc: string;
147
- };
148
- container: HTMLElement;
149
- isPrivate: (element: HTMLElement) => boolean;
150
- isHD: (element: HTMLElement) => boolean;
103
+ doScroll(url: string, offset: number): Promise<void>;
104
+ private createPaginationGenerator;
105
+ static create(store: JabronioStore, rules: RulesGlobal, parseData: (document: HTMLElement) => void): InfiniteScroller;
151
106
  }
152
107
 
153
- declare interface IRules_2 {
154
- paginationStrategy: PaginationStrategy;
155
- delay?: number;
156
- }
108
+ declare type InfiniteScrollerOptions = Pick<InfiniteScroller, 'rules'> & Partial<InfiniteScroller>;
157
109
 
158
110
  export declare function isMob(): boolean;
159
111
 
160
- declare interface JabroniStore {
161
- state: Record<string, boolean | string | number>;
162
- localState: Record<string, boolean | string | number>;
163
- subscribe: (callback: () => void) => void;
164
- }
165
-
166
112
  export declare class LazyImgLoader {
167
113
  lazyImgObserver: Observer;
168
114
  private attributeName;
169
115
  constructor(shouldDelazify: (target: Element) => boolean);
170
- lazify(_target: Element, img: HTMLImageElement, imgSrc: string): void;
116
+ lazify(_target: Element, img?: HTMLImageElement, imgSrc?: string): void;
171
117
  delazify: (target: HTMLImageElement) => void;
172
118
  }
173
119
 
174
- export declare function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void;
120
+ export declare function listenEvents(dom: HTMLElement, events: Array<string>, callback: (e: Event) => void): void;
175
121
 
176
122
  export declare const MOBILE_UA: string;
177
123
 
178
- export declare function objectToFormData(object: Record<string, number | boolean | string>): FormData;
124
+ export declare function objectToFormData<T extends {}>(obj: T): FormData;
179
125
 
180
126
  export declare class Observer {
181
127
  private callback;
182
128
  observer: IntersectionObserver;
129
+ private timeout;
183
130
  constructor(callback: (entry: Element) => void);
184
131
  observe(target: Element): void;
185
132
  throttle(target: Element, throttleTime: number): void;
186
133
  handleIntersection(entries: Iterable<IntersectionObserverEntry>): void;
134
+ dispose(): void;
187
135
  static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number): Observer;
188
136
  }
189
137
 
@@ -194,11 +142,13 @@ export declare class PaginationStrategy {
194
142
  url: URL;
195
143
  paginationSelector: string;
196
144
  searchParamSelector: string;
145
+ static _pathnameSelector: RegExp;
197
146
  pathnameSelector: RegExp;
147
+ dataparamSelector: string;
198
148
  fixPaginationLast?: (n: number, offset?: number) => number;
199
149
  offsetMin: number;
200
- constructor(options?: IPaginationStrategy);
201
- getPaginationElement(): Element | null;
150
+ constructor(options?: Partial<PaginationStrategy>);
151
+ getPaginationElement(): HTMLElement | null;
202
152
  get hasPagination(): boolean;
203
153
  getPaginationOffset(): number;
204
154
  getPaginationLast(): number;
@@ -209,10 +159,13 @@ export declare class PaginationStrategyDataParams extends PaginationStrategy {
209
159
  getPaginationLast(): number;
210
160
  getPaginationOffset(): number;
211
161
  getPaginationUrlGenerator(): (n: number) => string;
162
+ static testLinks(doc?: HTMLElement | Document): boolean;
212
163
  }
213
164
 
214
165
  export declare class PaginationStrategyPathnameParams extends PaginationStrategy {
215
166
  extractPage: (a: HTMLAnchorElement | Location | string) => number;
167
+ static checkLink(link: URL, pathnameSelector?: RegExp): boolean;
168
+ static testLinks(links: URL[], options: Partial<PaginationStrategy>): boolean;
216
169
  getPaginationLast(): number;
217
170
  getPaginationOffset(): number;
218
171
  getPaginationUrlGenerator(url_?: URL): (offset: number) => string;
@@ -220,10 +173,11 @@ export declare class PaginationStrategyPathnameParams extends PaginationStrategy
220
173
 
221
174
  export declare class PaginationStrategySearchParams extends PaginationStrategy {
222
175
  extractPage: (a: HTMLAnchorElement | Location | URL | string) => number;
223
- static checkLink(link: URL, searchParamSelector?: string): boolean;
224
176
  getPaginationLast(): number;
225
177
  getPaginationOffset(): number;
226
178
  getPaginationUrlGenerator(): (offset: number) => string;
179
+ static checkLink(link: URL, searchParamSelector?: string): boolean;
180
+ static testLinks(links: URL[], searchParamSelector?: string): boolean;
227
181
  }
228
182
 
229
183
  export declare function parseCSSUrl(s: string): string;
@@ -234,13 +188,64 @@ export declare function parseDom(html: string): HTMLElement;
234
188
 
235
189
  export declare function parseIntegerOr(n: string | number, or: number): number;
236
190
 
191
+ export declare function querySelectorText(el: HTMLElement, selector?: string): string;
192
+
237
193
  export declare function range(size: number, startAt?: number, step?: number): number[];
238
194
 
239
- export declare function replaceElementTag(e: HTMLElement | Element, tagName: string): HTMLElement;
195
+ export declare function replaceElementTag(e: HTMLElement, tagName: string): HTMLElement;
196
+
197
+ export declare class RulesGlobal {
198
+ delay?: number;
199
+ alternativeGenerator?: () => OffsetGenerator;
200
+ getThumbUrl(thumb: HTMLElement | HTMLAnchorElement): string;
201
+ titleSelector: undefined | string;
202
+ uploaderSelector: undefined | string;
203
+ durationSelector: undefined | string;
204
+ getThumbDataStrategy: 'default' | 'auto-select' | 'auto-text';
205
+ getThumbDataCallback?: (thumb: HTMLElement, thumbData: ThumbData) => void;
206
+ getThumbData(thumb: HTMLElement): ThumbData;
207
+ getThumbImgDataAttrSelector: string | undefined;
208
+ getThumbImgDataStrategy: 'default' | 'auto';
209
+ getThumbImgData(thumb: HTMLElement): {
210
+ img?: HTMLImageElement;
211
+ imgSrc?: string;
212
+ };
213
+ containerSelector: string | (() => HTMLElement);
214
+ intersectionObservable?: HTMLElement;
215
+ get container(): HTMLElement;
216
+ thumbsSelector: string;
217
+ getThumbsStrategy: 'default' | 'auto';
218
+ getThumbs(html: HTMLElement): HTMLElement[];
219
+ paginationStrategy: PaginationStrategy;
220
+ get observable(): HTMLElement;
221
+ mutationObservers: MutationObserver[];
222
+ reset(): void;
223
+ resetOnPaginationOrContainerDeath: boolean;
224
+ resetOn(): void;
225
+ customSelectors: Record<string, CustomSelector<any>>;
226
+ animatePreview?: (doc?: HTMLElement) => void;
227
+ storeOptions?: JabroniTypes.StoreStateOptions;
228
+ customScheme?: JabroniTypes.SchemeInput;
229
+ defaultSchemeOptions: Parameters<typeof setupScheme>[0];
230
+ store: JabronioStore;
231
+ scheme: JabroniTypes.SchemeInput;
232
+ gui: JabronioGUI;
233
+ dataManager: DataManager;
234
+ infiniteScroller: InfiniteScroller;
235
+ private resetInfiniteScroller;
236
+ initialGrope: 'all-in-one' | 'all-in-all' | undefined;
237
+ gropeInit(): void;
238
+ constructor();
239
+ }
240
240
 
241
241
  export declare function sanitizeStr(s: string): string;
242
242
 
243
- export declare function stringToWords(s: string): Array<string>;
243
+ export declare function splitWith(s: string, c?: string): Array<string>;
244
+
245
+ declare type ThumbData = {
246
+ title: string;
247
+ duration?: number;
248
+ };
244
249
 
245
250
  export declare class Tick {
246
251
  private delay;
@@ -256,10 +261,12 @@ export declare function timeToSeconds(t: string): number;
256
261
 
257
262
  export declare function wait(milliseconds: number): Promise<unknown>;
258
263
 
259
- export declare function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void;
264
+ export declare function waitForElementToAppear(parent: HTMLElement, selector: string, callback: (el: Element) => void): MutationObserver;
265
+
266
+ export declare function waitForElementToDisappear(observable: HTMLElement, callback: () => void): MutationObserver;
260
267
 
261
- export declare function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void, throttle?: number, times?: number, options?: Record<string, boolean>): MutationObserver;
268
+ export declare function watchDomChangesWithThrottle(element: HTMLElement, callback: () => void, throttle?: number, times?: number, options?: MutationObserverInit): MutationObserver;
262
269
 
263
- export declare function watchElementChildrenCount(element: HTMLElement | Element, callback: (observer: MutationObserver, count: number) => void): void;
270
+ export declare function watchElementChildrenCount(element: HTMLElement, callback: (observer: MutationObserver, count: number) => void): MutationObserver;
264
271
 
265
272
  export { }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "billy-herrington-utils",
3
3
  "description": "daddy told us not to be ashamed of our utils",
4
- "version": "1.5.9",
4
+ "version": "2.0.0",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "utils",
@@ -26,9 +26,9 @@
26
26
  "unpkg": "dist/billy-herrington-utils.es.js",
27
27
  "exports": {
28
28
  ".": {
29
+ "types": "./dist/index.d.ts",
29
30
  "import": "./dist/billy-herrington-utils.es.js",
30
- "require": "./dist/billy-herrington-utils.umd.js",
31
- "types": "./dist/index.d.ts"
31
+ "require": "./dist/billy-herrington-utils.umd.js"
32
32
  }
33
33
  },
34
34
  "files": [
@@ -41,8 +41,10 @@
41
41
  "preview": "vite preview"
42
42
  },
43
43
  "devDependencies": {
44
+ "@types/tampermonkey": "^5.0.5",
45
+ "jabroni-outfit": "^2.0.92",
44
46
  "typescript": "^5.5.3",
45
- "vite": "^5.4.0",
47
+ "vite": "^6.4.1",
46
48
  "vite-plugin-dts": "^4.0.3"
47
49
  }
48
- }
50
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export { DataManager } from './userscripts/data-manager';
2
2
  export { InfiniteScroller } from './userscripts/infinite-scroll';
3
- export { createInfiniteScroller } from './userscripts/jabroni-outfit-wrap';
4
3
  export { getPaginationStrategy } from './userscripts/pagination-parsing';
5
4
  export {
6
5
  PaginationStrategy,
@@ -8,6 +7,7 @@ export {
8
7
  PaginationStrategyPathnameParams,
9
8
  PaginationStrategySearchParams,
10
9
  } from './userscripts/pagination-parsing/pagination-strategies';
10
+ export { RulesGlobal } from './userscripts/rules';
11
11
  export { chunks, range } from './utils/arrays';
12
12
  export { AsyncPool, computeAsyncOneAtTime, wait } from './utils/async';
13
13
  export { isMob } from './utils/device';
@@ -18,14 +18,27 @@ export {
18
18
  findNextSibling,
19
19
  getAllUniqueParents,
20
20
  parseDom,
21
+ querySelectorText,
21
22
  replaceElementTag,
22
- waitForElementExists,
23
+ waitForElementToAppear,
24
+ waitForElementToDisappear,
23
25
  watchDomChangesWithThrottle,
24
26
  watchElementChildrenCount,
25
27
  } from './utils/dom';
26
28
  export { listenEvents, Tick } from './utils/events';
27
- export { fetchHtml, fetchText, fetchWith, MOBILE_UA, objectToFormData } from './utils/fetch';
29
+ export {
30
+ fetchHtml,
31
+ fetchText,
32
+ fetchWith,
33
+ MOBILE_UA,
34
+ objectToFormData,
35
+ } from './utils/fetch';
28
36
  export { circularShift } from './utils/math';
29
37
  export { LazyImgLoader, Observer } from './utils/observers';
30
- export { parseCSSUrl, parseDataParams, parseIntegerOr, timeToSeconds } from './utils/parsers';
31
- export { sanitizeStr, stringToWords } from './utils/strings';
38
+ export {
39
+ parseCSSUrl,
40
+ parseDataParams,
41
+ parseIntegerOr,
42
+ timeToSeconds,
43
+ } from './utils/parsers';
44
+ export { sanitizeStr, splitWith } from './utils/strings';
@@ -1,2 +0,0 @@
1
- declare var GM_addStyle: (css: string) => void;
2
- declare var unsafeWindow: Window & typeof globalThis;
@@ -0,0 +1,110 @@
1
+ import type { StoreState } from 'jabroni-outfit';
2
+ import { RegexFilter } from '../../utils/strings/regexes';
3
+ import type { RulesGlobal } from '../rules';
4
+ import type { DataElement } from '.';
5
+
6
+ export type CustomSelector<R> = {
7
+ handle: (el: DataElement, state: StoreState, $preDefineResult?: R) => boolean;
8
+ $preDefine?: (state: StoreState) => R;
9
+ };
10
+
11
+ interface FilterResult {
12
+ tag: string;
13
+ condition: boolean;
14
+ }
15
+
16
+ export type FilterFunction = (v: DataElement) => FilterResult;
17
+
18
+ export class DataFilter {
19
+ public filters = new Map<string, () => FilterFunction>();
20
+
21
+ constructor(
22
+ private rules: RulesGlobal,
23
+ private state: StoreState,
24
+ ) {
25
+ this.registerFilters(DataFilter.customFiltersDefault);
26
+ this.registerFilters(rules.customSelectors);
27
+ this.applyCSSFilters();
28
+ }
29
+
30
+ public applyCSSFilters() {
31
+ Object.keys(this.filters).forEach((name) => {
32
+ const className = `.filter-${name.toLowerCase().slice(6)}`;
33
+ GM_addStyle(`${className} { display: none !important; content-visibility: auto; }`);
34
+ });
35
+ }
36
+
37
+ public registerFilters(customFilters: Record<string, CustomSelector<any>>) {
38
+ Object.entries(customFilters).forEach(([k, v]) => {
39
+ if (!Object.hasOwn(this.rules.customSelectors, k)) {
40
+ this.rules.customSelectors[k] = v;
41
+ }
42
+ this.registerFilter(k);
43
+ });
44
+ }
45
+
46
+ public registerFilter(CustomSelectorName: string) {
47
+ const handler = this.rules.customSelectors[CustomSelectorName];
48
+
49
+ const fn = (): FilterFunction => {
50
+ const preDefined = handler.$preDefine?.(this.state);
51
+
52
+ return (v: DataElement) => {
53
+ const result = handler.handle(v, this.state, preDefined);
54
+
55
+ return {
56
+ condition: result,
57
+ tag: `filter-${CustomSelectorName}`,
58
+ };
59
+ };
60
+ };
61
+
62
+ this.filters.set(CustomSelectorName, fn);
63
+ }
64
+
65
+ static customFiltersDefault: Record<string, CustomSelector<any>> = {
66
+ isPrivate: {
67
+ handle(el, state) {
68
+ const isPrivate = !!(el.element as HTMLElement).querySelector('.private');
69
+ return (state.filterPrivate as boolean) && isPrivate;
70
+ },
71
+ },
72
+ isPublic: {
73
+ handle(el, state) {
74
+ const isPublic = !!(el.element as HTMLElement).querySelector('.public');
75
+ return (state.filterPublic as boolean) && isPublic;
76
+ },
77
+ },
78
+ filterDuration: {
79
+ handle(el, state, preDefined) {
80
+ const d = el.duration as number;
81
+ const notInRange = d < (preDefined.from as number) || d > (preDefined.to as number);
82
+ return (state.filterDuration as boolean) && notInRange;
83
+ },
84
+ $preDefine: (state) => {
85
+ const f = (x: number) => (state.filterDurationMinutes ? x * 60 : x);
86
+ const from = f(state.filterDurationFrom as number);
87
+ const to = f(state.filterDurationTo as number);
88
+ return { from, to };
89
+ },
90
+ },
91
+ filterExclude: {
92
+ handle(el, state, searchFilter) {
93
+ return (
94
+ (state.filterExclude as boolean) &&
95
+ (searchFilter as RegexFilter).hasNone(el.title as string)
96
+ );
97
+ },
98
+ $preDefine: (state) => new RegexFilter(state.filterExcludeWords as string),
99
+ },
100
+ filterInclude: {
101
+ handle(el, state, searchFilter) {
102
+ return (
103
+ (state.filterInclude as boolean) &&
104
+ (searchFilter as RegexFilter).hasEvery(el.title as string)
105
+ );
106
+ },
107
+ $preDefine: (state) => new RegexFilter(state.filterIncludeWords as string),
108
+ },
109
+ };
110
+ }