From: Eduardo San Martin Morote Date: Fri, 12 Jul 2019 10:14:31 +0000 (+0200) Subject: fix(matcher): handle custom regexp path ranking X-Git-Tag: v4.0.0-alpha.0~298 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a55a86584b85b41a3fdbcd47c1b564c4a73e3c9c;p=thirdparty%2Fvuejs%2Frouter.git fix(matcher): handle custom regexp path ranking --- diff --git a/__tests__/matcher-ranking.spec.js b/__tests__/matcher-ranking.spec.js index 5cde0fcf..30f5799e 100644 --- a/__tests__/matcher-ranking.spec.js +++ b/__tests__/matcher-ranking.spec.js @@ -24,6 +24,10 @@ describe('createRouteMatcher', () => { */ 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( { @@ -72,20 +76,23 @@ describe('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 ]) }) diff --git a/src/matcher.ts b/src/matcher.ts index cfd6d4db..442649a6 100644 --- a/src/matcher.ts +++ b/src/matcher.ts @@ -52,6 +52,7 @@ enum PathScore { 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* @@ -60,6 +61,9 @@ enum PathScore { Root = 1, // just / } +// allows to check if the user provided a custom regexp +const isDefaultPathRegExpRE = /^\[\^[^\]]+\]\+\?$/ + export function createRouteMatcher( record: Readonly, parent: RouteMatcher | void, @@ -182,7 +186,12 @@ export function createRouteMatcher( 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 @@ -201,7 +210,11 @@ export function createRouteMatcher( 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)