├── tests ├── scenarios │ ├── single-file │ │ └── home.vue │ ├── with-an-index │ │ ├── about.vue │ │ └── index.vue │ ├── with-everything │ │ ├── about.vue │ │ ├── contact.vue │ │ ├── index.vue │ │ ├── _product.vue │ │ ├── _product │ │ │ ├── buy.vue │ │ │ ├── index.vue │ │ │ └── sell.vue │ │ └── contact │ │ │ ├── help.vue │ │ │ └── feedback.vue │ ├── with-some-params │ │ ├── about.vue │ │ ├── team │ │ │ ├── _name.vue │ │ │ └── join.vue │ │ └── _product │ │ │ ├── buy.vue │ │ │ └── sell.vue │ ├── with-a-little-nesting │ │ ├── index.vue │ │ ├── contact.vue │ │ └── level1 │ │ │ ├── team.vue │ │ │ ├── about.vue │ │ │ └── level2 │ │ │ ├── deep.vue │ │ │ └── index.vue │ ├── single-level-multiple-files │ │ ├── about.vue │ │ ├── home.vue │ │ ├── -ignored.vue │ │ └── ignored.js │ └── with-some-child-components │ │ ├── about.vue │ │ ├── contact.vue │ │ └── contact │ │ ├── feedback.vue │ │ ├── help.vue │ │ └── index.vue └── directory-parser.spec.js ├── .gitignore ├── example ├── pages │ ├── contact.vue │ ├── services │ │ ├── index.vue │ │ ├── cooking.vue │ │ └── laundry.vue │ ├── team │ │ ├── index.vue │ │ └── _name.vue │ ├── _product │ │ ├── buy.vue │ │ └── sell.vue │ ├── about.vue │ └── services.vue ├── main.js ├── router.js └── App.vue ├── public └── favicon.ico ├── .prettierrc ├── vite.config.js ├── index.html ├── .eslintrc.js ├── vite-auto-route.code-workspace ├── LICENSE ├── package.json ├── src ├── plugin.js └── directory-parser.js └── README.md /tests/scenarios/single-file/home.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-an-index/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-an-index/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/contact.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-params/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/_product.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/_product/buy.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/contact/help.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-params/team/_name.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-params/team/join.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/single-level-multiple-files/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/single-level-multiple-files/home.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/contact.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/level1/team.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/_product/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/_product/sell.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-everything/contact/feedback.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-child-components/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-params/_product/buy.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-params/_product/sell.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.local -------------------------------------------------------------------------------- /tests/scenarios/single-level-multiple-files/-ignored.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/single-level-multiple-files/ignored.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/level1/about.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-child-components/contact.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/level1/level2/deep.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-a-little-nesting/level1/level2/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-child-components/contact/feedback.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-child-components/contact/help.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/scenarios/with-some-child-components/contact/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/pages/contact.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/services/index.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/team/index.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/services/cooking.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/services/laundry.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chs-uk/vite-plugin-auto-routes/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /example/pages/_product/buy.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/_product/sell.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /example/pages/team/_name.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "arrowParens": "always", 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "printWidth": 100 7 | } 8 | -------------------------------------------------------------------------------- /example/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | createApp(App).use(router).mount('#app') 6 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | const viteAutoRoute = require('./src/plugin.js') 2 | 3 | module.exports = { 4 | plugins: [viteAutoRoute({ pagesDir: './example/pages' })], 5 | } 6 | -------------------------------------------------------------------------------- /example/router.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHashHistory } from 'vue-router' 2 | import { routes } from 'vue-auto-routes' 3 | 4 | const router = createRouter({ 5 | history: createWebHashHistory(), 6 | routes, 7 | }) 8 | 9 | export default router 10 | -------------------------------------------------------------------------------- /example/pages/about.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 10 | { 11 | "meta": { 12 | "requiresLogin": true, 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /example/pages/services.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | parserOptions: { 8 | parser: 'babel-eslint', 9 | }, 10 | extends: ['prettier', 'prettier/vue', 'plugin:prettier/recommended'], 11 | plugins: ['prettier'], 12 | rules: { 13 | 'comma-dangle': ['error', 'always-multiline'], 14 | 15 | 'vue/max-attributes-per-line': [ 16 | 2, 17 | { 18 | singleline: 20, 19 | multiline: { 20 | max: 1, 21 | allowFirstLine: false, 22 | }, 23 | }, 24 | ], 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /example/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /vite-auto-route.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | // Newlines/spaces 9 | "files.insertFinalNewline": true, 10 | "files.trimFinalNewlines": true, 11 | "files.trimTrailingWhitespace": true, 12 | 13 | // Files to exclude from file explorer 14 | "files.exclude": { 15 | "**/node_modules/": true 16 | }, 17 | 18 | // Files to exclude from git watching 19 | "files.watcherExclude": { 20 | "**/.git/objects/**": true, 21 | "**/.git/subtree-cache/**": true, 22 | "**/node_modules/*/**": true 23 | }, 24 | 25 | // Editor appearance 26 | "editor.rulers": [100], 27 | 28 | // General formatting rules 29 | "editor.formatOnSave": true, 30 | 31 | // Frontend formatting 32 | "vetur.format.enable": false, 33 | "vetur.grammar.customBlocks": { 34 | "route": "json" 35 | }, 36 | "prettier.disableLanguages": [] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 katashin 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-auto-routes", 3 | "description": "Vite plugin to automatically generate routes from a file structure", 4 | "version": "0.1.1", 5 | "license": "MIT", 6 | "main": "src/plugin.js", 7 | "files": [ 8 | "src" 9 | ], 10 | "keywords": [ 11 | "Vue", 12 | "Vue 3", 13 | "vite", 14 | "plugin", 15 | "routing", 16 | "auto routing" 17 | ], 18 | "author": "axwalker", 19 | "bugs": { 20 | "url": "https://github.com/ImpactBox/vite-plugin-auto-routes/issues" 21 | }, 22 | "homepage": "https://github.com/ImpactBox/vite-plugin-auto-routes", 23 | "scripts": { 24 | "dev": "vite", 25 | "build": "vite build", 26 | "test": "jest" 27 | }, 28 | "dependencies": { 29 | "common-tags": "^1.8.0", 30 | "vue": "^3.0.0-rc.1", 31 | "vue-router": "4.0.0-beta.3" 32 | }, 33 | "devDependencies": { 34 | "@rollup/plugin-virtual": "^2.0.3", 35 | "@vue/compiler-sfc": "^3.0.0-rc.1", 36 | "jest": "^26.1.0", 37 | "rollup": "^2.23.0", 38 | "vite": "^1.0.0-rc.1" 39 | }, 40 | "peerDependencies": { 41 | "vue": "^3.0.0-rc.1", 42 | "vue-router": "4.0.0-beta.3" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/plugin.js: -------------------------------------------------------------------------------- 1 | const virtual = require('@rollup/plugin-virtual') 2 | const { parsePagesDirectory } = require('./directory-parser') 3 | 4 | function makeModuleContent({ pagesDir }) { 5 | const { routes } = parsePagesDirectory(pagesDir) 6 | return `export const routes = [${routes.join(', \n')}]` 7 | } 8 | 9 | module.exports = function ({ pagesDir } = { pagesDir: 'src/pages/' }) { 10 | const configureServer = [ 11 | async ({ app }) => { 12 | app.use(async (ctx, next) => { 13 | if (ctx.path.startsWith('/@modules/vue-auto-routes')) { 14 | ctx.type = 'js' 15 | ctx.body = makeModuleContent({ pagesDir }) 16 | } else { 17 | await next() 18 | } 19 | }) 20 | }, 21 | ] 22 | 23 | const rollupInputOptions = { 24 | plugins: [virtual({ 'vue-auto-routes': makeModuleContent({ pagesDir }) })], 25 | } 26 | 27 | /* Note: these route options are not yet used anywhere */ 28 | const vueCustomBlockTransforms = { 29 | route: ({ code }) => { 30 | return ` 31 | export default function (Component) { 32 | Component.__routeOptions = ${code} 33 | } 34 | ` 35 | }, 36 | } 37 | 38 | return { configureServer, rollupInputOptions, vueCustomBlockTransforms } 39 | } 40 | -------------------------------------------------------------------------------- /src/directory-parser.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | 4 | function parsePagesDirectory( 5 | dir, 6 | { prependName, prependPath } = { prependName: '', prependPath: '/' }, 7 | ) { 8 | let routes = [] 9 | 10 | const siblings = fs.readdirSync(dir, { withFileTypes: true }) 11 | 12 | const files = siblings 13 | .filter((f) => f.isFile() && f.name.endsWith('.vue') && !f.name.startsWith('-')) 14 | .map((f) => f.name) 15 | 16 | const directories = siblings.filter((f) => f.isDirectory()).map((d) => d.name) 17 | 18 | for (const name of files) { 19 | const f = { name: name.split('.')[0], importPath: path.join(dir, name) } 20 | 21 | const routeOptions = [] 22 | // Route name 23 | if (!directories.includes(f.name) || !fs.existsSync(path.join(dir, f.name, 'index.vue'))) { 24 | const routeName = 25 | f.name === 'index' && prependName 26 | ? prependName.slice(0, -1) 27 | : prependName + f.name.replace(/^_/, '') 28 | routeOptions.push(`name: '${routeName}'`) 29 | } 30 | // Route path 31 | routeOptions.push( 32 | `path: '${prependPath}${f.name === 'index' ? '' : f.name.replace(/^_/, ':')}'`, 33 | ) 34 | // Route component 35 | routeOptions.push(`component: () => import('/${f.importPath}')`) 36 | // Route children 37 | if (directories.includes(f.name)) { 38 | children = parsePagesDirectory(path.join(dir, f.name), { 39 | prependName: `${prependName}${f.name.replace(/^_/, '')}-`, 40 | prependPath: '', 41 | }).routes 42 | routeOptions.push(`children: [ ${children.join(', ')} ]`) 43 | } 44 | routes.push(`{ ${routeOptions.join(', ')} }`) 45 | } 46 | 47 | // If a directory exists with the same name as a sibling file, it means the folder acts as 48 | // children routes. Those children are dealt with above, so we filter them out here. 49 | const filesWithoutExtension = files.map((f) => f.slice(0, -4)) 50 | const remainingDirectories = directories.filter((d) => !filesWithoutExtension.includes(d)) 51 | for (const name of remainingDirectories) { 52 | const parsedDir = parsePagesDirectory(path.join(dir, name), { 53 | prependName: `${prependName}${name.replace(/^_/, '')}-`, 54 | prependPath: `${prependPath}${name.replace(/^_/, ':')}/`, 55 | }) 56 | routes = routes.concat(parsedDir.routes) 57 | } 58 | 59 | return { routes } 60 | } 61 | 62 | module.exports = { 63 | parsePagesDirectory, 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-plugin-auto-routes 2 | 3 | A vite plugin for automatic routing in Vue 3 based on your file structure. 4 | 5 | # Why? 6 | 7 | You want automatic routing from a file structure, as you'd get in [Nuxt](https://nuxtjs.org/guide/routing/). Specifically, you want to turn this file tree: 8 | 9 | ``` 10 | pages/ 11 | --| user/ 12 | -----| index.vue 13 | -----| one.vue 14 | --| index.vue 15 | ``` 16 | 17 | into this: 18 | 19 | ```js 20 | router: { 21 | routes: [ 22 | { 23 | name: 'index', 24 | path: '/', 25 | component: 'pages/index.vue', 26 | }, 27 | { 28 | name: 'user', 29 | path: '/user', 30 | component: 'pages/user/index.vue', 31 | }, 32 | { 33 | name: 'user-one', 34 | path: '/user/one', 35 | component: 'pages/user/one.vue', 36 | }, 37 | ] 38 | } 39 | ``` 40 | 41 | Paramaters and child components are supported in the same way as Nuxt. See the [example](example/) for a more complete example pages directory. 42 | 43 | There already exists a Vue 2 + [vue-cli plugin](https://github.com/ktsn/vue-cli-plugin-auto-routing) for this, but not for Vue 3 + vite. 44 | 45 | # Usage 46 | 47 | ## Installation 48 | 49 | With npm: 50 | 51 | ``` 52 | npm i --save-dev vite-plugin-auto-routes 53 | ``` 54 | 55 | With yarn: 56 | 57 | ``` 58 | yarn add -D vite-plugin-auto-routes 59 | ``` 60 | 61 | Then in your `vite.config.js` file add: 62 | 63 | ```js 64 | const viteAutoRoute = require('vite-plugin-auto-routes') 65 | 66 | module.exports = { 67 | plugins: [viteAutoRoute({ pagesDir: 'src/pages' })], 68 | } 69 | ``` 70 | 71 | Routes will now be available by importing `vue-auto-routes` in your app. You can then set up your router as you normally would, for example (using vue-router-next for Vue 3): 72 | 73 | ```js 74 | import { createApp } from 'vue' 75 | import { createRouter, createWebHashHistory } from 'vue-router' 76 | import { routes } from 'vue-auto-routes' 77 | import App from './App.vue' 78 | 79 | const router = createRouter({ 80 | history: createWebHashHistory(), 81 | routes, 82 | }) 83 | createApp(App).use(router).mount('#app') 84 | ``` 85 | 86 | # Limitations 87 | 88 | ## Hot module reloading 89 | 90 | If you create new pages that will generate new routes, they currently will not be available until you refresh the page. Editing existing pages will hot reload as normal. 91 | 92 | # To do 93 | 94 | - [x] Support single flat directory 95 | - [x] Support child components through nested directories 96 | - [x] Support route parameters 97 | - [x] Custom pages directory 98 | - [ ] Custom route block 99 | 100 | # Inspirations 101 | 102 | - [Nuxt routing](https://nuxtjs.org/guide/routing/) 103 | - [vue-cli-plugin-auto-routing](https://github.com/ktsn/vue-cli-plugin-auto-routing) 104 | -------------------------------------------------------------------------------- /tests/directory-parser.spec.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { oneLine } = require('common-tags') 3 | const { parsePagesDirectory } = require('../src/directory-parser') 4 | 5 | test('empty directory', () => { 6 | const { routes } = parsePagesDirectory('tests/scenarios/empty') 7 | expect(routes).toEqual([]) 8 | }) 9 | 10 | test('directory with a single file', () => { 11 | const dir = 'tests/scenarios/single-file' 12 | const { routes } = parsePagesDirectory(dir) 13 | expect(routes).toEqual([ 14 | `{ name: 'home', path: '/home', component: () => import('/${dir}/home.vue') }`, 15 | ]) 16 | }) 17 | 18 | test('directory with multiple files', () => { 19 | const dir = 'tests/scenarios/single-level-multiple-files' 20 | const { routes } = parsePagesDirectory(dir) 21 | 22 | expect(routes).toEqual([ 23 | `{ name: 'about', path: '/about', component: () => import('/${dir}/about.vue') }`, 24 | `{ name: 'home', path: '/home', component: () => import('/${dir}/home.vue') }`, 25 | ]) 26 | }) 27 | 28 | test('directory with an index file', () => { 29 | const dir = 'tests/scenarios/with-an-index' 30 | const { routes } = parsePagesDirectory(dir) 31 | 32 | expect(routes).toEqual([ 33 | `{ name: 'about', path: '/about', component: () => import('/${dir}/about.vue') }`, 34 | `{ name: 'index', path: '/', component: () => import('/${dir}/index.vue') }`, 35 | ]) 36 | }) 37 | 38 | test('directory with a little nesting', () => { 39 | const dir = 'tests/scenarios/with-a-little-nesting' 40 | const { routes } = parsePagesDirectory(dir) 41 | 42 | expect(routes).toEqual([ 43 | `{ name: 'contact', path: '/contact', component: () => import('/${dir}/contact.vue') }`, 44 | `{ name: 'index', path: '/', component: () => import('/${dir}/index.vue') }`, 45 | `{ name: 'level1-about', path: '/level1/about', component: () => import('/${dir}/level1/about.vue') }`, 46 | `{ name: 'level1-team', path: '/level1/team', component: () => import('/${dir}/level1/team.vue') }`, 47 | `{ name: 'level1-level2-deep', path: '/level1/level2/deep', component: () => import('/${dir}/level1/level2/deep.vue') }`, 48 | `{ name: 'level1-level2', path: '/level1/level2/', component: () => import('/${dir}/level1/level2/index.vue') }`, 49 | ]) 50 | }) 51 | 52 | test('directory with child components', () => { 53 | const dir = 'tests/scenarios/with-some-child-components' 54 | const { routes } = parsePagesDirectory(dir) 55 | 56 | expect(routes).toEqual([ 57 | `{ name: 'about', path: '/about', component: () => import('/${dir}/about.vue') }`, 58 | oneLine`{ 59 | path: '/contact', 60 | component: () => import('/${dir}/contact.vue'), 61 | children: [ 62 | { name: 'contact-feedback', path: 'feedback', component: () => import('/${dir}/contact/feedback.vue') }, 63 | { name: 'contact-help', path: 'help', component: () => import('/${dir}/contact/help.vue') }, 64 | { name: 'contact', path: '', component: () => import('/${dir}/contact/index.vue') } 65 | ] 66 | }`, 67 | ]) 68 | }) 69 | 70 | test('directory with some params', () => { 71 | const dir = 'tests/scenarios/with-some-params' 72 | const { routes } = parsePagesDirectory(dir) 73 | 74 | expect(routes).toEqual([ 75 | `{ name: 'about', path: '/about', component: () => import('/${dir}/about.vue') }`, 76 | `{ name: 'product-buy', path: '/:product/buy', component: () => import('/${dir}/_product/buy.vue') }`, 77 | `{ name: 'product-sell', path: '/:product/sell', component: () => import('/${dir}/_product/sell.vue') }`, 78 | `{ name: 'team-name', path: '/team/:name', component: () => import('/${dir}/team/_name.vue') }`, 79 | `{ name: 'team-join', path: '/team/join', component: () => import('/${dir}/team/join.vue') }`, 80 | ]) 81 | }) 82 | 83 | test('directory with everything', () => { 84 | const dir = 'tests/scenarios/with-everything' 85 | const { routes } = parsePagesDirectory(dir) 86 | 87 | expect(routes).toEqual([ 88 | oneLine`{ 89 | path: '/:product', 90 | component: () => import('/${dir}/_product.vue'), 91 | children: [ 92 | { name: 'product-buy', path: 'buy', component: () => import('/${dir}/_product/buy.vue') }, 93 | { name: 'product', path: '', component: () => import('/${dir}/_product/index.vue') }, 94 | { name: 'product-sell', path: 'sell', component: () => import('/${dir}/_product/sell.vue') } 95 | ] 96 | }`, 97 | `{ name: 'about', path: '/about', component: () => import('/${dir}/about.vue') }`, 98 | oneLine`{ 99 | name: 'contact', 100 | path: '/contact', 101 | component: () => import('/${dir}/contact.vue'), 102 | children: [ 103 | { name: 'contact-feedback', path: 'feedback', component: () => import('/${dir}/contact/feedback.vue') }, 104 | { name: 'contact-help', path: 'help', component: () => import('/${dir}/contact/help.vue') } 105 | ] 106 | }`, 107 | `{ name: 'index', path: '/', component: () => import('/${dir}/index.vue') }`, 108 | ]) 109 | }) 110 | --------------------------------------------------------------------------------