Skip to content

Commit

Permalink
feat: support for case-insensitive matches (#168)
Browse files Browse the repository at this point in the history
This commit updates the specification document with the support of
case-insensitive matches by introducing a third argument in the
`URLPattern` constructor. This additional document contains a single
boolean property named `ignoreCase`, which can be set to `true` to
enable case-insensitive matches. By default this flag is set to `false`,
thus enabling case-sensitive matches.
  • Loading branch information
Sayan751 authored Sep 22, 2022
1 parent 26b794d commit 7a09f4e
Showing 1 changed file with 34 additions and 10 deletions.
44 changes: 34 additions & 10 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ typedef (USVString or URLPatternInit) URLPatternInput;

[Exposed=(Window,Worker)]
interface URLPattern {
constructor(optional URLPatternInput input = {}, optional USVString baseURL);
constructor(optional URLPatternInput input = {}, optional USVString baseURL, optional URLPatternOptions options = {});

boolean test(optional URLPatternInput input = {}, optional USVString baseURL);

Expand Down Expand Up @@ -148,6 +148,10 @@ dictionary URLPatternInit {
USVString baseURL;
};

dictionary URLPatternOptions {
boolean ignoreCase = false;
};

dictionary URLPatternResult {
sequence<URLPatternInput> inputs;

Expand Down Expand Up @@ -184,16 +188,28 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>search componen
Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component</dfn>, a [=component=], which must be set upon creation.

<dl class="domintro non-normative">
<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL)|URLPattern}}(|input|)</code></dt>
<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL, options)|URLPattern}}(|input|)</code></dt>
<dd>
Constructs a new {{URLPattern}} object. The |input| is an object containing separate patterns for each URL component; e.g. hostname, pathname, etc. Missing components will default to a wildcard pattern. In addition, |input| can contain a {{URLPatternInit/baseURL}} property that provides static text patterns for any missing components.
</dd>

<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL)|URLPattern}}(|patternString|, |baseURL|)</code></dt>
<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL, options)|URLPattern}}(|patternString|, |baseURL|)</code></dt>
<dd>
Constructs a new {{URLPattern}} object. |patternString| is a URL string containing pattern syntax for one or more components. If |baseURL| is provided, then |patternString| can be relative. This constructor will always set at least an empty string value and does not default any components to wildcard patterns.
</dd>

<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL, options)|URLPattern}}(|input|, |options|)</code></dt>
<dd>
Constructs a new {{URLPattern}} object. The |options| is an object containing the additional configuration options that can affect how the components are matched. Currently it has only one property {{URLPatternOptions/ignoreCase}} which can be set to true to enable case-insensitive matching.

Note that by default, that is in the absence of the |options| argument, matching is always case-sensitive.
</dd>

<dt><code>|urlPattern| = new {{URLPattern/constructor(input, baseURL, options)|URLPattern}}(|patternString|, |baseURL|, |options|)</code></dt>
<dd>
Constructs a new {{URLPattern}} object. This overrides supports a {{URLPatternOptions}} object when constructing a pattern from a |patternString| object, describing the patterns for individual components, and base URL.
</dd>

<dt><code>|matches| = |urlPattern|.{{URLPattern/test(input, baseURL)|test}}(|input|)</code></dt>
<dd>
Tests if |urlPattern| matches the given arguments. The |input| is an object containing strings representing each URL component; e.g. hostname, pathname, etc. Missing components are treated as empty strings. In addition, |input| can contain a {{URLPatternInit/baseURL}} property that provides values for any missing components. If |urlPattern| matches the |input| on a component-by-component basis then true is returned. Otherwise, false is returned.
Expand Down Expand Up @@ -262,7 +278,7 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component<
</dl>

<div algorithm>
The <dfn constructor for=URLPattern lt="URLPattern(input, baseURL)">new URLPattern(|input|, |baseURL|)</dfn> constructor steps are:
The <dfn constructor for=URLPattern lt="URLPattern(input, baseURL, options)">new URLPattern(|input|, |baseURL|, |options|)</dfn> constructor steps are:

1. Let |init| be null.
1. If |input| is a [=scalar value string=] then:
Expand All @@ -281,10 +297,13 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component<
1. If the result running [=hostname pattern is an IPv6 address=] given |processedInit|["{{URLPatternInit/hostname}}"] is true, then set [=this=]'s [=URLPattern/hostname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/hostname}}"], [=canonicalize an IPv6 hostname=], and [=hostname options=].
1. Else, set [=this=]'s [=URLPattern/hostname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/hostname}}"], [=canonicalize a hostname=], and [=hostname options=].
1. Set [=this=]'s [=URLPattern/port component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/port}}"], [=canonicalize a port=], and [=default options=].
1. If the result of running [=protocol component matches a special scheme=] given [=this=]'s [=URLPattern/protocol component=] is true, then set [=this=]'s [=URLPattern/pathname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/pathname}}"], [=canonicalize a pathname=], and [=pathname options=].
1. Else set [=this=]'s [=URLPattern/pathname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/pathname}}"], [=canonicalize an opaque pathname=], and [=default options=]
1. Set [=this=]'s [=URLPattern/search component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/search}}"], [=canonicalize a search=], and [=default options=].
1. Set [=this=]'s [=URLPattern/hash component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/hash}}"], [=canonicalize a hash=], and [=default options=].
1. Let |compileOptions| be a copy of the [=default options=] with the [=options/ignore case=] property set to |options|["{{URLPatternOptions/ignoreCase}}"].
1. If the result of running [=protocol component matches a special scheme=] given [=this=]'s [=URLPattern/protocol component=] is true, then:
1. Let |pathCompileOptions| be copy of the [=pathname options=] with the the [=options/ignore case=] property set to |options|["{{URLPatternOptions/ignoreCase}}"].
1. Set [=this=]'s [=URLPattern/pathname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/pathname}}"], [=canonicalize a pathname=], and |pathCompileOptions|.
1. Else set [=this=]'s [=URLPattern/pathname component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/pathname}}"], [=canonicalize an opaque pathname=], and |compileOptions|.
1. Set [=this=]'s [=URLPattern/search component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/search}}"], [=canonicalize a search=], and |compileOptions|.
1. Set [=this=]'s [=URLPattern/hash component=] to the result of [=compiling a component=] given |processedInit|["{{URLPatternInit/hash}}"], [=canonicalize a hash=], and |compileOptions|.
</div>

<div algorithm>
Expand Down Expand Up @@ -365,7 +384,10 @@ A [=component=] has an associated <dfn for=component>group name list</dfn>, a [=
1. If |input| is null, then set |input| to "`*`".
1. Let |part list| be the result of running [=parse a pattern string=] given |input|, |options|, and |encoding callback|.
1. Let (|regular expression string|, |name list|) be the result of running [=generate a regular expression and name list=] given |part list| and |options|.
1. Let |regular expression| be [$RegExpCreate$](|regular expression string|, "`u`"). If this throws an exception, catch it, and throw a {{TypeError}}.
1. Let |flags| be an empty string.
1. If |options|'s [=options/ignore case=] is true then set |flags| to "`ui`".
1. Else set |flags| to "`u`"
1. Let |regular expression| be [$RegExpCreate$](|regular expression string|, |flags|). If this throws an exception, catch it, and throw a {{TypeError}}.
<p class="note allow-2119">The specification uses regular expressions to perform all matching, but this is not required. Implementations are free to perform matching directly against the [=/part list=] when possible; e.g. when there are no custom regexp matching groups. If there are custom regular expressions, however, its important that they should be immediately evaluated in the [=compile a component=] algorithm so an error can be thrown if they are invalid.
1. Let |pattern string| be the result of running [=generate a pattern string=] given |part list| and |options|.
1. Return a new [=component=] whose [=component/pattern string=] is |pattern string|, [=component/regular expression=] is |regular expression|, and [=component/group name list=] is |name list|.
Expand Down Expand Up @@ -1074,12 +1096,14 @@ A [=part=] has an associated <dfn for=part>suffix</dfn>, a string, initially the

<h4 id=options-header>Options</h4>

An <dfn>options</dfn> [=struct=] contains different settings that control how [=/pattern string=] behaves. These options originally come from [path-to-regexp](https://github.com/pillarjs/path-to-regexp). We only include the options that are modified within the URLPattern specification and exclude the other options. For the purposes of comparison, this specification acts like [path-to-regexp](https://github.com/pillarjs/path-to-regexp) where `sensitive`, `strict`, `start`, and `end` are always set to true.
An <dfn>options</dfn> [=struct=] contains different settings that control how [=/pattern string=] behaves. These options originally come from [path-to-regexp](https://github.com/pillarjs/path-to-regexp). We only include the options that are modified within the URLPattern specification and exclude the other options. For the purposes of comparison, this specification acts like [path-to-regexp](https://github.com/pillarjs/path-to-regexp) where `strict`, `start`, and `end` are always set to false.

An [=/options=] has an associated <dfn for=options>delimiter code point</dfn>, a string, which must be set upon creation. It must contain one [=ASCII code point=] or the empty string. This code point is treated as a segment separator and is used for determining how far a `:foo` named group should match by default. For example, if the [=options/delimiter code point=] is "`/`" then "`/:foo`" will match "`/bar`", but not "`/bar/baz`". If the [=options/delimiter code point=] is the empty string then the example pattern would match both strings.

An [=/options=] has an associated <dfn for=options>prefix code point</dfn>, a string, which must be set upon creation. It must contain one [=ASCII code point=] or the empty string. The code point is treated as an automatic prefix if found immediately preceding a match group. This matters when a match group is modified to be optional or repeating. For example, if [=options/prefix code point=] is "`/`" then "`/foo/:bar?/baz`" will treat the "`/`" before "`:bar`" as a prefix that becomes optional along with the named group. So in this example the pattern would match "`/foo/baz`".

An [=/options=] has an associated <dfn for=options>ignore case</dfn>, a boolean, which must be set up upon creation. It defaults to false. Depending on the set value, true or false, this flag enables case-sensitive or case-insensitive matches, respectively. For the purpose of comparison, this case be thought of as the negated `sensitive` option in [path-to-regexp](https://github.com/pillarjs/path-to-regexp).

<h4 id=parsing>Parsing</h4>

<div algorithm>
Expand Down

0 comments on commit 7a09f4e

Please sign in to comment.