*/
function checkPathOrder(paths, options = {}) {
const matchers = paths
+ .slice()
+ // Because sorting order is conserved, allows to mismatch order on
+ // routes with the same ranking
+ .reverse()
.map(path =>
createRouteMatcher(
{
checkPathOrder(['/', '/:rest(.*)'])
})
+ it('prioritises custom regex', () => {
+ checkPathOrder(['/:a(\\d+)', '/:a', '/:a(.*)'])
+ checkPathOrder(['/b-:a(\\d+)', '/b-:a', '/b-:a(.*)'])
+ })
+
it('handles sub segments optional params', () => {
// TODO: /a/c should be be bigger than /a/c/:b?
- checkPathOrder(['/a/d/c', '/a/b/c:b', '/a/c/:b?', '/a/c'])
+ checkPathOrder(['/a/d/c', '/a/b/c:b', '/a/c/:b', '/a/c/:b?', '/a/c'])
})
it('handles optional in sub segments', () => {
checkPathOrder([
- '/a/__',
'/a/_2_',
- '/a/_:b\\_', // the _ is escaped
// something like /a/_23_
'/a/_:b(\\d)?_',
+ '/a/_:b\\_', // the _ is escaped but b can be also letters
'/a/a_:b',
- '/a/_:b_', // the _ is part of the identifier
])
})
SubSegment = 2, // /multiple-:things-in-one-:segment
Static = 3, // /static
Dynamic = 2, // /:someId
+ DynamicCustomRegexp = 2.5, // /:someId(\\d+)
Wildcard = -1, // /:namedWildcard(.*)
SubWildcard = 1, // Wildcard as a subsegment
Repeatable = -0.5, // /:w+ or /:w*
Root = 1, // just /
}
+// allows to check if the user provided a custom regexp
+const isDefaultPathRegExpRE = /^\[\^[^\]]+\]\+\?$/
+
export function createRouteMatcher(
record: Readonly<NormalizedRouteRecord>,
parent: RouteMatcher | void,
if (typeof group === 'string') {
score += group === '/' ? PathScore.Root : PathScore.Static
} else {
- score += group.pattern === '.*' ? PathScore.Wildcard : PathScore.Dynamic
+ score +=
+ group.pattern === '.*'
+ ? PathScore.Wildcard
+ : isDefaultPathRegExpRE.test(group.pattern)
+ ? PathScore.Dynamic
+ : PathScore.DynamicCustomRegexp
score +=
+group.optional * PathScore.Optional +
+group.repeat * PathScore.Repeatable
score += PathScore.Static
} else {
score +=
- group.pattern === '.*' ? PathScore.SubWildcard : PathScore.Dynamic
+ group.pattern === '.*'
+ ? PathScore.SubWildcard
+ : isDefaultPathRegExpRE.test(group.pattern)
+ ? PathScore.Dynamic
+ : PathScore.DynamicCustomRegexp
score += +group.optional * PathScore.SubOptional
if (typeof group.name === 'number') throw new Error('Name your param')
// keys.push(group.name)