From 2b4933a00bce060b44c1b38b8453e21072326f4e Mon Sep 17 00:00:00 2001 From: pasturn Date: Sun, 9 Apr 2017 00:15:44 +0800 Subject: [PATCH] update omi-cli --- cli/README.md | 29 +++++-- cli/bin/omi | 102 ++++++++++++++++------- cli/bin/omi-init | 9 -- cli/lib/init-pr.js | 107 ++++++++++++++++++++++++ cli/lib/init.js | 136 +++++++++++++++++-------------- cli/lib/install.js | 23 ++++-- cli/lib/mirror.json | 8 ++ cli/lib/omi-pr/build.js | 121 +++++++++++++++++++++++++++ cli/lib/omi-pr/loadjs.js | 15 ++++ cli/lib/omi-pr/webpack.config.js | 78 ++++++++++++++++++ cli/lib/pr.js | 26 ++++++ cli/lib/utils.js | 36 ++++++++ cli/package.json | 12 ++- 13 files changed, 585 insertions(+), 117 deletions(-) delete mode 100644 cli/bin/omi-init create mode 100644 cli/lib/init-pr.js create mode 100644 cli/lib/mirror.json create mode 100644 cli/lib/omi-pr/build.js create mode 100644 cli/lib/omi-pr/loadjs.js create mode 100644 cli/lib/omi-pr/webpack.config.js create mode 100644 cli/lib/pr.js create mode 100644 cli/lib/utils.js diff --git a/cli/README.md b/cli/README.md index 964b7d6a7..6c21a8041 100644 --- a/cli/README.md +++ b/cli/README.md @@ -3,26 +3,43 @@ CLI for scaffolding Omi.js projects. -### Installation +## Installation Prerequisites: Node.js (>=6.x), npm version 3+ ``` $ npm install omi-cli -g ``` -### Usage - +## Usage +initialize a new omi application `omi-app` : ``` $ omi init // in current directory $ omi init [project name] // in new directroy named project name -$ omi init [project name] [cn] // shift to cnpm mirror ``` -Example: +initialize a new omi project `omi-pr` : +``` +$ omi init-pr // in current directory +$ omi init-pr [project name] // in new directroy named project name +``` +if you want to compile project for ssr, you can run: +``` +$ omi pr +``` +in your omi-pr project + +## Example: ``` $ omi init app +$ omi init-pr project +$ omi pr + ..... ``` -omi-cli will run npm to install dependencies. +omi-cli will run npm command to install dependencies automatically. You could switch the mirror source with: +``` +$ omi init app -m cnpm +``` +we support to shift from default to `npm`, `cnpm` or `taobao` mirror. ## Scaffolding diff --git a/cli/bin/omi b/cli/bin/omi index 7c715000b..8554c526e 100755 --- a/cli/bin/omi +++ b/cli/bin/omi @@ -8,51 +8,93 @@ var chalk = require('chalk'); var exists = require('fs-exists-sync'); var spawn = require('cross-spawn'); +var options = { + cmd: '', + projectName: '', + mirror: 'default', + language: 'en' +} + program .version(require('../package').version, '-v, --version') - .usage('init [project-name]') - .on('--help', help); + .usage(' [project-name]') + .option('-m, --mirror ', 'Select mirror like: npm, cnpm, taobao', /^(npm|cnpm|taobao|nj|rednpm|skimdb)$/i) + .option('-l, --language ', 'Select language: en / cn', selectLanguage) + .on('-h, --help', help); + + +program + .command('init [projectName]') + .description('Initialize a new Omi application in the current folder') + .action(function(projectName, option){ + var cmd = 'init'; + if(option.parent.mirror){ + options.mirror = option.parent.mirror; + } + switchCommand(cmd, {project: projectName, mirror: options.mirror, language: options.language}) + }) + +program + .command('init-pr [projectName]') + .description('Initialize a new Omi-Pr in the current folder') + .action(function(projectName, option){ + var cmd = 'init-pr'; + if(option.parent.mirror){ + options.mirror = option.parent.mirror; + } + switchCommand(cmd, {project: projectName, mirror: options.mirror, language: options.language}) + }) + +program + .command('pr') + .description('Compile your omi project') + .action(function(option){ + var cmd = 'pr'; + switchCommand(cmd, {language: options.language}) + }) + + +program + .command('*') + .action(function(){ + spawn('omi', ['-h'], { stdio: 'inherit'}) + }) program.parse(process.argv); -var args = process.argv.slice(3); - -let cmdstr = program.args[0]; - -if (cmdstr) { - - const binFile = executable(cmdstr); - if (binFile) { - console.log(); - console.log(chalk.bold.cyan("Omi-cli") + " is initializing... "); - secede(spawn('node', [].concat([binFile], args), {stdio: 'inherit'})) +function switchCommand (cmd, args) { + if (cmd) { + require('../lib/' + cmd)(args); } else { - program.help(); + setTimeout(program.help, 0); } -} else { - program.help(); +} + +function isCnFuc(language){ + return language === "cn" ? true : false +} + +function selectLanguage(language){ + if(language !== 'en' && language !== 'cn'){ + language = 'en'; + } + options.language = language; + return language; +} + +function executable(cmd) { + var file = join(__dirname, 'omi-' + cmd); + return exists(file) ? file : void 0; } function help() { console.log(' Commands:'); console.log(); console.log(` ${chalk.green('init [project-name]')} Initialize a new Omi application in the current folder `); - console.log(); - console.log(` ${chalk.green('init [project-name] [cn]')} Shift the npm registry to cnpm mirror `); + console.log(` ${chalk.green('init-pr [project-name]')} Initialize a new Omi-Pr in the current folder `) + console.log(` ${chalk.green('pr')} Compile your omi project `) console.log(); console.log(' All commands can be run with -h (or --help) for more information.') } -function executable(cmdstr) { - const file = join(__dirname, 'omi-' + cmdstr); - if (exists(file)) { - return file - } -} - -function secede(line){ - line.on('close', function(code){ - process.exit(code) - }) -} diff --git a/cli/bin/omi-init b/cli/bin/omi-init deleted file mode 100644 index 95acedbdb..000000000 --- a/cli/bin/omi-init +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); - -program - .arguments('[project-name]') - .parse(process.argv); - -require('../lib/init')(program); diff --git a/cli/lib/init-pr.js b/cli/lib/init-pr.js new file mode 100644 index 000000000..180c2ba57 --- /dev/null +++ b/cli/lib/init-pr.js @@ -0,0 +1,107 @@ +var path = require('path'); +var join = path.join; +var basename = path.basename; +var vfs = require('vinyl-fs'); +// var renameSync = require('fs').renameSync; +var existsSync = require('fs').existsSync; +var chalk = require('chalk'); +var through = require('through2'); +var emptyDir = require('empty-dir'); +var logger = require('./logger'); +var info = logger.info; +var error = logger.error; +var success = logger.success; +var isCnFun = require('./utils').isCnFuc; +var emptyFs = require('./utils').emptyFs; + +function initPr(args) { + var omiCli = chalk.bold.cyan("Omi-Cli"); + var isCn = isCnFun(args.language); + var customPrjName = args.project || ''; + var tpl = join(__dirname, '../template/pr'); + var dest = join(process.cwd(), customPrjName); + var projectName = basename(dest); + var mirror = args.mirror; + + console.log(); + console.log(omiCli + (!isCn ? " is booting... ": " 正在启动...")); + console.log(omiCli + (!isCn ? " will execute init-pr command... ": " 即将执行 init-pr 命令...")); + + if(existsSync(dest) && !emptyDir.sync(dest)) { + console.log(); + process.stdout.write(!isCn ? "This directory isn't empty, empty it? [Y/N] ": "此文件夹不为空,是否需要清空? [Y/N]: "); + process.stdin.resume(); + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', (chunk) => { + chunk = chunk.replace(/\s\n|\r\n/g, ''); + if(chunk !== 'y' && chunk !== 'Y') { + process.exit(0); + } else { + console.log(chalk.bold.cyan("Omi-Cli")+ (!isCn ? ' is emptying this directory...' : ' 正在清空此文件夹...')); + emptyFs(dest); + createPr() + } + }); + } else { + createPr() + } + + function createPr() { + console.log(); + console.log(chalk.bold.cyan("Omi-Cli") + (!isCn ? ' will creating a new omi-pr in ' : ' 即将创建一个新的omi-pr在 ') + dest); + + vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true}) + .pipe(template(dest, tpl)) + .pipe(vfs.dest(dest)) + .on('end', function(){ + try{ + // info('Rename', 'gitignore -> .gitignore'); + // renameSync(join(dest, 'gitignore'), join(dest, '.gitignore')); + if(customPrjName) { + try{ + process.chdir(customPrjName); + } + catch (err) { + console.log(error(err)); + } + } + info('Install', 'npm will install dependencies'); + console.log(); + require('./install')(mirror, done) + } catch(e){ + console.log(error(e)) + } + }) + .resume(); + } + + function done(){ + console.log(); + console.log(); + console.log(); + success(`Congratulation! a Omi-pr has been created successful! `); + console.log(` + +if you are not in ${projectName}, please run 'cd ${projectName}', then you can: + + > ${chalk.bold.white('omi pr')} compile your project`); + console.log(); + console.log(`${chalk.bold.cyan('Omi!')} https://alloyteam.github.io/omi` ) + } + + +} + +function template(dest, cwd) { + return through.obj(function (file, enc, cb) { + if (!file.stat.isFile()) { + return cb(); + } + + info('Copy', file.path.replace(cwd + '/', '')); + this.push(file); + cb(); + }); +} + +module.exports = initPr; \ No newline at end of file diff --git a/cli/lib/init.js b/cli/lib/init.js index 26d6ab79c..72d45041d 100644 --- a/cli/lib/init.js +++ b/cli/lib/init.js @@ -1,96 +1,110 @@ -var join = require('path').join; -var basename = require('path').basename; +var path = require('path'); +var join = path.join; +var basename = path.basename; +var fs = require('fs'); var vfs = require('vinyl-fs'); -var renameSync = require('fs').renameSync; +var renameSync = fs.renameSync; +var existsSync = fs.existsSync; var chalk = require('chalk'); var through = require('through2'); var emptyDir = require('empty-dir'); var info = require('./logger').info; var error = require('./logger').error; var success = require('./logger').success; +var isCnFun = require('./utils').isCnFuc; +var emptyFs = require('./utils').emptyFs; - -function init(program) { - var args = ['install']; - var customPrj = ''; - if(program.args[0] && program.args[0] === "cn"){ - args = ['install', "--registry", "https://registry.npm.taobao.org"]; - } else if(program.args[1] && program.args[1] === "cn") { - customPrj = program.args[0]; - args = ['install', "--registry", "https://registry.npm.taobao.org"]; - } else { - customPrj = program.args[0] || ''; - } - +function init(args){ + var omiCli = chalk.bold.cyan("Omi-Cli"); + var isCn = isCnFun(args.language); + var customPrjName = args.project || ''; var tpl = join(__dirname, '../template/app'); - var dest = join(process.cwd(), customPrj); + var dest = join(process.cwd(), customPrjName); var projectName = basename(dest); - - if (!customPrj && !emptyDir.sync(dest)) { - error('This directory existing files, please empty.'); - process.exit(1); - } + var mirror = args.mirror; console.log(); - console.log(`Creating a new Omi app in ${dest}`); + console.log(omiCli + (!isCn ? " is booting... ": " 正在启动...")); + console.log(omiCli + (!isCn ? " will execute init command... ": " 即将执行 init 命令...")); - /* - * Use vinyl-fs to init file - * https://github.com/dvajs/dva-cli/blob/master/src/init.js - */ - vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true}) - .pipe(template(dest, tpl)) - .pipe(vfs.dest(dest)) - .on('end', function(){ - try{ - info('Rename', 'gitignore -> .gitignore'); - renameSync(join(dest, 'gitignore'), join(dest, '.gitignore')); - if(customPrj) { - try{ - process.chdir(customPrj); - } - catch (err) { - console.log(error(err)); - }} - info('Run', 'npm will install dependencies'); - console.log(); - require('./install')(args, echoDone) - } catch(e){ - console.log(error(e)) + if(existsSync(dest) && !emptyDir.sync(dest)) { + console.log(); + process.stdout.write(!isCn ? "This directory isn't empty, empty it? [Y/N] ": "此文件夹不为空,是否需要清空? [Y/N]: "); + process.stdin.resume(); + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', (chunk) => { + chunk = chunk.replace(/\s\n|\r\n/g, ''); + if(chunk !== 'y' && chunk !== 'Y') { + process.exit(0); + } else { + console.log(chalk.bold.cyan("Omi-Cli")+ (!isCn ? ' is emptying this directory...' : ' 正在清空此文件夹...')); + emptyFs(dest); + createApp() } - }) - .resume(); + }); + } else { + createApp() + } - function echoDone(){ + + function createApp() { + console.log(); + console.log(chalk.bold.cyan("Omi-Cli") + (!isCn ? ' will creating a new omi app in ' : ' 即将创建一个新的应用在 ') + dest); + + vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true}) + .pipe(template(dest, tpl)) + .pipe(vfs.dest(dest)) + .on('end', function(){ + try{ + info('Rename', 'gitignore -> .gitignore'); + renameSync(join(dest, 'gitignore'), join(dest, '.gitignore')); + if(customPrjName) { + try{ + process.chdir(customPrjName); + } + catch (err) { + console.log(error(err)); + } + } + info('Install', 'npm will install dependencies'); + console.log(); + require('./install')(mirror, done) + } catch(e){ + console.log(error(e)) + } + }) + .resume(); + } + + function done(){ console.log(); console.log(); console.log(); success(`Congratulation! "${projectName}" has been created successful! `); console.log(` - + Using the scaffold with Gulp + Webpack + Babel + BrowserSync, - -In ${projectName}, you can run these commands: - - > ${chalk.bold.white('npm run dev')} Starts the development server - > ${chalk.bold.white('npm run dist')} Publish your project`); + +if you are not in ${projectName}, please run 'cd ${projectName}', then you can: + + > ${chalk.bold.white('npm run dev')} Starts the development server + > ${chalk.bold.white('npm run dist')} Publish your project`); console.log(); console.log(`${chalk.bold.cyan('Omi!')} https://alloyteam.github.io/omi` ) - } - + } function template(dest, cwd) { - return through.obj(function (file, enc, cb) { + return through.obj(function (file, enc, cb) { if (!file.stat.isFile()) { return cb(); } info('Copy', file.path.replace(cwd + '/', '')); - this.push(file); - cb(); - }); + this.push(file); + cb(); + }); } module.exports = init; \ No newline at end of file diff --git a/cli/lib/install.js b/cli/lib/install.js index caaed611a..c59f7109f 100644 --- a/cli/lib/install.js +++ b/cli/lib/install.js @@ -1,13 +1,20 @@ var spawn = require('cross-spawn'); var ora = require('ora'); -module.exports = function (args, done){ - var common = spawn('npm', args, { stdio: 'inherit' }); - common.on('close', function () { - done(); - process.exit(0); - }); - common.on('error', function (reason) { +module.exports = function (mirror, done){ + var registry; + if(mirror !== 'default'){ + registry = ['--registry', require('./mirror')[mirror]]; + } + secede(spawn('npm', registry ? [].concat(['install'], registry) : ['install'], { stdio: 'inherit'})); +}; + +function secede(line){ + line.on('close', function(code){ + process.exit(code) + }) + + line.on('error', function (reason) { console.log('An error occured while executing the NPM command.', reason); }); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/cli/lib/mirror.json b/cli/lib/mirror.json new file mode 100644 index 000000000..5d0edc847 --- /dev/null +++ b/cli/lib/mirror.json @@ -0,0 +1,8 @@ +{ + "npm": "https://registry.npmjs.org/", + "cnpm": "http://r.cnpmjs.org/", + "taobao": "https://registry.npm.taobao.org/", + "nj": "https://registry.nodejitsu.com/", + "rednpm": "http://registry.mirror.cqupt.edu.cn", + "skimdb": "https://skimdb.npmjs.com/registry" +} \ No newline at end of file diff --git a/cli/lib/omi-pr/build.js b/cli/lib/omi-pr/build.js new file mode 100644 index 000000000..8dc89ed85 --- /dev/null +++ b/cli/lib/omi-pr/build.js @@ -0,0 +1,121 @@ +const webpack = require('webpack') +const path = require('path') +const fs = require('fs') +let webpackConfig = require('./webpack.config.js') +let omiConfig = require(path.resolve('.')+"/omi.config.js") + +const dir = path.resolve('.') +const compiler = webpack(webpackConfig) +const jsdom = require("jsdom").jsdom +const window = jsdom().defaultView +const keys = Object.keys(webpackConfig.entry) +const len = keys.length +let index = 0 +let list = [] + +const build = () => { + compiler.run((err, stats) => { + if (err) { + console.error(err) + return + } + + const jsonStats = stats.toJson() + + if (jsonStats.errors.length > 0) { + const error = new Error(jsonStats.errors[0]) + error.errors = jsonStats.errors + error.warnings = jsonStats.warnings + console.log(jsonStats) + return + } + + getHTMLCSS(keys[index]) + }) +} + + + +const getHTMLCSS = (name) =>{ + window.document.head.innerHTML = '' + window.document.body.innerHTML = '' + window.Omi = null + let scriptEl = window.document.createElement("script"); + + scriptEl.onload = function () { + fs.unlinkSync(scriptEl.src) + list.push([window.document.head.innerHTML, '
'+window.document.body.innerHTML.replace('`, 'utf-8')) + fs.unlinkSync(name) + }) + + //http://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color + console.log('\x1b[32m') + console.log('-------------------------------------------') + console.log('-------------------------------------------') + console.log('-----------Successfully Executed-----------') + console.log('-------------------------------------------') + console.log('-------------------------------------------') + console.log('\x1b[37m') + }) +} + +const template = (tpl,html,css,js)=>{ + return tpl.replace('{{html}}',html).replace('{{css}}',css).replace('{{js}}',js) +} + +module.exports = build; \ No newline at end of file diff --git a/cli/lib/omi-pr/loadjs.js b/cli/lib/omi-pr/loadjs.js new file mode 100644 index 000000000..3c90df03e --- /dev/null +++ b/cli/lib/omi-pr/loadjs.js @@ -0,0 +1,15 @@ +(function () { + load('{{omi-cdn}}',function (err) { + eval(__OMI_DATA__.component) + }) + + function load (src, fn) { + fn = fn || function () {} + var script = document.createElement('script') + script.src = src + script.onload = function () { fn(null) } + script.onerror = fn + script.crossorigin = 'anonymous' + document.head.appendChild(script) + } +})() \ No newline at end of file diff --git a/cli/lib/omi-pr/webpack.config.js b/cli/lib/omi-pr/webpack.config.js new file mode 100644 index 000000000..683157310 --- /dev/null +++ b/cli/lib/omi-pr/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path') +const webpack = require("webpack") +const commonChunkPlugin = webpack.optimize.CommonsChunkPlugin +const fs = require('fs') + +let fileList = {}; + +walk(path.resolve('.')+'/src/page'); + +var config = { + entry: fileList, + output: { + filename: '[name].js' + }, + //watch: true, + module: { + rules: [ + { + test: /\.js$/, + loader: 'babel-loader', + query: { + presets: ["babel-preset-es2015", "babel-preset-stage-0"].map(require.resolve), + //support ie8 + plugins : [ + "babel-plugin-transform-es3-property-literals", + "babel-plugin-transform-es3-member-expression-literals" + ].map(require.resolve) + }, + exclude: /(node_modules|bower_components)/ + }, + {test: /\.html|\.css$/, loader: "string-loader"} + ] + }, + plugins: [ + // Avoid publishing files when compilation fails + new webpack.NoEmitOnErrorsPlugin() + ], + stats: { + // Nice colored output + colors: true + }, + externals: { + + }, + resolve: { + modules: [ + path.join(__dirname, '..', 'node_modules'), + 'node_modules', + path.join(__dirname, 'node_modules') + ] + }, + resolveLoader: { + modules: [ + path.join(__dirname, '..', 'node_modules'), + 'node_modules', + path.join(__dirname, 'node_modules') + ] + } + // Create Sourcemaps for the bundle + //devtool: 'source-map' +}; + + +config.plugins.push(new webpack.optimize.UglifyJsPlugin()); + +function walk(path){ + var dirList = fs.readdirSync(path); + dirList.forEach(function(item){ + if(fs.statSync(path + '/' + item).isDirectory()){ + fileList[item] = path + '/' + item+'/main.js' + //walk(path + '/' + item); + }else{ + //fileList.push(path + '/' + item); + } + }); +} + +module.exports = config; \ No newline at end of file diff --git a/cli/lib/pr.js b/cli/lib/pr.js new file mode 100644 index 000000000..86388a417 --- /dev/null +++ b/cli/lib/pr.js @@ -0,0 +1,26 @@ +var fs = require('fs'); +var chalk = require('chalk'); +var join = require('path').join; +var existsSync = fs.existsSync; + +function pr() { + var currentDir = process.cwd(); + var srcPath = join(currentDir, 'src'); + + if(existsSync(srcPath)){ + var build = require('./omi-pr/build'); + console.log(); + console.log(chalk.bold.cyan("Omi-Cli") + " is readying compiling..."); + console.log(); + + build(currentDir) + } else { + console.log(chalk.bold.red("-------------------------------------------")); + console.log(chalk.bold.red("---------------- Path Error ---------------")); + console.log(chalk.bold.red("-------------------------------------------")); + process.exit(1); + } + +} + +module.exports = pr; \ No newline at end of file diff --git a/cli/lib/utils.js b/cli/lib/utils.js new file mode 100644 index 000000000..cbd367591 --- /dev/null +++ b/cli/lib/utils.js @@ -0,0 +1,36 @@ +var fs = require('fs'); +var existsSync = fs.existsSync; +var readdirSync = fs.readdirSync; +var rmdirSync = fs.rmdirSync; +var unlinkSync = fs.unlinkSync; +var statSync = fs.statSync; + + +function isCnFuc(language){ + return language === "cn" ? true : false +} + +function emptyFs(path) { + var files = []; + var dir = []; + if(existsSync(path)){ + files = readdirSync(path); + files.forEach(function (file, index) { + var curPath = path + "/" + file; + if(statSync(curPath).isDirectory()){ + emptyFs(curPath) + } else { + unlinkSync(curPath); + } + }); + dir = readdirSync(path); + dir.forEach(function (dirName, index) { + rmdirSync(path + "/" + dirName) + }) + } +} + +module.exports = { + isCnFuc: isCnFuc, + emptyFs: emptyFs +}; \ No newline at end of file diff --git a/cli/package.json b/cli/package.json index a6ca206ac..b011ee105 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "omi-cli", - "version": "0.2.6", + "version": "0.2.7", "description": "CLI for scaffolding Omi.js projects.", "main": "bin/omi", "engines": { @@ -21,16 +21,22 @@ "author": "pasturn", "license": "MIT", "dependencies": { + "babel-plugin-transform-es3-member-expression-literals": "^6.22.0", + "babel-plugin-transform-es3-property-literals": "^6.22.0", + "babel-preset-es2015": "^6.24.1", + "babel-preset-stage-0": "^6.24.1", "chalk": "^1.1.3", "commander": "^2.9.0", "cross-npm-spawn": "^1.1.1", "cross-spawn": "^5.0.1", "empty-dir": "^0.2.1", "fs-exists-sync": "^0.1.0", + "jsdom": "^9.12.0", "ora": "^1.1.0", - "vinyl-fs": "^2.4.4" + "vinyl-fs": "^2.4.4", + "webpack": "^2.3.3" }, - "bugs": { + "bugs": { "url": "https://github.com/AlloyTeam/omi/issues" }, "homepage": "https://github.com/AlloyTeam/omi#readme"