handle nested routes - fixes #55

This commit is contained in:
Rich Harris
2017-12-31 13:25:52 -05:00
parent 12b73ecebf
commit 423e02aeae
2 changed files with 64 additions and 11 deletions

View File

@@ -16,9 +16,22 @@ module.exports = function create_matchers(files) {
.filter(part => part[0] === '[')
.map(part => part.slice(1, -1));
const pattern = new RegExp(
`^\\/${parts.map(p => p[0] === '[' ? '([^/]+)' : p).join('\\/')}$`
);
let pattern_string = '';
let i = parts.length;
let nested = true;
while (i--) {
const part = parts[i];
const dynamic = part[0] === '[';
if (dynamic) {
pattern_string = nested ? `(?:\\/([^/]+)${pattern_string})?` : `\\/([^/]+)${pattern_string}`;
} else {
nested = false;
pattern_string = `\\/${part}${pattern_string}`;
}
}
const pattern = new RegExp(`^${pattern_string}$`);
const test = url => pattern.test(url);
@@ -28,7 +41,7 @@ module.exports = function create_matchers(files) {
const params = {};
dynamic.forEach((param, i) => {
params[param] = match[i + 1];
params[param] = match[i + 1] || null;
});
return params;
@@ -58,8 +71,8 @@ module.exports = function create_matchers(files) {
return 0;
}
if (!a_part) return 1;
if (!b_part) return -1;
if (!a_part) return -1;
if (!b_part) return 1;
const a_is_dynamic = a_part[0] === '[';
const b_is_dynamic = b_part[0] === '[';

View File

@@ -10,12 +10,12 @@ describe('create_routes', () => {
assert.deepEqual(
routes.map(r => r.file),
[
'index.html',
'about.html',
'post/foo.html',
'post/bar.html',
'post/[id].html',
'about.html',
'[wildcard].html',
'index.html'
'[wildcard].html'
]
);
});
@@ -45,8 +45,8 @@ describe('create_routes', () => {
assert.deepEqual(
routes.map(r => r.file),
[
'e/f/g/h.html',
'index.html'
'index.html',
'e/f/g/h.html'
]
);
});
@@ -71,4 +71,44 @@ describe('create_routes', () => {
create_routes(['[foo].html', '[bar]/index.html']);
}, /The \[foo\].html and \[bar\]\/index.html routes clash/);
});
it('matches nested routes', () => {
const route = create_routes(['settings/[submenu].html'])[0];
assert.deepEqual(route.exec('/settings/foo'), {
submenu: 'foo'
});
assert.deepEqual(route.exec('/settings'), {
submenu: null
});
});
it('prefers index routes to nested routes', () => {
const routes = create_routes(['settings/[submenu].html', 'settings.html']);
assert.deepEqual(
routes.map(r => r.file),
['settings.html', 'settings/[submenu].html']
);
});
it('matches deeply nested routes', () => {
const route = create_routes(['settings/[a]/[b]/index.html'])[0];
assert.deepEqual(route.exec('/settings/foo/bar'), {
a: 'foo',
b: 'bar'
});
assert.deepEqual(route.exec('/settings/foo'), {
a: 'foo',
b: null
});
assert.deepEqual(route.exec('/settings'), {
a: null,
b: null
});
});
});