diff --git a/src/url-pattern.ts b/src/url-pattern.ts index 66867a8..673e600 100644 --- a/src/url-pattern.ts +++ b/src/url-pattern.ts @@ -340,6 +340,7 @@ export class URLPattern { #names: string[] = {}; #component_pattern: any = {}; #parts: any = {}; + #hasRegExpGroups: boolean = false; constructor(init: URLPatternInit | string, baseURL?: string, options?: URLPatternOptions); constructor(init: URLPatternInit | string, options?: URLPatternOptions); @@ -449,6 +450,8 @@ export class URLPattern { this.#parts[component] = parse(pattern as string, options); this.#regexp[component] = partsToRegexp(this.#parts[component], /* out */ this.#names[component], options); this.#component_pattern[component] = partsToPattern(this.#parts[component], options); + this.#hasRegExpGroups = this.#hasRegExpGroups || + this.#parts[component].some((p: Part) => p.type === PartType.kRegex); } catch (err) { // If a pattern is illegal the constructor will throw an exception throw new TypeError(`invalid ${component} pattern '${this.#pattern[component]}'.`); @@ -680,4 +683,8 @@ export class URLPattern { public get hash() { return this.#component_pattern.hash; } + + public get hasRegExpGroups() { + return this.#hasRegExpGroups; + } } diff --git a/test/urlpattern-hasregexpgroups-tests.js b/test/urlpattern-hasregexpgroups-tests.js new file mode 100644 index 0000000..e8ddbe4 --- /dev/null +++ b/test/urlpattern-hasregexpgroups-tests.js @@ -0,0 +1,24 @@ +import test from "ava"; +import "urlpattern-polyfill"; + +test("URLPattern.hasRegExpGroups", t => { + const assert_true = (actual, msg) => t.true(actual, msg); + const assert_false = (actual, msg) => t.false(actual, msg); + + assert_true('hasRegExpGroups' in URLPattern.prototype, "hasRegExpGroups is not implemented"); + assert_false(new URLPattern({}).hasRegExpGroups, "match-everything pattern"); + for (let component of ['protocol', 'username', 'password', 'hostname', 'port', 'pathname', 'search', 'hash']) { + assert_false(new URLPattern({[component]: '*'}).hasRegExpGroups, `wildcard in ${component}`); + assert_false(new URLPattern({[component]: ':foo'}).hasRegExpGroups, `segment wildcard in ${component}`); + assert_false(new URLPattern({[component]: ':foo?'}).hasRegExpGroups, `optional segment wildcard in ${component}`); + assert_true(new URLPattern({[component]: ':foo(hi)'}).hasRegExpGroups, `named regexp group in ${component}`); + assert_true(new URLPattern({[component]: '(hi)'}).hasRegExpGroups, `anonymous regexp group in ${component}`); + if (component !== 'protocol' && component !== 'port') { + // These components are more narrow in what they accept in any case. + assert_false(new URLPattern({[component]: 'a-{:hello}-z-*-a'}).hasRegExpGroups, `wildcards mixed in with fixed text and wildcards in ${component}`); + assert_true(new URLPattern({[component]: 'a-(hi)-z-(lo)-a'}).hasRegExpGroups, `regexp groups mixed in with fixed text and wildcards in ${component}`); + } + } + assert_false(new URLPattern({pathname: '/a/:foo/:baz?/b/*'}).hasRegExpGroups, "complex pathname with no regexp"); + assert_true(new URLPattern({pathname: '/a/:foo/:baz([a-z]+)?/b/*'}).hasRegExpGroups, "complex pathname with regexp"); +}); \ No newline at end of file