diff --git a/docs/guide/advance/custom-filter.md b/docs/guide/advance/custom-filter.md
index dba4c22c5..a3a030211 100644
--- a/docs/guide/advance/custom-filter.md
+++ b/docs/guide/advance/custom-filter.md
@@ -83,6 +83,14 @@ module.exports = {
};
```
+### discardKeywords
+
+生成一个反向关键词过滤器。第二个入参是开启严格模式。
+
+:::warning 注意
+`discardKeywords` 的目的是 **过滤掉**,`useKeywords` 的目的是 **过滤出**。
+:::
+
### useRegexp
生成一个正则表达式过滤器。
diff --git a/lib/utils/filter.ts b/lib/utils/filter.ts
index 7c9a3792b..075b41db5 100644
--- a/lib/utils/filter.ts
+++ b/lib/utils/filter.ts
@@ -17,6 +17,15 @@ export const useKeywords = (keywords: ReadonlyArray, isStrict?: boolean)
return item => keywords[isStrict ? 'every' : 'some'](keyword => item.nodeName.includes(keyword));
};
+export const discardKeywords = (keywords: ReadonlyArray, isStrict?: boolean): NodeNameFilterType => {
+ // istanbul ignore next
+ if (!Array.isArray(keywords)) {
+ throw new Error('keywords 请使用数组。');
+ }
+
+ return item => !keywords[isStrict ? 'every' : 'some'](keyword => item.nodeName.includes(keyword));
+};
+
export const useRegexp = (regexp: RegExp): NodeNameFilterType => {
// istanbul ignore next
if (!_.isRegExp(regexp)) {
@@ -38,7 +47,7 @@ export const netflixFilter: NodeNameFilterType = item => {
export const usFilter: NodeNameFilterType = item => {
return [
'🇺🇸', '美', 'us', '波特兰', '达拉斯', '俄勒冈',
- '凤凰城', '费利蒙', '硅谷', '拉斯维加斯', '洛杉矶',
+ '凤凰城', '费利蒙', '硅谷', '拉斯维加斯', '洛杉矶',
'圣何塞', '圣克拉拉', '西雅图', '芝加哥',
].some(key => item.nodeName.toLowerCase().includes(key));
};
diff --git a/test/utils/filter.test.ts b/test/utils/filter.test.ts
index 3bf904788..6aa2c7c96 100644
--- a/test/utils/filter.test.ts
+++ b/test/utils/filter.test.ts
@@ -20,6 +20,32 @@ test('useKeywords', t => {
}));
});
+test('discardKeywords', t => {
+ const fn1 = filter.discardKeywords(['测试', 'test']);
+ const fn2 = filter.discardKeywords(['测试', 'test'], true);
+
+ t.false(fn1({
+ nodeName: '测试',
+ type: NodeTypeEnum.Shadowsocks,
+ }));
+ t.true(fn1({
+ nodeName: '美国',
+ type: NodeTypeEnum.Shadowsocks,
+ }));
+ t.true(fn2({
+ nodeName: '测试',
+ type: NodeTypeEnum.Shadowsocks,
+ }));
+ t.true(fn2({
+ nodeName: '美国测试',
+ type: NodeTypeEnum.Shadowsocks,
+ }));
+ t.false(fn2({
+ nodeName: '测试 test',
+ type: NodeTypeEnum.Shadowsocks,
+ }));
+});
+
test('useRegexp', t => {
const fn = filter.useRegexp(/(测试|test)/i);