Yargs官方地址vue
存在三个参数
file: 文件夹以及模块名(必填)
path: 文件存放路径
type: 模板类型
command(cmd, desc, [builder], [handler])
用command方法建立了一个命令,将先前定义的参数放到command的bulider里面。
[handler]处理传参。
1.建立文件夹
2.建立文件
可以建立文件是不够的,咱们须要文件内容是咱们定义好的模板内容,因此咱们先定义好模板。
ReactTemplat、VueTemplate: 是自定义模板,能够根据本身的模板内容、结构来自定义。node
cli.js: 用来建立命令,而且将参数传给start文件处理。react
start.js: 用来处理参数,建立文件夹及文件,利用process进程与用户进行交互。git
handle.js: 处理文件的方法。github
node ./tools/cli add -h // 显示帮助信息
Options:
--version Show version number [boolean]
-h Show help [boolean]
--file, -f create a file [required]
--path, -p file path [default: ""]
--type, -t file‘s type [choices: "vue", "react"] [default: "vue"]
Examples:
node tools/cli add -p views -f test -t vue 在views目录下建立一个test模板
复制代码
node tools/cli add -f test -p views -t vue
复制代码
在views目录下建立一个test模块,模块类型是vue。
新建模块时会先判断存放路径是否存在该文件夹。bash
遇到重复的模块可选是否须要覆盖async
文件地址ide
const argv = require('yargs')
.command(
'add',
'create a file',
function(yargs) {
return yargs
.option('file', {
alias: 'f',
describe: 'create a file'
})
.option('path', {
alias: 'p',
describe: 'file path',
default: ''
})
.option('type', {
alias: 't',
describe: 'file‘s type',
choices: ['vue', 'react'], // 如今有两个模板供选择,能够根据本身的项目状况设计模板
default: 'vue'
})
.demandOption(['file'], 'Please provide file to work with this tool')
.example(
'node tools/cli add -p views -f test -t vue',
'在views目录下建立一个test模板'
)
},
function(argv) {
// 根据参数,建立模板
start(argv)
}
)
.help('h').argv
复制代码
const handel = require('./handle')
const colors = require('colors')
const path = require('path')
module.exports = async function(argv) {
argv.file = argv.file.toString()
const existPathFolder = await handel.existFolder(path.resolve(argv.path))
const fileName =
argv.file.substring(0, 1).toUpperCase() + argv.file.substring(1)
let className = ''
for (let i = 0; i < argv.file.length; i++) {
if (/[A-Z]/.test(argv.file[i])) {
className += '-'
}
className += argv.file[i].toLowerCase()
}
if (argv.path !== '') {
argv.path += '/'
}
const filePath = path.resolve(argv.path) + '/' + fileName
process.stdin.setEncoding('utf8')
const createFileData = {
filePath,
fileName,
className,
type: argv.type
}
// 不存在path的文件夹
if (!existPathFolder) {
console.warn(
colors.green(`是否建立 ${path.resolve(argv.path)} 文件夹?:y/n`)
)
process.stdin.on('data', async chunk => {
chunk = chunk.replace(/[\s\n]/, '')
if (chunk === 'y') {
// 建立path文件夹
await handel.createFolder(path.resolve(argv.path))
// 建立组件文件夹
await handel.createFolder(filePath)
// 建立文件
await handel.createFile(createFileData)
process.exit()
} else if (chunk === 'n') {
process.exit()
} else {
console.warn(colors.red('请输入正确指令:y/n'))
process.exit()
}
})
} else {
// 判断组件文件夹是否存在
const existFileFolder = await handel.existFolder(filePath)
if (existFileFolder) {
console.warn(colors.green(`${fileName}文件夹已存在,是否覆盖?:y/n`))
process.stdin.on('data', async chunk => {
chunk = chunk.replace(/[\s\n]/, '')
if (chunk === 'y') {
// 建立组件文件夹
await handel.createFolder(filePath)
// 建立文件
await handel.createFile(createFileData)
process.exit()
} else if (chunk === 'n') {
process.exit()
} else {
console.warn(colors.red('请输入正确指令:y/n'))
process.exit()
}
})
} else {
// 建立组件文件夹
await handel.createFolder(filePath)
// 建立文件
await handel.createFile(createFileData)
process.exit()
}
}
}
复制代码
const fs = require('fs')
const colors = require('colors')
const path = require('path')
module.exports = {
existFolder: async function(path) {
// 判断是否存在argv.path的文件夹
return new Promise(function(resolve, reject) {
return fs.exists(path, e => {
resolve(e)
})
})
},
/**
*建立文件夹
@param filePath 文件路径
*/
createFolder: function(filePath) {
return new Promise(function(resolve, reject) {
fs.mkdir(filePath, function(err) {
if (err) {
if (err.errno === -2) {
console.log(colors.red('找不到目录'))
} else if (err.errno === -17) {
}
} else {
console.log(colors.green('建立文件夹: '))
console.log(colors.underline(`${filePath}`))
}
resolve()
})
})
},
/**
* @param args:{
* filePath 文件路径
* fileName 文件名
* className 样式名
* type 文件类型
* }
*/
createFile: function({ filePath, fileName, className, type }) {
const data = {
fileName,
filePath,
className
}
// 模板路径
switch (type) {
case 'vue':
data.templateFolderPath = path.join(__dirname, './VueTemplate')
break
case 'react':
data.templateFolderPath = path.join(__dirname, './VueTemplate')
break
default:
data.templateFolderPath = path.join(__dirname, './VueTemplate')
}
return new Promise(async (resolve, reject) => {
await this.readAndWiteFile(data, resolve)
})
},
/**
* 读取模板内容而且写到新建文件里面
* @param args:{
* templateFolderPath 模板路径
* fileName 文件名
* filePath 文件路径
* className 样式名字
* }
* @param resolve
*/
readAndWiteFile: function(
{ templateFolderPath, fileName, filePath, className },
resolve
) {
fs.readdir(templateFolderPath, 'utf8', (err, files) => {
if (err) {
console.log(colors.red(err))
return false
}
files.forEach(templateName => {
const FileName = templateName
.replace('TemplateName', fileName)
.replace('.txt', '')
// 1.建立文件
fs.createWriteStream(`${filePath}/${FileName}`)
// 2.读取、写入模板内容
const content = fs
.readFileSync(`${templateFolderPath}/${templateName}`)
.toString() // 读取模板文件
.replace(/\${TemplateName}/g, FileName.split('.')[0])
.replace(/\${template-name}/g, className) // 替换模板内容
// 将templateName替换成对应的文件名
fs.writeFileSync(`${filePath}/${FileName}`, content, 'utf8')
console.log(colors.green('写入文件: '))
console.log(colors.underline(`${filePath}/${FileName}`))
})
resolve()
})
}
}
复制代码
这种方法比较繁琐,下面优化了两个版本工具
(1)命令: node tools2/cli add -f fileName学习
(2)提示选择模板
(3)选择放置位置,提供进入下一层,返回上一层操做
针对上面一旦出现深层路径的话,操做会很繁琐,因此提供动态选择路径,根据关键字提示路径地址。
步骤
(1)命令: node tools3/cli
(2)填写文件名
(3)提示选择模板
(4)提示放置地址