Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@
<li>
<router-link to="/p_1/absolute-a">/p_1/absolute-a</router-link>
</li>
<li>
<router-link to="/entity/section:aaabbbccc"
>/entity/section:aaabbbccc</router-link
>
</li>
<li>
<router-link to="/entity/sectionaaabbbccc"
>/entity/sectionaaabbbccc</router-link
>
</li>
</ul>
<button @click="toggleViewName">Toggle view</button>
<RouterView :name="viewName" v-slot="{ Component, route }">
Expand Down
5 changes: 5 additions & 0 deletions packages/playground/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ export const router = createRouter({
},
{ path: '/with-data', component: ComponentWithData, name: 'WithData' },
{ path: '/rep/:a*', component: RepeatedParams, name: 'repeat' },
{
path: '/entity/:entityType([^:]+)\\::entityID',
name: 'entity',
component,
},
{ path: '/:data(.*)', component: NotFound, name: 'NotFound' },
{
path: '/nested',
Expand Down
79 changes: 79 additions & 0 deletions packages/router/__tests__/matcher/pathParser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,58 @@ describe('Path parser', () => {
])
})

it('escapes : after param', () => {
expect(tokenizePath('/:foo\\:abc')).toEqual([
[
{
type: TokenType.Param,
value: 'foo',
regexp: '',
repeatable: false,
optional: false,
},
{ type: TokenType.Static, value: ':abc' },
],
])
})

it('escapes : after param with custom re', () => {
expect(tokenizePath('/:foo([^:]+)\\:abc')).toEqual([
[
{
type: TokenType.Param,
value: 'foo',
regexp: '[^:]+',
repeatable: false,
optional: false,
},
{ type: TokenType.Static, value: ':abc' },
],
])
})

it('escapes : between two params', () => {
expect(tokenizePath('/:foo([^:]+)\\::bar')).toEqual([
[
{
type: TokenType.Param,
value: 'foo',
regexp: '[^:]+',
repeatable: false,
optional: false,
},
{ type: TokenType.Static, value: ':' },
{
type: TokenType.Param,
value: 'bar',
regexp: '',
repeatable: false,
optional: false,
},
],
])
})

// not sure how useful this is and if it's worth supporting because of the
// cost to support the ranking as well
it.skip('groups', () => {
Expand Down Expand Up @@ -808,6 +860,33 @@ describe('Path parser', () => {
})
})

it('param followed by escaped colon and static', () => {
matchParams('/:foo\\:abc', '/section:abc', { foo: 'section' })
matchParams('/:foo\\:abc', '/sectionabc', null)
})

it('optional param followed by escaped colon and static', () => {
matchParams('/:foo?\\:abc', '/:abc', { foo: '' })
matchParams('/:foo?\\:abc', '/section:abc', { foo: 'section' })
})

it('repeatable param followed by escaped colon and static', () => {
matchParams('/:foo+\\:abc', '/section:abc', { foo: ['section'] })
matchParams('/:foo+\\:abc', '/a/b:abc', { foo: ['a', 'b'] })
})

it('param with custom re followed by escaped colon and static', () => {
matchParams('/:foo([^:]+)\\:abc', '/section:abc', { foo: 'section' })
matchParams('/:foo([^:]+)\\:abc', '/sectionabc', null)
})

it('param with custom re followed by escaped colon and another param', () => {
matchParams('/:foo([^:]+)\\::bar', '/section:aaabbbccc', {
foo: 'section',
bar: 'aaabbbccc',
})
})

// end of parsing urls
})

Expand Down
8 changes: 8 additions & 0 deletions packages/router/src/matcher/pathTokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ export function tokenizePath(path: string): Array<Token[]> {
char = path[i++]

if (char === '\\' && state !== TokenizerState.ParamRegExp) {
if (
state === TokenizerState.Param ||
state === TokenizerState.ParamRegExpEnd
) {
consumeBuffer()
customRe = ''
state = TokenizerState.Static
}
previousState = state
state = TokenizerState.EscapeNext
continue
Expand Down
Loading