webext-patterns 2.0.2 → 3.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.
- package/{index.d.ts → distribution/index.d.ts} +3 -3
- package/distribution/index.js +119 -0
- package/package.json +5 -5
- package/index.js +0 -150
|
@@ -3,8 +3,8 @@ export declare const allStarsRegex: RegExp;
|
|
|
3
3
|
export declare const allUrlsRegex: RegExp;
|
|
4
4
|
export declare function assertValidPattern(matchPattern: string): void;
|
|
5
5
|
export declare function isValidPattern(matchPattern: string): boolean;
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
6
|
+
export declare function testPatterns(url: string, patterns: string[]): boolean;
|
|
7
|
+
export declare function getMatchingPatterns(url: string, patterns: string[]): string[];
|
|
8
8
|
export declare function patternToRegex(...matchPatterns: readonly string[]): RegExp;
|
|
9
9
|
export declare function globToRegex(...globs: readonly string[]): RegExp;
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function removeRedundantPatterns(matchPatterns: readonly string[]): string[];
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Copied from https://github.com/mozilla/gecko-dev/blob/5836a062726f715fda621338a17b51aff30d0a8c/toolkit/components/extensions/schemas/manifest.json#L729-L741
|
|
2
|
+
export const patternValidationRegex = /^(https?|wss?|file|ftp|\*):\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^file:\/\/\/.*$|^resource:\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^about:/;
|
|
3
|
+
const isFirefox = globalThis.navigator?.userAgent.includes('Firefox/');
|
|
4
|
+
export const allStarsRegex = isFirefox
|
|
5
|
+
? /^(https?|wss?):[/][/][^/]+([/].*)?$/
|
|
6
|
+
: /^https?:[/][/][^/]+([/].*)?$/;
|
|
7
|
+
export const allUrlsRegex = /^(https?|file|ftp):[/]+/;
|
|
8
|
+
export function assertValidPattern(matchPattern) {
|
|
9
|
+
if (!isValidPattern(matchPattern)) {
|
|
10
|
+
throw new Error(matchPattern + ' is an invalid pattern. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns for more info.');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function isValidPattern(matchPattern) {
|
|
14
|
+
return matchPattern === '<all_urls>' || patternValidationRegex.test(matchPattern);
|
|
15
|
+
}
|
|
16
|
+
export function testPatterns(url, patterns) {
|
|
17
|
+
if (patterns.includes('<all_urls>') && allUrlsRegex.test(url)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (patterns.includes('*://*/*') && allStarsRegex.test(url)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
for (const pattern of patterns) {
|
|
24
|
+
if (patternToRegex(pattern).test(url)) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
export function getMatchingPatterns(url, patterns) {
|
|
31
|
+
return patterns.filter(pattern => testPatterns(url, [pattern]));
|
|
32
|
+
}
|
|
33
|
+
function getRawPatternRegex(matchPattern) {
|
|
34
|
+
assertValidPattern(matchPattern);
|
|
35
|
+
// Host undefined for file:///
|
|
36
|
+
let [, protocol, host = '', pathname] = matchPattern.split(/(^[^:]+:[/][/])([^/]+)?/);
|
|
37
|
+
protocol = protocol
|
|
38
|
+
.replace('*', isFirefox ? '(https?|wss?)' : 'https?') // Protocol wildcard
|
|
39
|
+
.replaceAll(/[/]/g, '[/]'); // Escape slashes
|
|
40
|
+
if (host === '*') {
|
|
41
|
+
host = '[^/]+';
|
|
42
|
+
}
|
|
43
|
+
host &&= host
|
|
44
|
+
.replace(/^[*][.]/, '([^/]+.)*') // Initial wildcard
|
|
45
|
+
.replaceAll(/[.]/g, '[.]') // Escape dots
|
|
46
|
+
.replace(/[*]$/, '[^.]+'); // Last wildcard
|
|
47
|
+
pathname = pathname
|
|
48
|
+
.replaceAll(/[/]/g, '[/]') // Escape slashes
|
|
49
|
+
.replaceAll(/[.]/g, '[.]') // Escape dots
|
|
50
|
+
.replaceAll(/[*]/g, '.*'); // Any wildcard
|
|
51
|
+
return '^' + protocol + host + '(' + pathname + ')?$';
|
|
52
|
+
}
|
|
53
|
+
export function patternToRegex(...matchPatterns) {
|
|
54
|
+
// No pattern, match nothing https://stackoverflow.com/q/14115522/288906
|
|
55
|
+
if (matchPatterns.length === 0) {
|
|
56
|
+
return /$./;
|
|
57
|
+
}
|
|
58
|
+
if (matchPatterns.includes('<all_urls>')) {
|
|
59
|
+
return allUrlsRegex;
|
|
60
|
+
}
|
|
61
|
+
if (matchPatterns.includes('*://*/*')) {
|
|
62
|
+
return allStarsRegex;
|
|
63
|
+
}
|
|
64
|
+
return new RegExp(matchPatterns.map(x => getRawPatternRegex(x)).join('|'));
|
|
65
|
+
}
|
|
66
|
+
// The parens are required by .split() to preserve the symbols
|
|
67
|
+
const globSymbols = /([?*]+)/;
|
|
68
|
+
function splitReplace(part, index) {
|
|
69
|
+
if (part === '') {
|
|
70
|
+
// Shortcut for speed
|
|
71
|
+
return '';
|
|
72
|
+
}
|
|
73
|
+
if (index % 2 === 0) {
|
|
74
|
+
// Raw text, escape it
|
|
75
|
+
// eslint-disable-next-line no-use-extend-native/no-use-extend-native -- TODO: Drop after https://github.com/dustinspecker/eslint-plugin-no-use-extend-native/issues/157
|
|
76
|
+
return RegExp.escape(part);
|
|
77
|
+
}
|
|
78
|
+
// Else: Symbol
|
|
79
|
+
if (part.includes('*')) { // Can be more than one and it swallows surrounding question marks
|
|
80
|
+
return '.*';
|
|
81
|
+
}
|
|
82
|
+
return [...part].map(() => isFirefox ? '.' : '.?').join('');
|
|
83
|
+
}
|
|
84
|
+
function getRawGlobRegex(glob) {
|
|
85
|
+
const regexString = glob
|
|
86
|
+
.split(globSymbols)
|
|
87
|
+
// eslint-disable-next-line unicorn/no-array-callback-reference -- tis ok 🤫
|
|
88
|
+
.map(splitReplace)
|
|
89
|
+
.join('');
|
|
90
|
+
// Drop "start with anything" and "end with anything" sequences because they're the default for regex
|
|
91
|
+
return ('^' + regexString + '$')
|
|
92
|
+
.replace(/^[.][*]/, '')
|
|
93
|
+
.replace(/[.][*]$/, '')
|
|
94
|
+
.replace(/^[$]$/, '.+'); // Catch `*` and `*`
|
|
95
|
+
}
|
|
96
|
+
export function globToRegex(...globs) {
|
|
97
|
+
// No glob, match anything; `include_globs: []` is the default
|
|
98
|
+
if (globs.length === 0) {
|
|
99
|
+
return /.*/;
|
|
100
|
+
}
|
|
101
|
+
return new RegExp(globs.map(x => getRawGlobRegex(x)).join('|'));
|
|
102
|
+
}
|
|
103
|
+
export function removeRedundantPatterns(matchPatterns) {
|
|
104
|
+
if (matchPatterns.includes('<all_urls>')) {
|
|
105
|
+
return ['<all_urls>'];
|
|
106
|
+
}
|
|
107
|
+
if (matchPatterns.includes('*://*/*')) {
|
|
108
|
+
return ['*://*/*'];
|
|
109
|
+
}
|
|
110
|
+
// Cover identical patterns
|
|
111
|
+
const uniquePatterns = [...new Set(matchPatterns)];
|
|
112
|
+
return uniquePatterns.filter(possibleSubset =>
|
|
113
|
+
// Keep if there are no matches
|
|
114
|
+
!uniquePatterns.some(possibleSuperset =>
|
|
115
|
+
// Don't compare to self
|
|
116
|
+
possibleSubset !== possibleSuperset
|
|
117
|
+
// Drop if it's a subset
|
|
118
|
+
&& patternToRegex(possibleSuperset).test(possibleSubset)));
|
|
119
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webext-patterns",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Tool to convert the patterns and globs of your WebExtension manifest to regex",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "Federico Brigante <me@fregante.com> (https://fregante.com)",
|
|
23
23
|
"type": "module",
|
|
24
|
-
"exports": "./index.js",
|
|
25
|
-
"types": "./index.d.ts",
|
|
24
|
+
"exports": "./distribution/index.js",
|
|
25
|
+
"types": "./distribution/index.d.ts",
|
|
26
26
|
"files": [
|
|
27
|
-
"index.js",
|
|
28
|
-
"index.d.ts"
|
|
27
|
+
"distribution/index.js",
|
|
28
|
+
"distribution/index.d.ts"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc",
|
package/index.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
-
if (ar || !(i in from)) {
|
|
5
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
-
ar[i] = from[i];
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
-
};
|
|
11
|
-
var _a;
|
|
12
|
-
exports.__esModule = true;
|
|
13
|
-
exports.removeRedundantPatterns = exports.globToRegex = exports.patternToRegex = exports.getMatchingPatterns = exports.testPatterns = exports.isValidPattern = exports.assertValidPattern = exports.allUrlsRegex = exports.allStarsRegex = exports.patternValidationRegex = void 0;
|
|
14
|
-
// Copied from https://github.com/mozilla/gecko-dev/blob/5836a062726f715fda621338a17b51aff30d0a8c/toolkit/components/extensions/schemas/manifest.json#L729-L741
|
|
15
|
-
exports.patternValidationRegex = /^(https?|wss?|file|ftp|\*):\/\/(\*|\*\.[^*/:]+|[^*/:]+)\/.*$|^file:\/\/\/.*$|^about:/;
|
|
16
|
-
var isFirefox = (_a = globalThis.navigator) === null || _a === void 0 ? void 0 : _a.userAgent.includes('Firefox/');
|
|
17
|
-
exports.allStarsRegex = isFirefox
|
|
18
|
-
? /^(https?|wss?):[/][/][^/]+([/].*)?$/
|
|
19
|
-
: /^https?:[/][/][^/]+([/].*)?$/;
|
|
20
|
-
exports.allUrlsRegex = /^(https?|file|ftp):[/]+/;
|
|
21
|
-
function assertValidPattern(matchPattern) {
|
|
22
|
-
if (!isValidPattern(matchPattern)) {
|
|
23
|
-
throw new Error(matchPattern + ' is an invalid pattern. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns for more info.');
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
exports.assertValidPattern = assertValidPattern;
|
|
27
|
-
function isValidPattern(matchPattern) {
|
|
28
|
-
return matchPattern === '<all_urls>' || exports.patternValidationRegex.test(matchPattern);
|
|
29
|
-
}
|
|
30
|
-
exports.isValidPattern = isValidPattern;
|
|
31
|
-
function testPatterns(url, patterns) {
|
|
32
|
-
if (patterns.includes('<all_urls>') && exports.allUrlsRegex.test(url)) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
if (patterns.includes('*://*/*') && exports.allStarsRegex.test(url)) {
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
|
|
39
|
-
var pattern = patterns_1[_i];
|
|
40
|
-
if (patternToRegex(pattern).test(url)) {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
exports.testPatterns = testPatterns;
|
|
47
|
-
function getMatchingPatterns(url, patterns) {
|
|
48
|
-
return patterns.filter(function (pattern) { return testPatterns(url, [pattern]); });
|
|
49
|
-
}
|
|
50
|
-
exports.getMatchingPatterns = getMatchingPatterns;
|
|
51
|
-
function getRawPatternRegex(matchPattern) {
|
|
52
|
-
assertValidPattern(matchPattern);
|
|
53
|
-
// Host undefined for file:///
|
|
54
|
-
var _a = matchPattern.split(/(^[^:]+:[/][/])([^/]+)?/), protocol = _a[1], _b = _a[2], host = _b === void 0 ? '' : _b, pathname = _a[3];
|
|
55
|
-
protocol = protocol
|
|
56
|
-
.replace('*', isFirefox ? '(https?|wss?)' : 'https?') // Protocol wildcard
|
|
57
|
-
.replaceAll(/[/]/g, '[/]'); // Escape slashes
|
|
58
|
-
if (host === '*') {
|
|
59
|
-
host = '[^/]+';
|
|
60
|
-
}
|
|
61
|
-
host && (host = host
|
|
62
|
-
.replace(/^[*][.]/, '([^/]+.)*') // Initial wildcard
|
|
63
|
-
.replaceAll(/[.]/g, '[.]') // Escape dots
|
|
64
|
-
.replace(/[*]$/, '[^.]+')); // Last wildcard
|
|
65
|
-
pathname = pathname
|
|
66
|
-
.replaceAll(/[/]/g, '[/]') // Escape slashes
|
|
67
|
-
.replaceAll(/[.]/g, '[.]') // Escape dots
|
|
68
|
-
.replaceAll(/[*]/g, '.*'); // Any wildcard
|
|
69
|
-
return '^' + protocol + host + '(' + pathname + ')?$';
|
|
70
|
-
}
|
|
71
|
-
function patternToRegex() {
|
|
72
|
-
var matchPatterns = [];
|
|
73
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
74
|
-
matchPatterns[_i] = arguments[_i];
|
|
75
|
-
}
|
|
76
|
-
// No pattern, match nothing https://stackoverflow.com/q/14115522/288906
|
|
77
|
-
if (matchPatterns.length === 0) {
|
|
78
|
-
return /$./;
|
|
79
|
-
}
|
|
80
|
-
if (matchPatterns.includes('<all_urls>')) {
|
|
81
|
-
return exports.allUrlsRegex;
|
|
82
|
-
}
|
|
83
|
-
if (matchPatterns.includes('*://*/*')) {
|
|
84
|
-
return exports.allStarsRegex;
|
|
85
|
-
}
|
|
86
|
-
return new RegExp(matchPatterns.map(function (x) { return getRawPatternRegex(x); }).join('|'));
|
|
87
|
-
}
|
|
88
|
-
exports.patternToRegex = patternToRegex;
|
|
89
|
-
// The parens are required by .split() to preserve the symbols
|
|
90
|
-
var globSymbols = /([?*]+)/;
|
|
91
|
-
function splitReplace(part, index) {
|
|
92
|
-
if (part === '') {
|
|
93
|
-
// Shortcut for speed
|
|
94
|
-
return '';
|
|
95
|
-
}
|
|
96
|
-
if (index % 2 === 0) {
|
|
97
|
-
// Raw text, escape it
|
|
98
|
-
// eslint-disable-next-line no-use-extend-native/no-use-extend-native -- TODO: Drop after https://github.com/dustinspecker/eslint-plugin-no-use-extend-native/issues/157
|
|
99
|
-
return RegExp.escape(part);
|
|
100
|
-
}
|
|
101
|
-
// Else: Symbol
|
|
102
|
-
if (part.includes('*')) { // Can be more than one and it swallows surrounding question marks
|
|
103
|
-
return '.*';
|
|
104
|
-
}
|
|
105
|
-
return __spreadArray([], part, true).map(function () { return isFirefox ? '.' : '.?'; }).join('');
|
|
106
|
-
}
|
|
107
|
-
function getRawGlobRegex(glob) {
|
|
108
|
-
var regexString = glob
|
|
109
|
-
.split(globSymbols)
|
|
110
|
-
// eslint-disable-next-line unicorn/no-array-callback-reference -- tis ok 🤫
|
|
111
|
-
.map(splitReplace)
|
|
112
|
-
.join('');
|
|
113
|
-
// Drop "start with anything" and "end with anything" sequences because they're the default for regex
|
|
114
|
-
return ('^' + regexString + '$')
|
|
115
|
-
.replace(/^[.][*]/, '')
|
|
116
|
-
.replace(/[.][*]$/, '')
|
|
117
|
-
.replace(/^[$]$/, '.+'); // Catch `*` and `*`
|
|
118
|
-
}
|
|
119
|
-
function globToRegex() {
|
|
120
|
-
var globs = [];
|
|
121
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
122
|
-
globs[_i] = arguments[_i];
|
|
123
|
-
}
|
|
124
|
-
// No glob, match anything; `include_globs: []` is the default
|
|
125
|
-
if (globs.length === 0) {
|
|
126
|
-
return /.*/;
|
|
127
|
-
}
|
|
128
|
-
return new RegExp(globs.map(function (x) { return getRawGlobRegex(x); }).join('|'));
|
|
129
|
-
}
|
|
130
|
-
exports.globToRegex = globToRegex;
|
|
131
|
-
function removeRedundantPatterns(matchPatterns) {
|
|
132
|
-
if (matchPatterns.includes('<all_urls>')) {
|
|
133
|
-
return ['<all_urls>'];
|
|
134
|
-
}
|
|
135
|
-
if (matchPatterns.includes('*://*/*')) {
|
|
136
|
-
return ['*://*/*'];
|
|
137
|
-
}
|
|
138
|
-
// Cover identical patterns
|
|
139
|
-
var uniquePatterns = __spreadArray([], new Set(matchPatterns), true);
|
|
140
|
-
return uniquePatterns.filter(function (possibleSubset) {
|
|
141
|
-
// Keep if there are no matches
|
|
142
|
-
return !uniquePatterns.some(function (possibleSuperset) {
|
|
143
|
-
// Don't compare to self
|
|
144
|
-
return possibleSubset !== possibleSuperset
|
|
145
|
-
// Drop if it's a subset
|
|
146
|
-
&& patternToRegex(possibleSuperset).test(possibleSubset);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
exports.removeRedundantPatterns = removeRedundantPatterns;
|