webext-patterns 1.1.1 → 1.3.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 +2 -0
- package/index.js +51 -3
- package/package.json +28 -9
- package/readme.md +59 -6
package/index.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export declare const patternValidationRegex: RegExp;
|
|
|
2
2
|
export declare const allStarsRegex: RegExp;
|
|
3
3
|
export declare const allUrlsRegex: RegExp;
|
|
4
4
|
export declare function patternToRegex(...matchPatterns: readonly string[]): RegExp;
|
|
5
|
+
export declare function globToRegex(...globs: readonly string[]): RegExp;
|
|
6
|
+
export declare function excludeDuplicatePatterns(matchPatterns: readonly string[]): string[];
|
package/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import escapeStringRegexp from 'escape-string-regexp';
|
|
1
2
|
// Copied from https://github.com/mozilla/gecko-dev/blob/073cc24f53d0cf31403121d768812146e597cc9d/toolkit/components/extensions/schemas/manifest.json#L487-L491
|
|
2
3
|
export const patternValidationRegex = /^(https?|wss?|file|ftp|\*):\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^file:\/\/\/.*$|^resource:\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^about:/;
|
|
3
4
|
const isFirefox = typeof navigator === 'object' && navigator.userAgent.includes('Firefox/');
|
|
4
|
-
export const allStarsRegex = isFirefox
|
|
5
|
+
export const allStarsRegex = isFirefox
|
|
6
|
+
? /^(https?|wss?):[/][/][^/]+([/].*)?$/
|
|
7
|
+
: /^https?:[/][/][^/]+([/].*)?$/;
|
|
5
8
|
export const allUrlsRegex = /^(https?|file|ftp):[/]+/;
|
|
6
|
-
function
|
|
9
|
+
function getRawPatternRegex(matchPattern) {
|
|
7
10
|
if (!patternValidationRegex.test(matchPattern)) {
|
|
8
11
|
throw new Error(matchPattern + ' is an invalid pattern, it must match ' + String(patternValidationRegex));
|
|
9
12
|
}
|
|
@@ -33,5 +36,50 @@ export function patternToRegex(...matchPatterns) {
|
|
|
33
36
|
if (matchPatterns.includes('*://*/*')) {
|
|
34
37
|
return allStarsRegex;
|
|
35
38
|
}
|
|
36
|
-
return new RegExp(matchPatterns.map(x =>
|
|
39
|
+
return new RegExp(matchPatterns.map(x => getRawPatternRegex(x)).join('|'));
|
|
40
|
+
}
|
|
41
|
+
// The parens are required by .split() to preserve the symbols
|
|
42
|
+
const globSymbols = /([?*]+)/;
|
|
43
|
+
function splitReplace(part, index) {
|
|
44
|
+
if (part === '') {
|
|
45
|
+
// Shortcut for speed
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
if (index % 2 === 0) {
|
|
49
|
+
// Raw text, escape it
|
|
50
|
+
return escapeStringRegexp(part);
|
|
51
|
+
}
|
|
52
|
+
// Else: Symbol
|
|
53
|
+
if (part.includes('*')) { // Can be more than one and it swallows surrounding question marks
|
|
54
|
+
return '.*';
|
|
55
|
+
}
|
|
56
|
+
return [...part].map(() => isFirefox ? '.' : '.?').join('');
|
|
57
|
+
}
|
|
58
|
+
function getRawGlobRegex(glob) {
|
|
59
|
+
const regexString = glob
|
|
60
|
+
.split(globSymbols)
|
|
61
|
+
// eslint-disable-next-line unicorn/no-array-callback-reference -- tis ok 🤫
|
|
62
|
+
.map(splitReplace)
|
|
63
|
+
.join('');
|
|
64
|
+
// Drop "start with anything" and "end with anything" sequences because they're the default for regex
|
|
65
|
+
return ('^' + regexString + '$')
|
|
66
|
+
.replace(/^[.][*]/, '')
|
|
67
|
+
.replace(/[.][*]$/, '')
|
|
68
|
+
.replace(/^[$]$/, '.+'); // Catch `*` and `*`
|
|
69
|
+
}
|
|
70
|
+
export function globToRegex(...globs) {
|
|
71
|
+
// No glob, match anything; `include_globs: []` is the default
|
|
72
|
+
if (globs.length === 0) {
|
|
73
|
+
return /.*/;
|
|
74
|
+
}
|
|
75
|
+
return new RegExp(globs.map(x => getRawGlobRegex(x)).join('|'));
|
|
76
|
+
}
|
|
77
|
+
export function excludeDuplicatePatterns(matchPatterns) {
|
|
78
|
+
if (matchPatterns.includes('<all_urls>')) {
|
|
79
|
+
return ['<all_urls>'];
|
|
80
|
+
}
|
|
81
|
+
if (matchPatterns.includes('*://*/*')) {
|
|
82
|
+
return ['*://*/*'];
|
|
83
|
+
}
|
|
84
|
+
return matchPatterns.filter(possibleSubset => !matchPatterns.some(possibleSuperset => possibleSubset !== possibleSuperset && patternToRegex(possibleSuperset).test(possibleSubset)));
|
|
37
85
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webext-patterns",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Tool to convert the patterns of your WebExtension manifest to regex",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Tool to convert the patterns and globs of your WebExtension manifest to regex",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
7
7
|
"chrome",
|
|
@@ -9,10 +9,15 @@
|
|
|
9
9
|
"firefox",
|
|
10
10
|
"glob",
|
|
11
11
|
"permission",
|
|
12
|
+
"greasemonkey",
|
|
13
|
+
"user scripts",
|
|
14
|
+
"globs",
|
|
15
|
+
"userscript",
|
|
12
16
|
"match",
|
|
13
17
|
"webext"
|
|
14
18
|
],
|
|
15
19
|
"repository": "fregante/webext-patterns",
|
|
20
|
+
"funding": "https://github.com/sponsors/fregante",
|
|
16
21
|
"license": "MIT",
|
|
17
22
|
"author": "Federico Brigante <me@fregante.com> (https://fregante.com)",
|
|
18
23
|
"type": "module",
|
|
@@ -24,6 +29,8 @@
|
|
|
24
29
|
],
|
|
25
30
|
"scripts": {
|
|
26
31
|
"build": "tsc",
|
|
32
|
+
"fix": "xo --fix",
|
|
33
|
+
"lint": "xo",
|
|
27
34
|
"prepare": "tsc --sourceMap false",
|
|
28
35
|
"test": "tsc && ava && xo",
|
|
29
36
|
"watch": "tsc --watch"
|
|
@@ -37,13 +44,25 @@
|
|
|
37
44
|
"unicorn/better-regex": "off"
|
|
38
45
|
}
|
|
39
46
|
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"escape-string-regexp": "^5.0.0"
|
|
49
|
+
},
|
|
40
50
|
"devDependencies": {
|
|
41
|
-
"@sindresorhus/tsconfig": "^
|
|
42
|
-
"@types/chrome": "0.0.
|
|
43
|
-
"ava": "^
|
|
44
|
-
"sinon": "^
|
|
45
|
-
"type-fest": "^
|
|
46
|
-
"typescript": "^4.
|
|
47
|
-
"xo": "^0.
|
|
51
|
+
"@sindresorhus/tsconfig": "^3.0.1",
|
|
52
|
+
"@types/chrome": "0.0.210",
|
|
53
|
+
"ava": "^5.1.1",
|
|
54
|
+
"sinon": "^15.0.1",
|
|
55
|
+
"type-fest": "^3.5.3",
|
|
56
|
+
"typescript": "^4.9.4",
|
|
57
|
+
"xo": "^0.53.1"
|
|
58
|
+
},
|
|
59
|
+
"webExt": {
|
|
60
|
+
"sourceDir": "demo-extension",
|
|
61
|
+
"run": {
|
|
62
|
+
"startUrl": [
|
|
63
|
+
"chrome://extensions/",
|
|
64
|
+
"https://example.com/"
|
|
65
|
+
]
|
|
66
|
+
}
|
|
48
67
|
}
|
|
49
68
|
}
|
package/readme.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[badge-gzip]: https://img.shields.io/bundlephobia/minzip/webext-patterns.svg?label=gzipped
|
|
4
4
|
[link-bundlephobia]: https://bundlephobia.com/result?p=webext-patterns
|
|
5
5
|
|
|
6
|
-
> Tool to convert the [patterns](https://developer.
|
|
6
|
+
> Tool to convert the [patterns](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts#globs) of your WebExtension manifest to regex
|
|
7
7
|
|
|
8
8
|
This might be incomplete. Please help me test it by adding more pattern and URLs to the [tests](./test.js).
|
|
9
9
|
|
|
@@ -26,13 +26,35 @@ import {patternToRegex} from 'webext-patterns';
|
|
|
26
26
|
|
|
27
27
|
```js
|
|
28
28
|
patternToRegex('http://*/*');
|
|
29
|
-
// Returns /^http
|
|
29
|
+
// Returns /^http:[/][/][^/]+[/].+$/
|
|
30
|
+
|
|
31
|
+
globToRegex('*.example.com');
|
|
32
|
+
// Returns /\.example\.com$/
|
|
33
|
+
|
|
34
|
+
excludeDuplicatePatterns(['https://*.google.com/*', 'https://google.com/*']);
|
|
35
|
+
// Returns ['https://*.google.com/*']
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> **Note**
|
|
39
|
+
> Firefox and Chrome handle patterns very slighly differently. `webext-patterns` defaults to Chrome’s logic, but if it detects a Firefox userAgent it will produce a Firefox-compatible regex.
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
#### patternToRegex(pattern1, pattern2, etc)
|
|
44
|
+
|
|
45
|
+
Accepts any number of `string` arguments and returns a single regex to match all of them.
|
|
46
|
+
|
|
47
|
+
[Match patterns](https://developer.chrome.com/extensions/match_patterns) are used in the manifest’s permissions and content scripts’ `matches` and `exclude_matches` array.
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
patternToRegex('http://*/*');
|
|
51
|
+
// Returns /^http:[/][/][^/]+[/].+$/
|
|
30
52
|
|
|
31
53
|
const gmailRegex = patternToRegex('*://mail.google.com/*');
|
|
32
54
|
gmailRegex.test('https://mail.google.com/a/b/c'); // -> true
|
|
33
55
|
gmailRegex.test('https://photos.google.com/a/b/c'); // -> false
|
|
34
56
|
|
|
35
|
-
// Also accepts
|
|
57
|
+
// Also accepts multiple patterns and returns a single regex
|
|
36
58
|
const googleRegex = patternToRegex(
|
|
37
59
|
'https://google.com/*',
|
|
38
60
|
'https://google.it/*'
|
|
@@ -41,12 +63,43 @@ googleRegex.test('https://google.it/search'); // -> true
|
|
|
41
63
|
googleRegex.test('https://google.de/search'); // -> false
|
|
42
64
|
```
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
#### patternToRegex(pattern1, pattern2, etc)
|
|
66
|
+
#### globToRegex(pattern1, pattern2, etc)
|
|
47
67
|
|
|
48
68
|
Accepts any number of `string` arguments and returns a single regex to match all of them.
|
|
49
69
|
|
|
70
|
+
[Globs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts#globs) are used in the manifest’s content scripts’ `include_globs` and `exclude_globs` arrays.
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
globToRegex('*.example.co?');
|
|
74
|
+
// Returns /\.example\.co.?$/ in Firefox
|
|
75
|
+
// Returns /\.example\.co.$/ everywhere else
|
|
76
|
+
|
|
77
|
+
const gmailRegex = globToRegex('*://mai?.google.com/*');
|
|
78
|
+
gmailRegex.test('https://mail.google.com/a/b/c'); // -> true
|
|
79
|
+
gmailRegex.test('https://photos.google.com/a/b/c'); // -> false
|
|
80
|
+
|
|
81
|
+
// Also accepts multiple globs and returns a single regex
|
|
82
|
+
const googleRegex = globToRegex(
|
|
83
|
+
'*google.com*',
|
|
84
|
+
'*google.it*'
|
|
85
|
+
);
|
|
86
|
+
googleRegex.test('https://google.it/search'); // -> true
|
|
87
|
+
googleRegex.test('https://google.de/search'); // -> false
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### excludeDuplicatePatterns([pattern1, pattern2, etc])
|
|
91
|
+
|
|
92
|
+
Accepts an array of patterns and returns a filtered array without the patterns that are already covered by others. For example `"https://*/*"` already covers all "https" URLs, so having `"https://google.com/*"` in the array won't make any difference and therefore it's dropped.
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
excludeDuplicatePatterns([
|
|
96
|
+
"https://*/*",
|
|
97
|
+
"https://google.com/*",
|
|
98
|
+
"https://*.example.com/*",
|
|
99
|
+
]);
|
|
100
|
+
// Returns ["https://*/*"]
|
|
101
|
+
```
|
|
102
|
+
|
|
50
103
|
## Related
|
|
51
104
|
|
|
52
105
|
### Permissions
|