【问题标题】:Convert a JavaScript RegEx into JSON format将 JavaScript RegEx 转换为 JSON 格式
【发布时间】:2015-12-31 14:26:13
【问题描述】:

我目前正在开发一个 Safari 扩展程序,它将利用 Safari 9 中提供的新 webkit-content-blocker 功能。现在,此类阻止程序的规则需要用 JSON 编写。

我即将推出的扩展程序的后台脚本会生成这样的 JSON 规则。我遇到的问题是我无法正确格式化正则表达式,其作用是过滤 URL,使其与 JSON 兼容。

假设我需要阻止 URL 包含“香蕉”、“橙色”或“苹果”的所有图像。我的正则表达式是这样的:

var url-filter = /banana|orange|apple/g;

现在是 JSON 中的拦截器规则,缺少 url 过滤部分:

"action": {
   "type": "block"
    },
"trigger": {
   "url-filter": <JSON regex here>,
   "resource-type": ["image"],
   "load-type": ["third-party"]
    }

[更新]

在知道不支持交替的情况下,如何将我的正则表达式重写为 JSON 兼容/就绪?

正则表达式格式

触发器支持基于正则表达式过滤每个资源的 URL。

支持以下功能:

  • 用“.”匹配任何字符。
  • 使用范围语法 [a-b] 匹配范围。
  • 用“?”、“+”和“*”量化表达式。
  • 带括号的组。

可以使用行首 (“^”) 和行尾 (“$”) 标记,但它们仅限于表达式的第一个和最后一个字符。例如,像“^bar$”这样的模式是完全有效的,而“(foo)?^bar$”会导致语法错误。

[更新的 BIS]

鉴于 Safari 实施了严格的 CSP 政策,并且缺乏对交替的支持,我最终将我原来的正则表达式转换为一个数组,然后通过循环动态生成 JSON 规则。

var regex = 'banana|orange|apple',
    filters = regex.split('|'),
    json_rules = [];

var Blocker = {
        build: function() {

            filters.forEach( function(filter) {
                var rule = {
                    action: {
                        'type': 'block'
                    },
                    trigger: {
                        'url-filter': filter,
                        'resource-type': ['image'],
                        'load-type': ['third-party']
                    }
                };
                json_rules.push(rule);
            });

            Blocker.set(JSON.stringify(json_rules));
        },
        init: function() {
            Blocker.build();
        },
        set: function (rule) {
            safari.extension.setContentBlocker(rule);
        }

};

【问题讨论】:

  • 将正则表达式添加为 JSON 中的 string,并在 new RegExp(str, 'g') 中使用此字符串,而且我假设您总是想使用全局标志,所以不需要在 JSON 字符串中使用
  • JSON 不能包含正则表达式。因此,他们需要将它们作为字符串保存,因为这个特定的 API 也需要。
  • 很简单...使用 regexp.toString() 然后 eval 转换回来 ;) 不支持的只是检查里面的字符...

标签: javascript json regex safari-extension


【解决方案1】:

根据您链接的文档,过滤器的值被视为正则表达式(例如,它们显示"url-filter": "evil-tracker\\.js""url-filter": ".*")。

文档还说url-filter 不区分大小写,因此您不必担心您可能想要使用的i 标志。但是如果你想要一个区分大小写的,你可以添加"url-filter-is-case-sensitive": true

在这种情况下,您只需将正则表达式放在引号中,确保转义字符串文字中需要转义的任何字符(例如,注意他们如何在 "evil-tracker\\.js" 字符串中使用两个反斜杠,在正则表达式的顺序为evil-tracker\.js)。

然而:你的表达方式的问题是它们不支持交替。同样,从您链接的文档中:

格式是 JavaScript 正则表达式的严格子集。从语法上讲,JavaScript 支持的所有内容都是保留的,但解析器只接受一个子集。不受支持的表达式会导致解析错误。

支持以下功能:

  • 用“.”匹配任何字符。
  • 使用范围语法 [a-b] 匹配范围。
  • 用“?”、“+”和“*”量化表达式。
  • 带括号的组。

可以使用行首 (“^”) 和行尾 (“$”) 标记,但它们仅限于表达式的第一个和最后一个字符。例如,像“^bar$”这样的模式是完全有效的,而“(foo)?^bar$”会导致语法错误。

请注意,他们不接受|(替代)。

这告诉我你需要三个规则:一个用于banana,一个用于orange,一个用于apple

【讨论】:

  • 感谢您的回复。您建议的 url-filter 是我在编写拦截器规则时尝试的第一个。但是,每当我使用这种格式加载扩展时,我都会收到错误消息:“JSON 编译失败”。使用全局“。*”有效,所以我知道错误来自正则表达式。
  • @flo:稍后在文档中我们会看到原因:它们不支持交替。我已经更新了答案。
  • 是的,这是我的问题 :) [抱歉造成误解,更新了我的问题以使其更清楚]。问题是我的单词列表很大,这意味着为每个单词编写规则会使整个事情变得丑陋和过于复杂......
  • @flo:不幸的是,由于他们不支持交替,你会有很长的列表。您有时可以将事物与字符类(他们在上面将它们称为“范围”)和量词结合起来,但如果它们不支持交替,它们就不支持交替。 :-|
  • 是的,将尝试将正则表达式转换为数组,然后循环遍历每个元素以动态创建规则!感谢您的宝贵时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 2013-01-24
  • 2017-10-12
  • 1970-01-01
相关资源
最近更新 更多