Reproduction
https://paths.esm.dev/?p=AAMeJQ2BuMDAFAF2JXAJkhXgAXQAzhugPUAFGBrQSoB0AJln0DVAEgARIKDWCMwAtwdU5FqlITEMcMRpSTgHfQgIKUrpRABA&t=/a/section:abc
Steps to reproduce the bug
There are two related bugs, but seem to be triggered by the same issue (the reproduction link shows both bugs).
- Create a route that contains
\: immediately following a parameter, e.g. { path: '/:foo([^:]+)\\:abc' }
- Attempt to load the route by navigating to (say)
section:abc; the attempt will fail (but should succeed)
- Attempt to load the route by navigating to (say)
sectionabc; the attempt will succeed (but should fail)
- Also note that
$route.params is incorrect in the above case, containing { 'foo:': ... } instead of { foo: ... } (note the colon)
Expected behavior
A route of /:foo([^:]+)\:abc should:
- not suffix a ':' to the
foo parameter name ($route.params should be { foo: ... } and not { 'foo:': ... })
- correctly match
xxx:abc and not match xxxabc
- in other words, the generated regex should be
/^\/([^:]+):abc\/?$/i and not /^\/([^:]+)abc\/?$/i (added the missing colon)
A route of /:foo([^:]+)\::bar should additionally (on top of above expectations):
- not have
bar contain the separating colon
- e.g.
/abc:def should result in { foo: 'abc', bar: 'def' } and not { 'foo:': 'abc', bar: ':def' }
Actual behavior
Short version:
For example, the following route:
/:entityType([^:]+)\::entityID
When provided a path such as:
... will result in the following parameters in $route.params:
{
'entityType:': 'section', // note the extra colon in the *key*
entityID: ':aaabbbccc', // note the extra colon in the *value*
}
Long version:
Any parameter that's followed immediately by \:<something> (e.g. /:foo([^:]+)\:abc) appears to be mis-parsed. Specifically, the \: appears to be gobbled up and thus ignored in the actual route.
The example /:foo([^:]+)\:abc results in a regexp of /^\/([^:]+)abc\/?$/i — note the dropped colon.
This has the following consequences:
- The parameter name of the preceding parameter is appended a
: (cases /a/ and /b/ in repro link)
- The
: in the trailing value is dropped, e.g. /:foo([^:]+)\:abc matches xxxabc but not xxx:abc (case /b/˙in repro)
- If the part immediately following the
\: is itself a parameter, that parameter is value is prepended a : (this is a direct consequence of the incorrect regex) (case /a/ in repro)
Note that this only seems to happen with : (or rather \: / '\\:'); symbols such as ! or - appear to work fine (case /c/ in repro).
Additional information
Reproduced locally using vue-router@4.5.1 and online via the playground.
Workaround:
A workaround is to make a "dummy" parameter with (:) as its regex, e.g.:
With a path of /xxx:abc, this will correctly match it to the route, and result in the expected $route.params of: { foo: 'xxx', _: ':' }.
Reproduction
https://paths.esm.dev/?p=AAMeJQ2BuMDAFAF2JXAJkhXgAXQAzhugPUAFGBrQSoB0AJln0DVAEgARIKDWCMwAtwdU5FqlITEMcMRpSTgHfQgIKUrpRABA&t=/a/section:abc
Steps to reproduce the bug
There are two related bugs, but seem to be triggered by the same issue (the reproduction link shows both bugs).
\:immediately following a parameter, e.g.{ path: '/:foo([^:]+)\\:abc' }section:abc; the attempt will fail (but should succeed)sectionabc; the attempt will succeed (but should fail)$route.paramsis incorrect in the above case, containing{ 'foo:': ... }instead of{ foo: ... }(note the colon)Expected behavior
A route of
/:foo([^:]+)\:abcshould:fooparameter name ($route.paramsshould be{ foo: ... }and not{ 'foo:': ... })xxx:abcand not matchxxxabc/^\/([^:]+):abc\/?$/iand not/^\/([^:]+)abc\/?$/i(added the missing colon)A route of
/:foo([^:]+)\::barshould additionally (on top of above expectations):barcontain the separating colon/abc:defshould result in{ foo: 'abc', bar: 'def' }and not{ 'foo:': 'abc', bar: ':def' }Actual behavior
Short version:
For example, the following route:
When provided a path such as:
... will result in the following parameters in
$route.params:Long version:
Any parameter that's followed immediately by
\:<something>(e.g./:foo([^:]+)\:abc) appears to be mis-parsed. Specifically, the\:appears to be gobbled up and thus ignored in the actual route.The example
/:foo([^:]+)\:abcresults in a regexp of/^\/([^:]+)abc\/?$/i— note the dropped colon.This has the following consequences:
:(cases/a/and/b/in repro link):in the trailing value is dropped, e.g./:foo([^:]+)\:abcmatchesxxxabcbut notxxx:abc(case/b/˙in repro)\:is itself a parameter, that parameter is value is prepended a:(this is a direct consequence of the incorrect regex) (case/a/in repro)Note that this only seems to happen with
:(or rather\:/'\\:'); symbols such as!or-appear to work fine (case/c/in repro).Additional information
Reproduced locally using vue-router@4.5.1 and online via the playground.
Workaround:
A workaround is to make a "dummy" parameter with
(:)as its regex, e.g.:With a path of
/xxx:abc, this will correctly match it to the route, and result in the expected$route.paramsof:{ foo: 'xxx', _: ':' }.