tbfe/generator-mis

View on GitHub
app/index.js

Summary

Maintainability
F
1 wk
Test Coverage
'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');
//for parsing and manipulate javascript code
var program = require('ast-query');

module.exports = yeoman.generators.Base.extend({
    initializing: function() {
        // Have Yeoman greet the user.
        this.log(yosay(
            chalk.yellow('TIEBA MIS GENERATOR ')
        ));

        this.log('need help? go and open issue: https://github.com/tbfe/generator-mis/issues/new');

        this.mis = {};

        this.pkg = require('../package.json');
        //尝试读取deploy-conf.js文件,并且获取模块名,部署路径等,如果是全新模块则会读取失败,这些信息稍后由用户输入
        var deployConfFile = this.expand(this.destinationPath('deploy-conf.js'));
        if (deployConfFile.length > 0) {
            //file exists
            var deployConfTree = program(this.readFileAsString(this.destinationPath('deploy-conf.js')));
            var deployConfBody = deployConfTree.assignment('module.exports').value();

            //host
            this.mis.host = deployConfBody.key('\'host\'').value();
            //modName
            this.mis.modName = deployConfBody.key('\'modName\'').value();
            //subModName
            this.mis.subModName = deployConfBody.key('\'subModName\'').value();

            this.log(
                '检测到deploy-conf.js文件里已有如下信息:\n ' +
                chalk.yellow('host') + ':' + this.mis.host + '\n ' +
                chalk.yellow('modName') + ':' + this.mis.modName + '\n ' +
                chalk.yellow('subModName') + ':' + this.mis.subModName +
                '\n 将以此为基础生成新的项目,你也可以在稍后的提问中进行更改'
            );

            //这里获取到项目名后可以用于之后添加view用,同时用于后面项目同名冲突的检测
            //进一步检测control文件夹下存在哪些项目,用于后面项目重名时的覆盖提示
            this.existedProjects = [];
            var controlFiles = this.expand(this.destinationPath('control/*.php'));
            controlFiles.forEach(function(v) {
                this.existedProjects.push(this._.chain(v).strRightBack('/').strLeftBack('.php').underscored().value());
            }.bind(this));

        } else {
            //host
            this.mis.host = '';
            //modName
            this.mis.modName = '';
            //subModName
            this.mis.subModName = '';

            this.log(
                chalk.yellow('没有检测到deploy-conf.js文件,将会生成整个模块需要的所有文件并创建项目')
            );
        }
    },

    prompting: function() {
        var done = this.async();
        //collect some info to setup the project
        var prompts = [{
            type: 'input',
            name: 'author',
            message: '作者(用于生成文件头部的文档):',
            default: this.user.git.name() || process.env.USER || 'tbfe',
            store: true
        }, {
            type: 'input',
            name: 'projectName',
            message: '项目名 (会用来生成主angular模块,control文件及template文件):',
            default: 'Sample',
            validate: function(input) {
                if (this.existedProjects && this.existedProjects.indexOf(this._.underscored(input)) > -1) {
                    return input + ' 已存在!';
                } else {
                    return true;
                }
            }.bind(this)
        }, {
            type: 'list',
            name: 'projectType',
            choices: ['MIS', '平台化MIS', '业务线'],
            message: '项目类型',
            store: true,
            default: 0
        }, {
            type: 'input',
            name: 'host',
            message: '部署地址:',
            default: this.mis.host
        }, {
            type: 'confirm',
            name: 'singleMod',
            message: '本项目有父子模块么?',
            default: false,
            when: function() {
                //如果检测到子模块名,则此项默认为true, 否则为false
                return this.mis.subModName.length === 0;
            }.bind(this)
        }, {
            type: 'confirm',
            name: 'singleMod',
            message: '本项目有父子模块么?',
            default: true,
            when: function() {
                //如果检测到子模块名,则此项默认为true, 否则为false
                return this.mis.subModName.length > 0;
            }.bind(this)
        }, {
            type: 'input',
            name: 'modName',
            message: '模块名:',
            when: function(anwsers) {
                return !anwsers.singleMod;
            },
            default: this.mis.modName,
            validate: function(input) {
                this.log(this.mis.modName);
                //如果是新模块,此字段为必需
                if (!this.mis.modName && !input) {
                    return false;
                } else {
                    return true;
                }
            }.bind(this)
        }, {
            type: 'input',
            name: 'modName',
            message: '主模块名:',
            when: function(anwsers) {
                return anwsers.singleMod;
            },
            default: this.mis.modName,
            validate: function(input) {
                this.log(this.mis.modName);
                //如果是新模块,此字段为必需
                if (!this.mis.modName && !input) {
                    return false;
                } else {
                    return true;
                }
            }.bind(this)
        }, {
            type: 'input',
            name: 'subModName',
            message: '子模块名:',
            default: this.mis.subModName,
            when: function(anwsers) {
                return anwsers.singleMod;
            },
            validate: function(input) {
                this.log(this.mis.subModName);
                //如果是新模块,且选择了有父子模块,则此字段也是必需的
                if (!this.mis.subModName && !input) {
                    return false;
                } else {
                    return true;
                }
            }.bind(this)
        }, {
            type: 'input',
            name: 'modDescription',
            message: '模块描述:',
            default: ''
        }, {
            type: 'checkbox',
            name: 'uiPlugins',
            choices: ['bootstrap-material-design', 'sweetalert', 'animate.css', 'highcharts-ng', 'lodash', 'moment','pace', 'ztree'],
            message: '以下插件按需选择(空格进行选择)',
            when: function(anwsers) {
                return anwsers.projectType !== '业务线';
            }
        }];

        this.prompt(prompts, function(anwsers) {
            this.mis = anwsers;
            this.mis.date = new Date().toISOString().substring(0, 10);
            this.mis.goodbyeMsg = chalk.green('All done!\n') + chalk.white('好用再来!') + '\n' + chalk.yellow('HAPPY CODING \\(^____^)/');

            //去掉了主题选项,只有默认主题
            this.mis.theme = 'default';

            //防止subModName可能会为undefined
            this.mis.subModName = this.mis.subModName || '';
            //防止uiPlugins可能会为undefined
            this.mis.uiPlugins = this.mis.uiPlugins || [];

            done();
        }.bind(this));
    },

    writing: {
        app: function() {
            this.fs.copy(
                this.templatePath('_package.json'),
                this.destinationPath('package.json')
            );
            this.fs.copyTpl(
                this.templatePath('_bower.json'),
                this.destinationPath('bower.json'),
                this.mis
            );
            this.fs.copyTpl(
                this.templatePath('_gruntfile.js'),
                this.destinationPath('Gruntfile.js'), {
                    uiPlugins: this.mis.uiPlugins
                }
            );
        },

        projectfiles: function() {
            var fileBase = this._.underscored(this.mis.projectName);

            //生成bingo空文件夹但angular开发方案中无用
            this.mkdir('data');
            this.mkdir('layout');
            this.mkdir('widget');
            //end

            //复制配置文件
            this.fs.copy(
                this.templatePath('editorconfig'),
                this.destinationPath('.editorconfig')
            );
            this.fs.copy(
                this.templatePath('jshintrc'),
                this.destinationPath('.jshintrc')
            );
            //end

            //复制编译脚本
            this.fs.copy(
                this.templatePath('build.sh'),
                this.destinationPath('build.sh')
            );
            this.fs.copy(
                this.templatePath('Makefile'),
                this.destinationPath('Makefile')
            );
            this.fs.copyTpl(
                this.templatePath('readme.txt'),
                this.destinationPath('readme.txt'),
                this.mis
            );
            //end

            //deploy-conf.js
            this.fs.copyTpl(
                this.templatePath('deploy-conf.js'),
                this.destinationPath('deploy-conf.js'),
                this.mis
            );

            //fis-conf.js
            //新模块则创建该文件,否则更新该文件
            if (!this.existedProjects) {
                this.fs.copyTpl(
                    this.templatePath('fis-conf.js'),
                    this.destinationPath('fis-conf.js'), {
                        projectName: fileBase
                    }
                );
            } else {
                var fisConfFile = program(this.readFileAsString(this.destinationPath('fis-conf.js')));
                var fisConfContent = fisConfFile.callExpression('fis.config.merge');
                //添加文件合并规则
                fisConfContent.arguments.at(0).key('pack').key('\'static/' + fileBase + '/app_all.js\'').value('[/static\\/' + fileBase + '\\/.*\.js$/]');
                fisConfContent.arguments.at(0).key('pack').key('\'static/' + fileBase + '/app_all.css\'').value('[/static\\/' + fileBase + '\\/.*\.css$/]');
                this.fs.write(this.destinationPath('fis-conf.js'), fisConfFile.toString());
            }
            //end

            //这里分三条路,MIS路线,平台化MIS和业务线
            if (this.mis.projectType !== '业务线') {
                //control
                this.fs.copyTpl(
                    this.templatePath('control/_control.php'),
                    this.destinationPath('control/' + fileBase + '.php'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        projectName: fileBase,
                    }
                );

                //template
                if (this.mis.projectType === 'MIS') {
                    //MIS路线
                    this.fs.copyTpl(
                        this.templatePath('template/_template.php'),
                        this.destinationPath('template/' + fileBase + '/index.php'), {
                            date: this.mis.date,
                            author: this.mis.author,
                            projectName: this._.humanize(this.mis.projectName),
                            projectFoler: fileBase,
                            modName: this.mis.modName,
                            uiPlugins: this.mis.uiPlugins,
                            theme: this.mis.theme
                        }
                    );

                    //template/index.css
                    this.fs.copy(
                        this.templatePath('static/project/views/' + this.mis.theme + '/theme.css'),
                        this.destinationPath('template/' + fileBase + '/index.css')
                    );

                } else {
                    //平台化
                    this.fs.copyTpl(
                        this.templatePath('template/_template_pplatform.php'),
                        this.destinationPath('template/' + fileBase + '/index.php'), {
                            date: this.mis.date,
                            author: this.mis.author,
                            projectName: this._.humanize(this.mis.projectName),
                            projectFoler: fileBase,
                            modName: this.mis.modName,
                            uiPlugins: this.mis.uiPlugins,
                            theme: this.mis.theme
                        }
                    );

                    //template/index.css
                    this.fs.copy(
                        this.templatePath('static/project/views/pplatform/theme.css'),
                        this.destinationPath('template/' + fileBase + '/index.css')
                    );


                    // 平台化需要resetcss
                    this.fs.copy(
                        this.templatePath('static/lib/resetcss.css'),
                        this.destinationPath('static/lib/resetcss.css')
                    );

                }

                //template/index.js
                this.fs.copyTpl(
                    this.templatePath('template/_template.js'),
                    this.destinationPath('template/' + fileBase + '/index.js'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        uiPlugins: this.mis.uiPlugins,
                    }
                );

                //angular app.js
                this.fs.copyTpl(
                    this.templatePath('static/project/_app.js'),
                    this.destinationPath('static/' + fileBase + '/app.js'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        moduleName: this._.camelize(this.mis.projectName),
                        modName: this.mis.modName,
                        uiPlugins: this.mis.uiPlugins
                    }
                );

                //resource file
                this.fs.copyTpl(
                    this.templatePath('static/project/resources/_resource.js'),
                    this.destinationPath('static/' + fileBase + '/resources/resource.js'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        resourceName: this._.classify(this.mis.projectName),
                        projectName: this._.camelize(this.mis.projectName)
                    }
                );

                //filter file
                this.fs.copyTpl(
                    this.templatePath('static/project/filters/_filter.js'),
                    this.destinationPath('static/' + fileBase + '/filters/filter.js'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        resourceName: this._.classify(this.mis.projectName),
                        projectName: this._.camelize(this.mis.projectName)
                    }
                );

                //navbar directive
                this.fs.copyTpl(
                    this.templatePath('static/project/directives/navbar/_navbar.html'),
                    this.destinationPath('static/' + fileBase + '/directives/navbar/navbar.html'), {
                        theme: this.mis.theme,
                        projectName: this._.camelize(this.mis.projectName)
                    }
                );

                //如果是平台化MIS,则复制sidebar
                if (this.mis.projectType === '平台化MIS') {
                    this.fs.copy(
                        this.templatePath('static/project/directives/sidebar/_sidebar.html'),
                        this.destinationPath('static/' + fileBase + '/directives/sidebar/sidebar.html')
                    );
                    this.fs.copyTpl(
                        this.templatePath('static/project/directives/sidebar/_sidebar.js'),
                        this.destinationPath('static/' + fileBase + '/directives/sidebar/sidebar.js'), {
                            date: this.mis.date,
                            author: this.mis.author,
                            projectName: this._.camelize(this.mis.projectName)
                        }
                    );
                    this.fs.copyTpl(
                        this.templatePath('static/project/directives/sidebar/_sidebar.css'),
                        this.destinationPath('static/' + fileBase + '/directives/sidebar/sidebar.css'), {
                            date: this.mis.date,
                            author: this.mis.author,
                            projectName: this._.camelize(this.mis.projectName)
                        }
                    );

                }

                this.fs.copyTpl(
                    this.templatePath('static/project/directives/navbar/_navbar.js'),
                    this.destinationPath('static/' + fileBase + '/directives/navbar/navbar.js'), {
                        projectName: this._.camelize(this.mis.projectName)
                    }
                );

                // sample views
                for (var i = 2; i >= 1; i--) {

                    //view template
                    this.fs.copyTpl(
                        this.templatePath('static/project/views/' + (this.mis.projectType === 'MIS'?this.mis.theme:'pplatform') + '/view.html'),
                        this.destinationPath('static/' + fileBase + '/views/view' + i + '/view' + i + '.html'), {
                            viewName: 'view' + i
                        }
                    );

                    //view controller
                    this.fs.copyTpl(
                        this.templatePath('static/project/views/view.js'),
                        this.destinationPath('static/' + fileBase + '/views/view' + i + '/view' + i + '_controller.js'), {
                            date: this.mis.date,
                            author: this.mis.author,
                            resourceName: this._.classify(this.mis.projectName),
                            projectName: this._.camelize(this.mis.projectName),
                            index: i,
                            controllerName: 'View' + i + 'Ctrl',
                            theme: this.mis.theme
                        }
                    );

                    //view style
                    this.fs.copyTpl(
                        this.templatePath('static/project/views/view.css'),
                        this.destinationPath('static/' + fileBase + '/views/view' + i + '/view' + i + '.css'), {
                            date: this.mis.date,
                            author: this.mis.author
                        }
                    );
                }
            } else {
                //业务线模板
                //control
                this.fs.copyTpl(
                    this.templatePath('control/_control_business.php'),
                    this.destinationPath('control/' + fileBase + '.php'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        projectName: fileBase,
                    }
                );

                this.fs.copyTpl(
                    this.templatePath('template/_template_business.php'),
                    this.destinationPath('template/' + fileBase + '/' + fileBase + '.php'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        templateDescription: this.mis.modDescription
                    }
                );
                //template js
                this.fs.copyTpl(
                    this.templatePath('template/_template.js'),
                    this.destinationPath('template/' + fileBase + '/' + fileBase + '.js'), {
                        date: this.mis.date,
                        author: this.mis.author,
                        uiPlugins: this.mis.uiPlugins
                    }
                );

                //template css
                this.fs.copyTpl(
                    this.templatePath('template/_template.css'),
                    this.destinationPath('template/' + fileBase + '/' + fileBase + '.css'), {
                        date: this.mis.date,
                        author: this.mis.author
                    }
                );

                //static directory
                this.mkdir('static');

            }

            //static/img
            this.fs.copy(
                this.templatePath('static/img/tb-logo.png'),
                this.destinationPath('static/img/tb-logo.png')
            );

        }
    },

    install: function() {
        this.installDependencies({
            // skipInstall: !this.mis.uiPlugins.length, //项目为MIS并且选择了插件才进行安装
            skipInstall: false, //项目为MIS并且选择了插件才进行安装
            callback: function() {

                //如果选择了插件才进行复制
                if ( !! this.mis.uiPlugins.length) {
                    this.log('将bower安装的插件复制到static/lib目录下...');
                    var gruntTask = this.spawnCommand('grunt', ['copy']);

                    //when finish copying, say goodbye
                    gruntTask.on('close', function(code) {
                        //if exited abnormally the code is null
                        if (code === null) {
                            this.log('error while copying file to static folder :(');
                        } else {
                            this.log('文件复制完成!');
                            this.log(this.mis.goodbyeMsg);
                        }
                    }.bind(this));
                } else {
                    this.log('没有需要复制的文件');
                    this.log(this.mis.goodbyeMsg);
                }

            }.bind(this)
        });
    },
    end: function() {

        //store user configuration
        this.config.set('author', this.mis.author);
        this.config.set('projectName', this.mis.projectName);

        //一些善后工作,ignore bower_components folder, 删除带中文的文件避免编译失败
        //在ocean机器上会执行失败,先去掉
        // this.spawnCommand('rm bower_components/ztree_v3/QUI 框架介绍.txt');
    }
});