mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-28 00:42:08 +08:00
* feat(proxy): unify filter search box and sync filter options * docs: fix JSDoc placement * refactor(search): unify string matcher and stabilize regex filtering * fix(search): treat invalid regex as matching nothing * docs: update changelog to include advanced filter search feature for proxy page --------- Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
export type SearchMatcherOptions = {
|
|
matchCase?: boolean;
|
|
matchWholeWord?: boolean;
|
|
useRegularExpression?: boolean;
|
|
};
|
|
|
|
export type CompileStringMatcherResult = {
|
|
matcher: (content: string) => boolean;
|
|
isValid: boolean;
|
|
};
|
|
|
|
export const escapeRegex = (value: string) => {
|
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
};
|
|
|
|
export const buildRegex = (pattern: string, flags = "") => {
|
|
try {
|
|
return new RegExp(pattern, flags);
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const compileStringMatcher = (
|
|
query: string,
|
|
options: SearchMatcherOptions = {},
|
|
): CompileStringMatcherResult => {
|
|
if (!query) return { matcher: () => true, isValid: true };
|
|
|
|
const matchCase = options.matchCase ?? false;
|
|
const matchWholeWord = options.matchWholeWord ?? false;
|
|
const useRegularExpression = options.useRegularExpression ?? false;
|
|
const flags = matchCase ? "" : "i";
|
|
|
|
if (useRegularExpression) {
|
|
const regex = buildRegex(query, flags);
|
|
if (!regex) return { matcher: () => false, isValid: false };
|
|
return { matcher: (content: string) => regex.test(content), isValid: true };
|
|
}
|
|
|
|
if (matchWholeWord) {
|
|
const regex = buildRegex(`\\b${escapeRegex(query)}\\b`, flags);
|
|
if (!regex) return { matcher: () => false, isValid: false };
|
|
return { matcher: (content: string) => regex.test(content), isValid: true };
|
|
}
|
|
|
|
if (matchCase) {
|
|
return {
|
|
matcher: (content: string) => content.includes(query),
|
|
isValid: true,
|
|
};
|
|
}
|
|
|
|
const target = query.toLowerCase();
|
|
return {
|
|
matcher: (content: string) => content.toLowerCase().includes(target),
|
|
isValid: true,
|
|
};
|
|
};
|