|
12 | 12 | * - [[HookMatchCriteria.retained]]
|
13 | 13 | * - [[HookMatchCriteria.entering]]
|
14 | 14 | *
|
15 |
| - * A `Glob` string is a pattern which matches state names according to the following rules: |
| 15 | + * A `Glob` string is a pattern which matches state names. |
| 16 | + * Nested state names are split into segments (separated by a dot) when processing. |
| 17 | + * The state named `foo.bar.baz` is split into three segments ['foo', 'bar', 'baz'] |
| 18 | + * |
| 19 | + * Globs work according to the following rules: |
16 | 20 | *
|
17 | 21 | * ### Exact match:
|
18 | 22 | *
|
19 | 23 | * The glob `'A.B'` matches the state named exactly `'A.B'`.
|
20 | 24 | *
|
21 | 25 | * | Glob |Matches states named|Does not match state named|
|
22 |
| - * |:------------|:--------------------|:-----------------| |
23 |
| - * | `'A'` | `'A'` | `'B'` , `'A.C'` | |
24 |
| - * | `'A.B'` | `'A.B'` | `'A'` , `'A.B.C'`| |
| 26 | + * |:------------|:--------------------|:---------------------| |
| 27 | + * | `'A'` | `'A'` | `'B'` , `'A.C'` | |
| 28 | + * | `'A.B'` | `'A.B'` | `'A'` , `'A.B.C'` | |
| 29 | + * | `'foo'` | `'foo'` | `'FOO'` , `'foo.bar'`| |
25 | 30 | *
|
26 |
| - * ### Single wildcard (`*`) |
| 31 | + * ### Single star (`*`) |
27 | 32 | *
|
28 |
| - * A single wildcard (`*`) matches any value for *a single segment* of a state name. |
| 33 | + * A single star (`*`) is a wildcard that matches exactly one segment. |
29 | 34 | *
|
30 | 35 | * | Glob |Matches states named |Does not match state named |
|
31 | 36 | * |:------------|:---------------------|:--------------------------|
|
32 |
| - * | `'A.*'` | `'A.B'` , `'A.C'` | `'A'` , `'A.B.C'` | |
33 | 37 | * | `'*'` | `'A'` , `'Z'` | `'A.B'` , `'Z.Y.X'` |
|
| 38 | + * | `'A.*'` | `'A.B'` , `'A.C'` | `'A'` , `'A.B.C'` | |
34 | 39 | * | `'A.*.*'` | `'A.B.C'` , `'A.X.Y'`| `'A'`, `'A.B'` , `'Z.Y.X'`|
|
35 | 40 | *
|
| 41 | + * ### Double star (`**`) |
36 | 42 | *
|
37 |
| - * ### Double wildcards (`**`) |
| 43 | + * A double star (`'**'`) is a wildcard that matches *zero or more segments* |
38 | 44 | *
|
39 |
| - * Double wildcards (`'**'`) act as a wildcard for *one or more segments* |
40 |
| - * |
41 |
| - * | Glob |Matches states named |Does not match state named| |
42 |
| - * |:------------|:----------------------------------------------|:-------------------------| |
43 |
| - * | `'**'` | `'A'` , `'A.B'`, `'Z.Y.X'` | (matches all states) | |
44 |
| - * | `'A.**'` | `'A.B'` , `'A.C'` , `'A.B.X'` | `'A'`, `'Z.Y.X'` | |
45 |
| - * | `'**.login'`| `'A.login'` , `'A.B.login'` , `'Z.Y.X.login'` | `'A'` , `'login'` , `'A.login.Z'` | |
| 45 | + * | Glob |Matches states named |Does not match state named | |
| 46 | + * |:------------|:----------------------------------------------|:----------------------------------| |
| 47 | + * | `'**'` | `'A'` , `'A.B'`, `'Z.Y.X'` | (matches all states) | |
| 48 | + * | `'A.**'` | `'A'` , `'A.B'` , `'A.C.X'` | `'Z.Y.X'` | |
| 49 | + * | `'**.X'` | `'X'` , `'A.X'` , `'Z.Y.X'` | `'A'` , `'A.login.Z'` | |
| 50 | + * | `'A.**.X'` | `'A.X'` , `'A.B.X'` , `'A.B.C.X'` | `'A'` , `'A.B.C'` | |
46 | 51 | *
|
47 | 52 | */
|
48 | 53 | export class Glob {
|
49 | 54 | text: string;
|
50 | 55 | glob: Array<string>;
|
| 56 | + regexp: RegExp; |
51 | 57 |
|
52 | 58 | constructor(text: string) {
|
53 | 59 | this.text = text;
|
54 | 60 | this.glob = text.split('.');
|
55 |
| - } |
56 | 61 |
|
57 |
| - matches(name: string) { |
58 |
| - let segments = name.split('.'); |
59 |
| - |
60 |
| - // match single stars |
61 |
| - for (let i = 0, l = this.glob.length; i < l; i++) { |
62 |
| - if (this.glob[i] === '*') segments[i] = '*'; |
63 |
| - } |
| 62 | + let regexpString = this.text.split('.') |
| 63 | + .map(seg => { |
| 64 | + if (seg === '**') return '(?:|(?:\\.[^.]*)*)'; |
| 65 | + if (seg === '*') return '\\.[^.]*'; |
| 66 | + return '\\.' + seg; |
| 67 | + }).join(''); |
64 | 68 |
|
65 |
| - // match greedy starts |
66 |
| - if (this.glob[0] === '**') { |
67 |
| - segments = segments.slice(segments.indexOf(this.glob[1])); |
68 |
| - segments.unshift('**'); |
69 |
| - } |
70 |
| - // match greedy ends |
71 |
| - if (this.glob[this.glob.length - 1] === '**') { |
72 |
| - segments.splice(segments.indexOf(this.glob[this.glob.length - 2]) + 1, Number.MAX_VALUE); |
73 |
| - segments.push('**'); |
74 |
| - } |
75 |
| - if (this.glob.length != segments.length) return false; |
| 69 | + this.regexp = new RegExp("^" + regexpString + "$"); |
| 70 | + } |
76 | 71 |
|
77 |
| - return segments.join('') === this.glob.join(''); |
| 72 | + matches(name: string) { |
| 73 | + return this.regexp.test('.' + name); |
78 | 74 | }
|
79 | 75 |
|
| 76 | + /** @deprecated whats the point? */ |
80 | 77 | static is(text: string) {
|
81 | 78 | return text.indexOf('*') > -1;
|
82 | 79 | }
|
83 | 80 |
|
| 81 | + /** @deprecated whats the point? */ |
84 | 82 | static fromString(text: string) {
|
85 | 83 | if (!this.is(text)) return null;
|
86 | 84 | return new Glob(text);
|
|
0 commit comments