daniellmb/generator-microjs

View on GitHub
app/index.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict';

var url = require('url');
var path = require('path');
var yeoman = require('yeoman-generator');
var yosay = require('yosay');
var npmName = require('npm-name');
/* jshint -W106 */
var proxy = process.env.http_proxy || process.env.HTTP_PROXY || process.env.https_proxy || process.env.HTTPS_PROXY || null;
/* jshint +W106 */
var githubOptions = {
  version: '3.0.0'
};

if (proxy) {
  var proxyUrl = url.parse(proxy);
  githubOptions.proxy = {
    host: proxyUrl.hostname,
    port: proxyUrl.port
  };
}

var GitHubApi = require('github');
var github = new GitHubApi(githubOptions);

var extractProj = function (_, appname) {
  var slugged = _.slugify(appname);
  var match = slugged.match(/^generator-(.+)/);

  if (match && match.length === 2) {
    return match[1].toLowerCase();
  }

  return slugged;
};

var toCamelCase = function (input) {
  return input.toLowerCase().replace(/-(.)/g, function (match, group1) {
    return group1.toUpperCase();
  });
};

var githubUserInfo = function (name, cb) {

  // handle bad data
  if (name === 'daniellmb') {
    /*jshint camelcase:false */
    cb({
      name: 'Daniel Lamb',
      email: 'dlamb.open.source@gmail.com',
      html_url: 'https://github.com/daniellmb'
    });

    // exit
    return;
  }

  github.user.getFrom({
    user: name
  }, function (err, res) {
    if (err) {
      throw new Error(err.message + '\n\nCannot fetch your github profile. Make sure you\'ve typed it correctly.');
    }
    cb(JSON.parse(JSON.stringify(res)));
  });
};

var MicroJSGenerator = yeoman.generators.Base.extend({
  init: function () {
    this.pkg = require('../package.json');
    this.currentYear = (new Date()).getFullYear();

    this.on('end', function () {
      if (!this.options['skip-install']) {
        this.installDependencies();
      }
    });
  },

  welcome: function () {

    if (this.options['skip-welcome-message']) {
      return;
    }

    // Have Yeoman greet the user.
    this.log(yosay('Welcome to the marvelous MicroJS generator!'));

  },

  askForUsername: function () {
    var done = this.async();

    var prompts = [{
      name: 'githubUser',
      message: 'Would you mind telling me your username on GitHub?',
      default: (process.env && process.env.USER !== undefined) ? process.env.USER : 'username'
    }];

    this.prompt(prompts, function (props) {
      this.githubUser = props.githubUser;

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

  askForProj: function () {
    var done = this.async();
    var projName = extractProj(this._, this.appname);

    var prompts = [{
      name: 'projName',
      message: 'What\'s the name of your project?',
      default: projName
    }, {
      type: 'confirm',
      name: 'pkgName',
      message: 'The name above already exists on npm, choose another?',
      default: true,
      when: function (answers) {
        var done = this.async();
        var name = answers.projName;

        npmName(name, function (err, available) {
          if (!available) {
            done(true);
          }

          done(false);
        });
      }
    }];

    this.prompt(prompts, function (props) {
      if (props.pkgName) {
        return this.askForProj();
      }

      this.projName = props.projName;
      this.baseFileName = path.basename(this.projName, path.extname(this.projName));
      this.exportName = toCamelCase(this.baseFileName);

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

  askForTaskFramework: function () {
    var done = this.async();

    var prompts = [{
      name: 'taskFramework',
      message: 'What task runner do you want to use?',
      type : 'list',
      choices : [
        { name : 'Gulp', value : 'gulp' },
        { name : 'Grunt', value : 'grunt' }
      ],
      default : 'gulp'
    }];

    this.prompt(prompts, function (props) {
      this.taskFramework = props.taskFramework;

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

  askForTestFramework: function () {
    var done = this.async();

    var prompts = [{
      name: 'testFramework',
      message: 'What test runner do you want to use?',
      type : 'list',
      choices : [
        { name : 'Jasmine', value : 'jasmine' },
        { name : 'Mocha', value : 'mocha' }
      ],
      default : 'jasmine'
    }];

    this.prompt(prompts, function (props) {
      this.testFramework = props.testFramework;

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

  askForLicType: function () {
    var done = this.async();

    var prompts = [{
      type: 'confirm',
      name: 'useMitOrg',
      message: 'Would you like to use mit-license.org?',
      default: true
    }];

    this.prompt(prompts, function (props) {
      this.useMitOrg = props.useMitOrg;

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

  userInfo: function () {
    var done = this.async();

    githubUserInfo(this.githubUser, function (res) {
      /*jshint camelcase:false */
      this.realname = res.name;
      this.email = res.email;
      this.githubUrl = res.html_url;
      done();
    }.bind(this));
  },

  bower: function () {
    this.template('_bower.json', 'bower.json');
  },

  packageJSON: function () {
    this.template('_package.json', 'package.json');
  },

  git: function () {
    this.copy('gitattributes', '.gitattributes');
    this.copy('gitignore', '.gitignore');
  },

  travis: function () {
    this.template('travis.yml', '.travis.yml');
  },

  taskRunner: function () {
    if (this.taskFramework === 'grunt') {
      this.template('_gruntfile.js', 'gruntfile.js');
    } else {
      this.template('_gulpfile.js', 'gulpfile.js');
    }
  },

  projectFiles: function () {
    this.copy('editorconfig', '.editorconfig');
    this.copy('npmignore', '.npmignore');
    this.template('umd', '.umd');

    // only copy over coffee if the option was set
    if (this.options.coffee) {
      this.template('micro-tmpl.coffee', this.baseFileName + '.coffee');
    }
    this.template('micro-tmpl.js', this.baseFileName + '.js');
    this.template('micro-tmpl.min.js', this.baseFileName + '.min.js');
    this.template('README.md', 'README.md');
  },

  testConfig: function () {
    // only copy over coffee if the option was set
    if (this.options.coffee) {
      this.template('test/karma.conf.coffee', 'test/karma.conf.coffee');
    }
    this.template('test/karma.conf.js', 'test/karma.conf.js');
  },

  jshint: function () {
    this.copy('jshintrc', '.jshintrc');
  },

  tests: function () {
    this.mkdir('test/spec');
    // only copy over coffee if the option was set
    if (this.options.coffee) {
      this.template('test/' + this.testFramework + '.spec.coffee', 'test/spec/' + this.baseFileName + '.spec.coffee');
    }
    this.template('test/' + this.testFramework + '.spec.js', 'test/spec/' + this.baseFileName + '.spec.js');
  }
});

module.exports = MicroJSGenerator;