browser-extension-url-match
Version:
Browser extension URL pattern matching
78 lines (77 loc) • 3.09 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toMatchFnOrError = toMatchFnOrError;
var _fancyRegex = require("fancy-regex");
var _constants = require("./constants");
var _getHostRegex = require("./getHostRegex");
var _getPatternSegments = require("./getPatternSegments");
var _utils = require("./utils");
function toMatchFnOrError(pattern, options) {
var _a;
const {
supportedSchemes,
schemeStarMatchesWs,
strict
} = options;
if (pattern === _constants.ALL_URLS) {
return (0, _utils.createMatchFn)(url => {
return (0, _fancyRegex.regex)()`
^
(?:${supportedSchemes})
:
$
`.test(url.protocol);
});
}
const unsupportedScheme = (_a = pattern.match(/^(urn|data):/)) === null || _a === void 0 ? void 0 : _a[1];
if (unsupportedScheme) {
return new TypeError(`browser-extension-url-match does not currently support scheme "${unsupportedScheme}"`);
}
const patternSegments = (0, _getPatternSegments.getPatternSegments)(pattern);
if (!patternSegments) {
try {
const url = new URL(pattern);
if (url.hash || url.href.endsWith('#')) {
return new TypeError(`Pattern cannot contain a hash: "${pattern}" contains hash "${url.hash || '#'}"`);
}
if (!pattern.slice(url.origin.length).startsWith('/')) {
return new TypeError(`Pattern "${pattern}" does not contain a path. Use "${pattern}/*" to match any paths with that origin or "${pattern}/" to match that URL alone`);
}
} catch (_b) {
/* fall back to generic err */
}
return new TypeError(`Pattern "${pattern}" is invalid`);
}
const {
scheme,
rawPathAndQuery
} = patternSegments;
/* Scheme */
if (scheme !== '*' && !supportedSchemes.includes(scheme)) {
return new TypeError(`Scheme "${scheme}" is not supported`);
}
const schemeRegex = (0, _fancyRegex.regex)()`${scheme === '*' ? new _fancyRegex.RegexFragment(['https?', schemeStarMatchesWs && 'wss?'].filter(Boolean).join('|')) : scheme}:`;
/* Host */
const hostRegex = (0, _getHostRegex.getHostRegex)(patternSegments);
if (hostRegex instanceof Error) {
return hostRegex;
}
/* Path and query string */
// Non-strict used for host permissions.
// "The path must be present in a host permission, but is always treated as /*."
// See https://developer.chrome.com/docs/extensions/mv3/match_patterns/
const pathAndQuery = strict ? (0, _utils.normalizeUrlFragment)(rawPathAndQuery) : '/*';
if (pathAndQuery instanceof Error) {
return pathAndQuery;
}
const pathAndQueryRegex = (0, _fancyRegex.regex)()`^${new _fancyRegex.RegexFragment(pathAndQuery.split('*').map(x => (0, _fancyRegex.regexEscape)(x)).join('.*'))}$`;
return (0, _utils.createMatchFn)(url => {
// respect zero-search-string
const pathAndQuery = url.pathname + (url.href.endsWith('?') ? '?' : url.search);
return schemeRegex.test(url.protocol) &&
// test against `url.hostname`, not `url.host`, as port is ignored
hostRegex.test(url.hostname) && pathAndQueryRegex.test(pathAndQuery);
});
}
;