1 | #!/usr/bin/env node
|
2 |
|
3 | const download = require('download-git-repo') // //用于下载远程仓库至本地 支持GitHub、GitLab、Bitbucket
|
4 | const program = require('commander') //命令行处理工具
|
5 | const exists = require('fs').existsSync //node自带的fs模块下的existsSync方法,用于检测路径是否存在。(会阻塞)
|
6 | const path = require('path') //node自带的path模块,用于拼接路径
|
7 | const ora = require('ora') //用于命令行上的加载效果
|
8 | const home = require('user-home') //用于获取用户的根目录
|
9 | const tildify = require('tildify') //将绝对路径转换成带波浪符的路径
|
10 | const chalk = require('chalk') // 用于高亮终端打印出的信息
|
11 | const inquirer = require('inquirer') //用于命令行与开发者交互
|
12 | const rm = require('rimraf').sync // 相当于UNIX的“rm -rf”命令
|
13 | const logger = require('../lib/logger') //自定义工具-用于日志打印
|
14 | const generate = require('../lib/generate') //自定义工具-用于基于模板构建项目
|
15 | const checkVersion = require('../lib/check-version') //自定义工具-用于检测vue-cli版本的工具
|
16 | const warnings = require('../lib/warnings') //自定义工具-用于模板的警告
|
17 | const localPath = require('../lib/local-path') //自定义工具-用于路径的处理
|
18 |
|
19 | const isLocalPath = localPath.isLocalPath //判断是否是本地路径
|
20 | const getTemplatePath = localPath.getTemplatePath //获取本地模板的绝对路径
|
21 |
|
22 | /**
|
23 | * Usage.
|
24 | */
|
25 | /**
|
26 | * 配置commander的使用方法
|
27 | */
|
28 | program
|
29 | .usage('<template-name> [project-name]')
|
30 | .option('-c, --clone', 'use git clone')
|
31 | .option('--offline', 'use cached template')
|
32 |
|
33 | /**
|
34 | * Help.
|
35 | */
|
36 | /**
|
37 | * 定义commander的help方法
|
38 | */
|
39 | program.on('--help', () => {
|
40 | console.log(' Examples:')
|
41 | console.log(chalk.gray(' # create a new project with an official template'))
|
42 | console.log(' $ angular init webpack my-project')
|
43 | console.log(chalk.gray(' # create a new project straight from a github template'))
|
44 | console.log(' $ angular init username/repo my-project')
|
45 | })
|
46 |
|
47 | /**
|
48 | * Help.
|
49 | */
|
50 |
|
51 | function help () {
|
52 | program.parse(process.argv)
|
53 | if (program.args.length < 1) return program.help()
|
54 | }
|
55 | help()
|
56 |
|
57 | /**
|
58 | * Settings.
|
59 | */
|
60 | /**
|
61 | * 定义一大堆变量
|
62 | */
|
63 | let template = program.args[0] //模板名称
|
64 | const hasSlash = template.indexOf('/') > -1 //是否有斜杠,后面将会用来判定是否为官方模板
|
65 | const rawName = program.args[1] //项目构建目录名
|
66 | const inPlace = !rawName || rawName === '.' // 没写或者“.”,表示当前目录下构建项目
|
67 | const name = inPlace ? path.relative('../', process.cwd()) : rawName //如果在当前目录下构建项目,当前目录名为项目构建目录名,否则是当前目录下的子目录【rawName】为项目构建目录名
|
68 | const to = path.resolve(rawName || '.') //项目构建目录的绝对路径
|
69 | const clone = program.clone || false //是否采用clone模式,提供给“download-git-repo”的参数
|
70 | const tmp = path.join(home, 'angular1-templates', template.replace(/[\/:]/g, '-')) //远程模板下载到本地的路径
|
71 | if (program.offline) {
|
72 | console.log(`> Use cached template at ${chalk.yellow(tildify(tmp))}`)
|
73 | template = tmp
|
74 | }
|
75 |
|
76 | /**
|
77 | * Padding.
|
78 | */
|
79 |
|
80 | process.on('exit', () => {
|
81 | })
|
82 | /**
|
83 | * 判断是否输入项目名 是 - 直接执行run函数 否- 询问开发者是否在当前目录下生成项目,开发者回答“是” 也执行run函数 否则不执行run函数
|
84 | */
|
85 |
|
86 | /**
|
87 | * 定义主函数 run
|
88 | */
|
89 | if (inPlace || exists(to)) {
|
90 | inquirer.prompt([{
|
91 | type: 'confirm',
|
92 | message: inPlace
|
93 | ? 'Generate project in current directory?'
|
94 | : 'Target directory exists. Continue?',
|
95 | name: 'ok'
|
96 | }]).then(answers => {
|
97 | if (answers.ok) {
|
98 | run()
|
99 | }
|
100 | }).catch(logger.fatal)
|
101 | } else {
|
102 | run()
|
103 | }
|
104 |
|
105 | /**
|
106 | * Check, download and generate the project.
|
107 | */
|
108 |
|
109 | function run () {
|
110 | // check if template is local
|
111 | if (isLocalPath(template)) {
|
112 | const templatePath = getTemplatePath(template)
|
113 | if (exists(templatePath)) {
|
114 | generate(name, templatePath, to, err => {
|
115 | if (err) logger.fatal(err)
|
116 | logger.success('Generated "%s".', name)
|
117 | })
|
118 | } else {
|
119 | logger.fatal('Local template "%s" not found.', template)
|
120 | }
|
121 | } else {
|
122 | console.log('3333333333333')
|
123 | checkVersion(() => {
|
124 | if (!hasSlash) {
|
125 | // use official templates
|
126 | const officialTemplate = 'Fang-fs/' + template
|
127 | if (template.indexOf('#') !== -1) {
|
128 | downloadAndGenerate(officialTemplate)
|
129 | } else {
|
130 | if (template.indexOf('-2.0') !== -1) {
|
131 | warnings.v2SuffixTemplatesDeprecated(template, inPlace ? '' : name)
|
132 | return
|
133 | }
|
134 |
|
135 | // warnings.v2BranchIsNowDefault(template, inPlace ? '' : name)
|
136 | downloadAndGenerate(officialTemplate)
|
137 | }
|
138 | } else {
|
139 | downloadAndGenerate(template)
|
140 | }
|
141 | })
|
142 | }
|
143 | }
|
144 |
|
145 | /**
|
146 | * Download a generate from a template repo.
|
147 | *
|
148 | * @param {String} template
|
149 | */
|
150 | /**
|
151 | * 定义下载模板并生产项目的函数 downloadAndGenerate
|
152 | */
|
153 | function downloadAndGenerate (template) {
|
154 | const spinner = ora('downloading template')
|
155 | spinner.start()
|
156 | // Remove if local template exists
|
157 | if (exists(tmp)) rm(tmp)
|
158 | download(template, tmp, { clone }, err => {
|
159 | spinner.stop()
|
160 | if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim())
|
161 | console.log('999999999999');
|
162 | generate(name, tmp, to, err => {
|
163 | if (err) logger.fatal(err)
|
164 | console.log()
|
165 | logger.success('Generated "%s".', name)
|
166 | })
|
167 | })
|
168 | }
|