@marianmeres/simple-router 1.9.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/index.cjs +34 -11
- package/dist/index.js +34 -11
- package/dist/route.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ Route segments:
|
|
|
40
40
|
- `[name(regex)]` matches if `regex.test(segment)` is truthy
|
|
41
41
|
- `exact?` or `[name]?` marks segment as optional
|
|
42
42
|
- `[...name]` matches "rest segments"
|
|
43
|
+
- `*` matches zero or more following segments
|
|
43
44
|
|
|
44
45
|
Few notes on segments separators (which is slash `/` by default):
|
|
45
46
|
- multiple ones are always normalized to single,
|
|
@@ -68,8 +69,11 @@ Few notes on segments separators (which is slash `/` by default):
|
|
|
68
69
|
| `/foo/[id([0-9]+)]/[bar]` | `/foo/bar/baz` | `null` |
|
|
69
70
|
| `/foo/[([0-9]+)]` | `/foo/123` | `null` (missing name before regex) |
|
|
70
71
|
| `/foo/[bar]?` | `/foo` | `{}` |
|
|
71
|
-
| `/foo/[bar]?` | `/foo/bar` | `{ bar:
|
|
72
|
-
| `/foo/[bar]?/baz` | `/foo/bar/baz` | `{ bar:
|
|
73
|
-
| `/[...path]/[file]` | `/foo/bar/baz.js` | `{ path
|
|
72
|
+
| `/foo/[bar]?` | `/foo/bar` | `{ bar: "bar" }` |
|
|
73
|
+
| `/foo/[bar]?/baz` | `/foo/bar/baz` | `{ bar: "bar" }` |
|
|
74
|
+
| `/[...path]/[file]` | `/foo/bar/baz.js` | `{ path: "foo/bar", file: "baz.js" }`|
|
|
75
|
+
| `/foo/*` | `/foo/bar/baz.js` | `{}` |
|
|
76
|
+
| `/[foo]/*` | `/foo/bar` | `{ foo: "foo" }` |
|
|
77
|
+
| `/*` | `/foo/bar` | `{}` |
|
|
74
78
|
See [tests](tests) or [examples](examples) for more.
|
|
75
79
|
|
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
class SimpleRoute {
|
|
4
4
|
route;
|
|
5
5
|
static SPLITTER = '/';
|
|
6
|
+
static WILDCARD = '*';
|
|
6
7
|
_parsed;
|
|
7
8
|
constructor(route) {
|
|
8
9
|
this.route = route;
|
|
@@ -25,7 +26,8 @@ class SimpleRoute {
|
|
|
25
26
|
}
|
|
26
27
|
static _parse(route) {
|
|
27
28
|
let wasSpread = false;
|
|
28
|
-
|
|
29
|
+
let wasWildcard = false;
|
|
30
|
+
return SimpleRoute._sanitizeAndSplit(route).reduce((memo, segment, idx, all) => {
|
|
29
31
|
let name = null;
|
|
30
32
|
// if optional, remove trailing '?' marker
|
|
31
33
|
let isOptional = segment.endsWith('?');
|
|
@@ -43,17 +45,30 @@ class SimpleRoute {
|
|
|
43
45
|
segment = '[' + segment.slice(4);
|
|
44
46
|
}
|
|
45
47
|
let test = new RegExp('^' + SimpleRoute._escapeRegExp(segment) + '$');
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
test = /.+/;
|
|
51
|
-
// id([0-9]+)
|
|
52
|
-
let m2 = m[1].match(/^(\w.*)\((.+)\)$/);
|
|
53
|
-
if (m2) {
|
|
54
|
-
name = m2[1];
|
|
55
|
-
test = new RegExp('^' + m2[2] + '$');
|
|
48
|
+
// catch all wildcard
|
|
49
|
+
if (segment === SimpleRoute.WILDCARD) {
|
|
50
|
+
if (idx < all.length - 1) {
|
|
51
|
+
throw new Error(`Wildcard '${SimpleRoute.WILDCARD}' can be used only as a last segment`);
|
|
56
52
|
}
|
|
53
|
+
wasWildcard = true;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// starting with at least one word char within brackets...
|
|
57
|
+
let m = segment.match(/^\[(\w.*)]$/);
|
|
58
|
+
if (m) {
|
|
59
|
+
name = m[1];
|
|
60
|
+
test = /.+/;
|
|
61
|
+
// id([0-9]+)
|
|
62
|
+
let m2 = m[1].match(/^(\w.*)\((.+)\)$/);
|
|
63
|
+
if (m2) {
|
|
64
|
+
name = m2[1];
|
|
65
|
+
test = new RegExp('^' + m2[2] + '$');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (wasWildcard) {
|
|
70
|
+
isOptional = true;
|
|
71
|
+
test = /.*/;
|
|
57
72
|
}
|
|
58
73
|
memo.push({ segment, name, test, isOptional, isSpread });
|
|
59
74
|
return memo;
|
|
@@ -105,6 +120,11 @@ class SimpleRoute {
|
|
|
105
120
|
});
|
|
106
121
|
segments = newSegments;
|
|
107
122
|
}
|
|
123
|
+
// return early no-op special case: first segment is a wildcard
|
|
124
|
+
// (no need to process further)
|
|
125
|
+
if (this._parsed?.[0]?.segment === SimpleRoute.WILDCARD) {
|
|
126
|
+
return matched;
|
|
127
|
+
}
|
|
108
128
|
// minimum required (not optional) segments length
|
|
109
129
|
const reqLen = this._parsed.reduce((memo, p, idx, arr) => {
|
|
110
130
|
const next = arr[idx + 1];
|
|
@@ -126,6 +146,9 @@ class SimpleRoute {
|
|
|
126
146
|
if (p.name) {
|
|
127
147
|
matched[decodeURIComponent(p.name)] = decodeURIComponent(s);
|
|
128
148
|
}
|
|
149
|
+
if (p.segment === SimpleRoute.WILDCARD) {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
129
152
|
}
|
|
130
153
|
return matched;
|
|
131
154
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
class SimpleRoute {
|
|
2
2
|
route;
|
|
3
3
|
static SPLITTER = '/';
|
|
4
|
+
static WILDCARD = '*';
|
|
4
5
|
_parsed;
|
|
5
6
|
constructor(route) {
|
|
6
7
|
this.route = route;
|
|
@@ -23,7 +24,8 @@ class SimpleRoute {
|
|
|
23
24
|
}
|
|
24
25
|
static _parse(route) {
|
|
25
26
|
let wasSpread = false;
|
|
26
|
-
|
|
27
|
+
let wasWildcard = false;
|
|
28
|
+
return SimpleRoute._sanitizeAndSplit(route).reduce((memo, segment, idx, all) => {
|
|
27
29
|
let name = null;
|
|
28
30
|
// if optional, remove trailing '?' marker
|
|
29
31
|
let isOptional = segment.endsWith('?');
|
|
@@ -41,17 +43,30 @@ class SimpleRoute {
|
|
|
41
43
|
segment = '[' + segment.slice(4);
|
|
42
44
|
}
|
|
43
45
|
let test = new RegExp('^' + SimpleRoute._escapeRegExp(segment) + '$');
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
test = /.+/;
|
|
49
|
-
// id([0-9]+)
|
|
50
|
-
let m2 = m[1].match(/^(\w.*)\((.+)\)$/);
|
|
51
|
-
if (m2) {
|
|
52
|
-
name = m2[1];
|
|
53
|
-
test = new RegExp('^' + m2[2] + '$');
|
|
46
|
+
// catch all wildcard
|
|
47
|
+
if (segment === SimpleRoute.WILDCARD) {
|
|
48
|
+
if (idx < all.length - 1) {
|
|
49
|
+
throw new Error(`Wildcard '${SimpleRoute.WILDCARD}' can be used only as a last segment`);
|
|
54
50
|
}
|
|
51
|
+
wasWildcard = true;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// starting with at least one word char within brackets...
|
|
55
|
+
let m = segment.match(/^\[(\w.*)]$/);
|
|
56
|
+
if (m) {
|
|
57
|
+
name = m[1];
|
|
58
|
+
test = /.+/;
|
|
59
|
+
// id([0-9]+)
|
|
60
|
+
let m2 = m[1].match(/^(\w.*)\((.+)\)$/);
|
|
61
|
+
if (m2) {
|
|
62
|
+
name = m2[1];
|
|
63
|
+
test = new RegExp('^' + m2[2] + '$');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (wasWildcard) {
|
|
68
|
+
isOptional = true;
|
|
69
|
+
test = /.*/;
|
|
55
70
|
}
|
|
56
71
|
memo.push({ segment, name, test, isOptional, isSpread });
|
|
57
72
|
return memo;
|
|
@@ -103,6 +118,11 @@ class SimpleRoute {
|
|
|
103
118
|
});
|
|
104
119
|
segments = newSegments;
|
|
105
120
|
}
|
|
121
|
+
// return early no-op special case: first segment is a wildcard
|
|
122
|
+
// (no need to process further)
|
|
123
|
+
if (this._parsed?.[0]?.segment === SimpleRoute.WILDCARD) {
|
|
124
|
+
return matched;
|
|
125
|
+
}
|
|
106
126
|
// minimum required (not optional) segments length
|
|
107
127
|
const reqLen = this._parsed.reduce((memo, p, idx, arr) => {
|
|
108
128
|
const next = arr[idx + 1];
|
|
@@ -124,6 +144,9 @@ class SimpleRoute {
|
|
|
124
144
|
if (p.name) {
|
|
125
145
|
matched[decodeURIComponent(p.name)] = decodeURIComponent(s);
|
|
126
146
|
}
|
|
147
|
+
if (p.segment === SimpleRoute.WILDCARD) {
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
127
150
|
}
|
|
128
151
|
return matched;
|
|
129
152
|
}
|
package/dist/route.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface RouteConfig {
|
|
|
8
8
|
export declare class SimpleRoute {
|
|
9
9
|
readonly route: any;
|
|
10
10
|
static SPLITTER: string;
|
|
11
|
+
static WILDCARD: string;
|
|
11
12
|
protected _parsed: RouteConfig[];
|
|
12
13
|
constructor(route: any);
|
|
13
14
|
protected static _escapeRegExp(str: string): string;
|