UNPKG

browser-extension-url-match

Version:

Browser extension URL pattern matching

78 lines (77 loc) 3.09 kB
"use strict"; 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); }); }