Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit f50d3c4

Browse files
committed
error if routes clash - fixes #33
1 parent 8925e54 commit f50d3c4

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

lib/utils/create_routes.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const path = require('path');
22

33
module.exports = function create_matchers(files) {
4-
return files
4+
const routes = files
55
.map(file => {
66
if (/(^|\/|\\)_/.test(file)) return;
77

@@ -47,9 +47,31 @@ module.exports = function create_matchers(files) {
4747
})
4848
.filter(Boolean)
4949
.sort((a, b) => {
50-
return (
51-
(a.dynamic.length - b.dynamic.length) || // match static paths first
52-
(b.parts.length - a.parts.length) // match longer paths first
53-
);
50+
let same = true;
51+
52+
for (let i = 0; true; i += 1) {
53+
const a_part = a.parts[i];
54+
const b_part = b.parts[i];
55+
56+
if (!a_part && !b_part) {
57+
if (same) throw new Error(`The ${a.file} and ${b.file} routes clash`);
58+
return 0;
59+
}
60+
61+
if (!a_part) return 1;
62+
if (!b_part) return -1;
63+
64+
const a_is_dynamic = a_part[0] === '[';
65+
const b_is_dynamic = b_part[0] === '[';
66+
67+
if (a_is_dynamic === b_is_dynamic) {
68+
if (!a_is_dynamic) same = false;
69+
continue;
70+
}
71+
72+
return a_is_dynamic ? 1 : -1;
73+
}
5474
});
75+
76+
return routes;
5577
}

test/unit/create_routes.test.js

+27-4
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ const create_routes = require('../../lib/utils/create_routes.js');
55

66
describe('create_routes', () => {
77
it('sorts routes correctly', () => {
8-
const routes = create_routes(['index.html', 'about.html', '[wildcard].html', 'post/[id].html']);
8+
const routes = create_routes(['index.html', 'about.html', '[wildcard].html', 'post/foo.html', 'post/[id].html', 'post/bar.html']);
99

1010
assert.deepEqual(
1111
routes.map(r => r.file),
1212
[
13-
'about.html',
14-
'index.html',
13+
'post/foo.html',
14+
'post/bar.html',
1515
'post/[id].html',
16-
'[wildcard].html'
16+
'about.html',
17+
'[wildcard].html',
18+
'index.html'
1719
]
1820
);
1921
});
@@ -48,4 +50,25 @@ describe('create_routes', () => {
4850
]
4951
);
5052
});
53+
54+
it('matches /foo/:bar before /:baz/qux', () => {
55+
const a = create_routes(['foo/[bar].html', '[baz]/qux.html']);
56+
const b = create_routes(['[baz]/qux.html', 'foo/[bar].html']);
57+
58+
assert.deepEqual(
59+
a.map(r => r.file),
60+
['foo/[bar].html', '[baz]/qux.html']
61+
);
62+
63+
assert.deepEqual(
64+
b.map(r => r.file),
65+
['foo/[bar].html', '[baz]/qux.html']
66+
);
67+
});
68+
69+
it('fails if routes are indistinguishable', () => {
70+
assert.throws(() => {
71+
create_routes(['[foo].html', '[bar]/index.html']);
72+
}, /The \[foo\].html and \[bar\]\/index.html routes clash/);
73+
});
5174
});

0 commit comments

Comments
 (0)