Skip to content

Commit

Permalink
feat: allow inserting raw routes in the editable tree node
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Apr 27, 2023
1 parent bc540bb commit c04d068
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 34 deletions.
93 changes: 93 additions & 0 deletions src/codegen/__snapshots__/generateRouteRecords.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,99 @@ exports[`generateRouteRecord > nested children 2`] = `
]"
`;

exports[`generateRouteRecord > raw paths insertions > do not nest raw segments with file based 1`] = `
"[
{
path: '/a',
/* internal name: '/a' */
/* no component */
children: [
{
path: 'b',
name: '/a/b',
component: () => import('a/b.vue'),
/* no children */
}
],
},
{
path: '/a/b/c',
name: '/a/b/c',
component: () => import('a.vue'),
/* no children */
}
]"
`;

exports[`generateRouteRecord > raw paths insertions > works with mixed nodes 1`] = `
"[
{
path: '/a',
name: '/a',
component: () => import('a.vue'),
/* no children */
},
{
path: '/b',
name: '/b',
component: () => import('b.vue'),
/* no children */
},
{
path: '/c',
name: '/c',
component: () => import('c.vue'),
/* no children */
}
]"
`;

exports[`generateRouteRecord > raw paths insertions > works with nested nodes 1`] = `
"[
{
path: '/a/b/c',
name: '/a/b/c',
component: () => import('a.vue'),
/* no children */
},
{
path: '/a/b/d',
name: '/a/b/d',
component: () => import('a.vue'),
/* no children */
},
{
path: '/a/d/c',
name: '/a/d/c',
component: () => import('a.vue'),
/* no children */
}
]"
`;

exports[`generateRouteRecord > raw paths insertions > works with raw paths 1`] = `
"[
{
path: '/a',
name: '/a',
component: () => import('a.vue'),
/* no children */
},
{
path: '/b',
name: '/b',
component: () => import('b.vue'),
/* no children */
},
{
path: '/c',
name: '/c',
component: () => import('c.vue'),
/* no children */
}
]"
`;

exports[`generateRouteRecord > removes trailing slashes 1`] = `
"[
{
Expand Down
34 changes: 34 additions & 0 deletions src/codegen/generateRouteRecords.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,38 @@ describe('generateRouteRecord', () => {
expect(generateRouteRecordSimple(tree)).toMatchSnapshot()
})
})

describe('raw paths insertions', () => {
it('works with raw paths', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
tree.insertParsedPath('a', 'a.vue')
tree.insertParsedPath('b', 'b.vue')
tree.insertParsedPath('c', 'c.vue')
expect(generateRouteRecordSimple(tree)).toMatchSnapshot()
})

it('works with mixed nodes', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
tree.insertParsedPath('a', 'a.vue')
tree.insert('b.vue')
tree.insertParsedPath('c', 'c.vue')
expect(generateRouteRecordSimple(tree)).toMatchSnapshot()
})

it('works with nested nodes', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
tree.insertParsedPath('a/b/c', 'a.vue')
tree.insertParsedPath('a/b/d', 'a.vue')
tree.insertParsedPath('a/d/c', 'a.vue')
expect(generateRouteRecordSimple(tree)).toMatchSnapshot()
})

it('do not nest raw segments with file based', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
tree.insert('a/b.vue')
// should be separated
tree.insertParsedPath('a/b/c', 'a.vue')
expect(generateRouteRecordSimple(tree)).toMatchSnapshot()
})
})
})
88 changes: 85 additions & 3 deletions src/core/extendRoutes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,76 @@ describe('EditableTreeNode', () => {
expect(tree.children.get('foo')?.path).toBe('/foo')
})

it('can insert nested nodes', () => {
it('keeps nested routes flat', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
const editable = new EditableTreeNode(tree)

editable.insert('foo/bar', 'file.vue')
expect(tree.children.size).toBe(1)
expect(tree.children.get('foo')?.children.size).toBe(1)
expect(tree.children.get('foo')?.children.get('bar')?.path).toBe('bar')
expect(tree.children.get('foo/bar')?.children.size).toBe(0)
expect(tree.children.get('foo/bar')?.fullPath).toBe('/foo/bar')
expect(tree.children.get('foo/bar')?.path).toBe('/foo/bar')
})

it('can have multiple params', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
const editable = new EditableTreeNode(tree)

editable.insert(':foo/:bar', 'file.vue')
expect(tree.children.size).toBe(1)
const node = tree.children.get(':foo/:bar')!
expect(node.fullPath).toBe('/:foo/:bar')
expect(node.path).toBe('/:foo/:bar')
expect(node.params).toEqual([
{
paramName: 'foo',
modifier: '',
optional: false,
repeatable: false,
isSplat: false,
},
{
paramName: 'bar',
modifier: '',
optional: false,
repeatable: false,
isSplat: false,
},
])
})

it('can have multiple params with modifiers', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
const editable = new EditableTreeNode(tree)

editable.insert(':foo/:bar+_:o(\\d+)', 'file.vue')
expect(tree.children.size).toBe(1)
const node = tree.children.get(':foo/:bar+_:o(\\d+)')!
expect(node.fullPath).toBe('/:foo/:bar+_:o(\\d+)')
expect(node.path).toBe('/:foo/:bar+_:o(\\d+)')
expect(node.params).toEqual([
{
paramName: 'foo',
modifier: '',
optional: false,
repeatable: false,
isSplat: false,
},
{
paramName: 'bar',
modifier: '+',
optional: false,
repeatable: true,
isSplat: false,
},
{
paramName: 'o',
modifier: '',
optional: false,
repeatable: false,
isSplat: false,
},
])
})

it('adds params', () => {
Expand Down Expand Up @@ -78,4 +140,24 @@ describe('EditableTreeNode', () => {
},
])
})

it('detects a splat', () => {
const tree = createPrefixTree(DEFAULT_OPTIONS)
const editable = new EditableTreeNode(tree)

editable.insert('/:path(.*)', 'file.vue')
expect(tree.children.size).toBe(1)
const child = tree.children.get(':path(.*)')!
expect(child.fullPath).toBe('/:path(.*)')
expect(child.path).toBe('/:path(.*)')
expect(child.params).toEqual([
{
paramName: 'path',
modifier: '',
optional: false,
repeatable: false,
isSplat: true,
},
])
})
})
47 changes: 17 additions & 30 deletions src/core/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,42 +84,29 @@ export class TreeNode {
* @param filePath - file path, defaults to path for convenience and testing
*/
insertParsedPath(path: string, filePath: string = path): TreeNode {
const slashPos = path.indexOf('/')
const segment = slashPos < 0 ? path : path.slice(0, slashPos)
const tail = slashPos < 0 ? '' : path.slice(slashPos + 1)

// TODO: allow null filePath?
const isComponent = !tail

if (!this.children.has(segment)) {
this.children.set(
segment,
new TreeNode(
{
...this.options,
// force the format to raw
treeNodeOptions: {
...this.options.pathParser,
format: 'path',
},
},
segment,
this
)
)
}
const child = this.children.get(segment)!
const isComponent = true

const node = new TreeNode(
{
...this.options,
// force the format to raw
treeNodeOptions: {
...this.options.pathParser,
format: 'path',
},
},
path,
this
)
this.children.set(path, node)

if (isComponent) {
// TODO: allow a way to set the view name
child.value.components.set('default', filePath)
}

if (tail) {
return child.insertParsedPath(tail, filePath)
node.value.components.set('default', filePath)
}

return child
return node
}

setCustomRouteBlock(path: string, routeBlock: CustomRouteBlock | undefined) {
Expand Down
12 changes: 11 additions & 1 deletion src/core/treeNodeValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,13 @@ function parseRawPathSegment(
for (pos = 0; pos < segment.length; pos++) {
c = segment[pos]

if (c === '\\') {
// skip the next char
pos++
buffer += segment[pos]
continue
}

if (state === ParseRawPathSegmentState.static) {
if (c === ':') {
consumeBuffer()
Expand Down Expand Up @@ -452,7 +459,10 @@ function parseRawPathSegment(
if (c === ')') {
// we don't actually care about the regexp as it already on the segment
// currentTreeRouteParam.regexp = buffer
buffer = ''
if (buffer === '.*') {
currentTreeRouteParam.isSplat = true
}
// we don't reset the buffer but it needs to be consumed
// check if there is a modifier
state = ParseRawPathSegmentState.modifier
} else {
Expand Down

0 comments on commit c04d068

Please sign in to comment.