webext-patterns 2.0.0 → 2.0.1

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.
@@ -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 doesUrlMatchPatterns(url: string, ...patterns: string[]): boolean;
7
- export declare function findMatchingPatterns(url: string, ...patterns: string[]): string[];
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 excludeDuplicatePatterns(matchPatterns: readonly string[]): string[];
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:\/\/\/.*$|^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": "2.0.0",
3
+ "version": "2.0.1",
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;