Created
July 13, 2018 05:37
-
-
Save nick-ChenZe/6167ec30cd709b16b37d1ccb20bc7ee7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs-extra') | |
const path = require('path') | |
const resolve = dir => path.resolve(__dirname, '..', 'src', dir) | |
const viewsDir = resolve('views') | |
const routeFile = resolve('routes/index.js') | |
// 移除JSON字符串中component的引号 | |
const excludeQuote = str => str.replace(/(\s*component":\s*)"([^""]+)"(.*)/g, '$1$2$3') | |
// 将对象字面量转为导出格式的JSON字符串 | |
const exportString = obj => `export default ${excludeQuote(JSON.stringify(obj, '', 2))}` | |
// 判断当前目录是否为components | |
const isComponents = dir => path.basename(dir) === 'components' | |
// 从对象数组中用某个键值对找到符合条件的唯一项 | |
const findChildByName = (parent, name, key = 'name') => parent.find(item => item[key] === name) | |
// 将:转为by格式,user/:id 转为 user/by/id | |
const parseQueryColon = dir => dir.replace(/\/(:)/g, '/by/') | |
// 将路径格式转为驼峰格式 /user/id 转为 UserId | |
const parsePath2CamelCase = dir => dir.replace(/(^|\/){1}([a-zA-Z:])/g, ($1, $2, $3) => $3.toUpperCase()) | |
// 将路径格式转为capital格式 /user/id 转为 userId | |
const parsePath2CapitalCase = dir => dir.replace(/(\/)([a-zA-Z])/g, ($1, $2, $3) => $3.toUpperCase()) | |
// 将字符串写入路由文件 | |
const writeFile = (content, callback) => fs.writeFile(routeFile, content, callback) | |
/** | |
* 展平所有文件结构 | |
* @param {String} dir 根路由 | |
* [ | |
* { | |
* name: capital格式文件名 | |
* path: 单级的路径 | |
* relpath: 完整的相对路径 | |
* component: 驼峰格式文件名 | |
* importPath: 完整的导入行字符串 | |
* } | |
* ] | |
*/ | |
let getAllFiles = dir => | |
fs.readdirSync(dir).reduce((files, file) => { | |
const name = path.join(dir, file) | |
const isDirectory = fs.statSync(name).isDirectory() | |
if (isDirectory && isComponents(name)) return [...files] | |
let relpath = path.relative(viewsDir, name) | |
let relpathWithoutExt = relpath.split('.')[0] | |
let component = parsePath2CamelCase(parseQueryColon(relpathWithoutExt)) | |
let componentName = parsePath2CapitalCase(parseQueryColon(relpathWithoutExt)) | |
let componentPath = `../views/${relpath}` | |
let fileInfo = { | |
name: componentName, | |
relpath, | |
component, | |
importPath: `const ${component} = resolve => require(['${componentPath}'], resolve)` | |
} | |
return isDirectory ? [...files, ...getAllFiles(name)] : [...files, fileInfo] | |
}, []) | |
/** | |
* 重新将文件格式转化为嵌套的路由格式,并写入路由文件 | |
* @param {Function} callback | |
*/ | |
function writeRoutes(callback) { | |
let lines = [] | |
let routeDefault = { path: '/', redirect: '/dashboard' } | |
let route404 = { path: '*', redirect: 'notFound' } | |
let routeConfig = [routeDefault, route404] | |
const lineBreak = '\n' | |
const emptyComponent = "{ render: h => h('router-view') }" | |
getAllFiles(viewsDir).forEach(item => { | |
let paths = item.relpath.split('/') | |
let length = paths.length | |
lines.push(item.importPath) | |
delete item.importPath | |
let collection = routeConfig | |
while (paths.length) { | |
let isEnd = paths.length === 1 | |
let isRoot = paths.length === length | |
let prefix = isRoot ? '/' : '' | |
let pathname = path.basename(paths.shift(), '.vue') | |
let found = findChildByName(collection, prefix + pathname, 'path') | |
let name = isEnd ? item.name : '' | |
let component = isEnd ? item.component : emptyComponent | |
let route | |
if (found) { | |
if (found.children.length) { | |
component = emptyComponent | |
name = '' | |
isEnd && found.children.push({ path: '/', component: item.component, name: item.name }) | |
} | |
route = Object.assign(found, { name, component, children: (collection = found.children) }) | |
} else collection.push((route = { name, path: prefix + pathname, component, children: (collection = []) })) | |
if (!route.name) delete route.name | |
if (!route.component) delete route.component | |
} | |
}) | |
lines.push(lineBreak) | |
fs.ensureFileSync(routeFile) | |
writeFile(lines.join(lineBreak) + exportString(routeConfig), callback) | |
} | |
module.exports = writeRoutes |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment