Skip to content

Commit 98b95d0

Browse files
authored
fix: Wildcard splat/rest param matches should return undefined instead of empty strings (#45)
* fix: Wildcard splat matches * docs: Add docs for spat/rest param routes
1 parent 8490100 commit 98b95d0

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,22 @@ Paths are matched using a simple string matching algorithm. The following featur
170170
- `:param` - Matches any URL segment, binding the value to the label (can later extract this value from `useRoute()`)
171171
- `/profile/:id` will match `/profile/123` and `/profile/abc`
172172
- `/profile/:id?` will match `/profile` and `/profile/123`
173+
- `/profile/:id*` will match `/profile`, `/profile/123`, and `/profile/123/abc`
174+
- `/profile/:id+` will match `/profile/123`, `/profile/123/abc`
173175
- `*` - Matches one or more URL segments
174176
- `/profile/*` will match `/profile/123`, `/profile/123/abc`, etc.
175177

176178
These can then be composed to create more complex routes:
177179

178180
- `/profile/:id/*` will match `/profile/123/abc`, `/profile/123/abc/def`, etc.
179181

182+
The difference between `/:id*` and `/:id/*` is that in the former, the `id` param will include the entire path after it, while in the latter, the `id` is just the single path segment.
183+
184+
- `/profile/:id*`, with `/profile/123/abc`
185+
- `id` is `123/abc`
186+
- `/profile/:id/*`, with `/profile/123/abc`
187+
- `id` is `123`
188+
180189
### `useLocation`
181190

182191
A hook to work with the `LocationProvider` to access location context.

src/router.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const exec = (url, route, matches) => {
6565
if (!m || (!val && flag != '?' && flag != '*')) return;
6666
rest = flag == '+' || flag == '*';
6767
// rest (+/*) match:
68-
if (rest) val = url.slice(i).map(decodeURIComponent).join('/');
68+
if (rest) val = url.slice(i).map(decodeURIComponent).join('/') || undefined;
6969
// normal/optional field:
7070
else if (val) val = decodeURIComponent(val);
7171
matches.params[param] = val;

test/node/router-match.test.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,26 @@ test('Optional param route', () => {
5858
});
5959

6060
test('Optional rest param route "/:x*"', () => {
61-
const accurateResult = execPath('/user', '/user/:id?');
62-
assert.equal(accurateResult, { path: '/user', params: { id: undefined }, id: undefined, query: {} });
61+
const matchedResult = execPath('/user', '/user/:id*');
62+
assert.equal(matchedResult, { path: '/user', params: { id: undefined }, id: undefined, query: {} });
6363

64-
const inaccurateResult = execPath('/', '/user/:id?');
64+
const matchedResultWithSlash = execPath('/user/foo/bar', '/user/:id*');
65+
assert.equal(matchedResultWithSlash, {
66+
path: '/user/foo/bar',
67+
params: { id: 'foo/bar' },
68+
id: 'foo/bar',
69+
query: {}
70+
});
71+
72+
const emptyResult = execPath('/user', '/user/:id*');
73+
assert.equal(emptyResult, {
74+
path: '/user',
75+
params: { id: undefined },
76+
id: undefined,
77+
query: {}
78+
});
79+
80+
const inaccurateResult = execPath('/', '/user/:id*');
6581
assert.equal(inaccurateResult, undefined);
6682
});
6783

0 commit comments

Comments
 (0)