webext-patterns 1.0.0 → 1.2.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 +3 -0
- package/index.js +51 -3
- package/package.json +29 -16
- package/readme.md +46 -7
package/index.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export declare const patternValidationRegex: RegExp;
|
|
2
|
+
export declare const allStarsRegex: RegExp;
|
|
3
|
+
export declare const allUrlsRegex: RegExp;
|
|
2
4
|
export declare function patternToRegex(...matchPatterns: readonly string[]): RegExp;
|
|
5
|
+
export declare function globToRegex(...globs: readonly string[]): RegExp;
|
package/index.js
CHANGED
|
@@ -1,7 +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
|
-
|
|
5
|
+
export const allStarsRegex = isFirefox
|
|
6
|
+
? /^(https?|wss?):[/][/][^/]+([/].*)?$/
|
|
7
|
+
: /^https?:[/][/][^/]+([/].*)?$/;
|
|
8
|
+
export const allUrlsRegex = /^(https?|file|ftp):[/]+/;
|
|
9
|
+
function getRawPatternRegex(matchPattern) {
|
|
5
10
|
if (!patternValidationRegex.test(matchPattern)) {
|
|
6
11
|
throw new Error(matchPattern + ' is an invalid pattern, it must match ' + String(patternValidationRegex));
|
|
7
12
|
}
|
|
@@ -21,8 +26,51 @@ function getRawRegex(matchPattern) {
|
|
|
21
26
|
return '^' + protocol + host + '(' + pathname + ')?$';
|
|
22
27
|
}
|
|
23
28
|
export function patternToRegex(...matchPatterns) {
|
|
29
|
+
// No pattern, match nothing https://stackoverflow.com/q/14115522/288906
|
|
30
|
+
if (matchPatterns.length === 0) {
|
|
31
|
+
return /$./;
|
|
32
|
+
}
|
|
24
33
|
if (matchPatterns.includes('<all_urls>')) {
|
|
25
|
-
return
|
|
34
|
+
return allUrlsRegex;
|
|
35
|
+
}
|
|
36
|
+
if (matchPatterns.includes('*://*/*')) {
|
|
37
|
+
return allStarsRegex;
|
|
38
|
+
}
|
|
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 /.*/;
|
|
26
74
|
}
|
|
27
|
-
return new RegExp(
|
|
75
|
+
return new RegExp(globs.map(x => getRawGlobRegex(x)).join('|'));
|
|
28
76
|
}
|
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.2.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,6 +9,10 @@
|
|
|
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
|
],
|
|
@@ -24,7 +28,9 @@
|
|
|
24
28
|
],
|
|
25
29
|
"scripts": {
|
|
26
30
|
"build": "tsc",
|
|
27
|
-
"
|
|
31
|
+
"fix": "xo --fix",
|
|
32
|
+
"lint": "xo",
|
|
33
|
+
"prepare": "tsc --sourceMap false",
|
|
28
34
|
"test": "tsc && ava && xo",
|
|
29
35
|
"watch": "tsc --watch"
|
|
30
36
|
},
|
|
@@ -34,21 +40,28 @@
|
|
|
34
40
|
"webextensions"
|
|
35
41
|
],
|
|
36
42
|
"rules": {
|
|
37
|
-
"unicorn/better-regex": "off"
|
|
38
|
-
"unicorn/no-array-callback-reference": "off",
|
|
39
|
-
"comma-dangle": [
|
|
40
|
-
"error",
|
|
41
|
-
"always-multiline"
|
|
42
|
-
]
|
|
43
|
+
"unicorn/better-regex": "off"
|
|
43
44
|
}
|
|
44
45
|
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"escape-string-regexp": "^5.0.0"
|
|
48
|
+
},
|
|
45
49
|
"devDependencies": {
|
|
46
|
-
"@sindresorhus/tsconfig": "^0.
|
|
47
|
-
"@types/chrome": "0.0.
|
|
48
|
-
"ava": "^3.
|
|
49
|
-
"sinon": "^
|
|
50
|
-
"type-fest": "^
|
|
51
|
-
"typescript": "^4.
|
|
52
|
-
"xo": "^0.
|
|
50
|
+
"@sindresorhus/tsconfig": "^3.0.1",
|
|
51
|
+
"@types/chrome": "0.0.190",
|
|
52
|
+
"ava": "^4.3.0",
|
|
53
|
+
"sinon": "^14.0.0",
|
|
54
|
+
"type-fest": "^2.13.1",
|
|
55
|
+
"typescript": "^4.7.4",
|
|
56
|
+
"xo": "^0.50.0"
|
|
57
|
+
},
|
|
58
|
+
"webExt": {
|
|
59
|
+
"sourceDir": "demo-extension",
|
|
60
|
+
"run": {
|
|
61
|
+
"startUrl": [
|
|
62
|
+
"chrome://extensions/",
|
|
63
|
+
"https://example.com/"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
53
66
|
}
|
|
54
67
|
}
|
package/readme.md
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
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
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
12
|
-
You can
|
|
12
|
+
You can download the [standalone bundle](https://bundle.fregante.com/?pkg=webext-patterns) and include it in your `manifest.json`.
|
|
13
|
+
|
|
14
|
+
Or use `npm`:
|
|
13
15
|
|
|
14
16
|
```sh
|
|
15
17
|
npm install webext-patterns
|
|
@@ -22,15 +24,34 @@ import {patternToRegex} from 'webext-patterns';
|
|
|
22
24
|
|
|
23
25
|
## Usage
|
|
24
26
|
|
|
27
|
+
> **Note**
|
|
28
|
+
> Firefox and Chrome handle globs very slighly differently. `webext-patterns` defaults to Chrome’s logic, but if it detects a Firefox userAgent it will produce a Firefox-compatible regex.
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
patternToRegex('http://*/*');
|
|
32
|
+
// Returns /^http:[/][/][^/]+[/].+$/
|
|
33
|
+
|
|
34
|
+
globToRegex('*.example.com');
|
|
35
|
+
// Returns /\.example\.com$/
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
#### patternToRegex(pattern1, pattern2, etc)
|
|
41
|
+
|
|
42
|
+
Accepts any number of `string` arguments and returns a single regex to match all of them.
|
|
43
|
+
|
|
44
|
+
[Match patterns](https://developer.chrome.com/extensions/match_patterns) are used in the manifest’s permissions and content scripts’ `matches` and `exclude_matches` array.
|
|
45
|
+
|
|
25
46
|
```js
|
|
26
47
|
patternToRegex('http://*/*');
|
|
27
|
-
// Returns /^http
|
|
48
|
+
// Returns /^http:[/][/][^/]+[/].+$/
|
|
28
49
|
|
|
29
50
|
const gmailRegex = patternToRegex('*://mail.google.com/*');
|
|
30
51
|
gmailRegex.test('https://mail.google.com/a/b/c'); // -> true
|
|
31
52
|
gmailRegex.test('https://photos.google.com/a/b/c'); // -> false
|
|
32
53
|
|
|
33
|
-
// Also accepts
|
|
54
|
+
// Also accepts multiple patterns and returns a single regex
|
|
34
55
|
const googleRegex = patternToRegex(
|
|
35
56
|
'https://google.com/*',
|
|
36
57
|
'https://google.it/*'
|
|
@@ -39,12 +60,30 @@ googleRegex.test('https://google.it/search'); // -> true
|
|
|
39
60
|
googleRegex.test('https://google.de/search'); // -> false
|
|
40
61
|
```
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
#### patternToRegex(pattern1, pattern2, etc)
|
|
63
|
+
#### globToRegex(pattern1, pattern2, etc)
|
|
45
64
|
|
|
46
65
|
Accepts any number of `string` arguments and returns a single regex to match all of them.
|
|
47
66
|
|
|
67
|
+
[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.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
globToRegex('*.example.co?');
|
|
71
|
+
// Returns /\.example\.co.?$/ in Firefox
|
|
72
|
+
// Returns /\.example\.co.$/ everywhere else
|
|
73
|
+
|
|
74
|
+
const gmailRegex = globToRegex('*://mai?.google.com/*');
|
|
75
|
+
gmailRegex.test('https://mail.google.com/a/b/c'); // -> true
|
|
76
|
+
gmailRegex.test('https://photos.google.com/a/b/c'); // -> false
|
|
77
|
+
|
|
78
|
+
// Also accepts multiple globs and returns a single regex
|
|
79
|
+
const googleRegex = globToRegex(
|
|
80
|
+
'*google.com*',
|
|
81
|
+
'*google.it*'
|
|
82
|
+
);
|
|
83
|
+
googleRegex.test('https://google.it/search'); // -> true
|
|
84
|
+
googleRegex.test('https://google.de/search'); // -> false
|
|
85
|
+
```
|
|
86
|
+
|
|
48
87
|
## Related
|
|
49
88
|
|
|
50
89
|
### Permissions
|