From 0864743f14603fe346001e73a4f9df25c90e8f2b Mon Sep 17 00:00:00 2001 From: Avi Haiat Date: Mon, 25 Jan 2016 20:06:31 +0200 Subject: [PATCH 1/3] feat(app): Add generator:app --- .eslintrc => .eslintrc.json | 2 +- README.md | 34 +++- generators/app/index.js | 114 +++++++++--- generators/app/templates/.eslintignore | 5 + generators/app/templates/.eslintrc.json | 120 +++++++++++++ generators/app/templates/.gitignore | 68 +++++++ generators/app/templates/.jsbeautifyrc | 43 +++++ generators/app/templates/.npmrc | 1 + generators/app/templates/_README.md | 1 + generators/app/templates/_package.json | 75 ++++++++ generators/app/templates/_spec-bundle.js | 107 +++++++++++ generators/app/templates/_tsconfig.json | 22 +++ generators/app/templates/karma.conf.js | 107 +++++++++++ generators/app/templates/package.json | 10 -- generators/app/templates/tslint.json | 74 ++++++++ generators/app/templates/webpack.config.js | 200 +++++++++++++++++++++ generators/target/index.js | 27 +++ generators/target/templates/dummyfile.txt | 1 + libs/mixinBeautify.js | 4 +- libs/mixinInspector.js | 31 ++++ libs/mixinLodash.js | 4 +- libs/mixinReadFile.js | 6 +- package.json | 4 +- test/mocha/app.spec.js | 104 +++++++++-- test/mocha/component.spec.js | 23 +-- test/mocha/target.spec.js | 29 +++ test/mocha/testHelper.js | 51 ++++++ 27 files changed, 1190 insertions(+), 77 deletions(-) rename .eslintrc => .eslintrc.json (99%) create mode 100644 generators/app/templates/.eslintignore create mode 100644 generators/app/templates/.eslintrc.json create mode 100644 generators/app/templates/.gitignore create mode 100644 generators/app/templates/.jsbeautifyrc create mode 100644 generators/app/templates/.npmrc create mode 100644 generators/app/templates/_README.md create mode 100644 generators/app/templates/_package.json create mode 100644 generators/app/templates/_spec-bundle.js create mode 100644 generators/app/templates/_tsconfig.json create mode 100644 generators/app/templates/karma.conf.js delete mode 100644 generators/app/templates/package.json create mode 100644 generators/app/templates/tslint.json create mode 100644 generators/app/templates/webpack.config.js create mode 100644 generators/target/index.js create mode 100644 generators/target/templates/dummyfile.txt create mode 100644 libs/mixinInspector.js create mode 100644 test/mocha/target.spec.js create mode 100644 test/mocha/testHelper.js diff --git a/.eslintrc b/.eslintrc.json similarity index 99% rename from .eslintrc rename to .eslintrc.json index 2e0075c..5d4ef49 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -37,7 +37,7 @@ "max-nested-callbacks": [0, 2], "max-params": [0, 15], "max-statements": [0, 10], - "new-cap": [2], + "new-cap": [0], "new-parens": 2, "no-alert": 2, "no-array-constructor": 2, diff --git a/README.md b/README.md index e39879a..2eda2d2 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Yeoman has a heart of gold. He's a person with feelings and opinions, but he MIT -## Yeoman stuff -### create directory +## Yeoman notes +### Create directory ```js var mkdirp = require('mkdirp'); mkdirp.sync(this.templatePath('xxx')); @@ -37,6 +37,36 @@ mkdirp.sync(this.templatePath('xxx')); this.fs.write(this.destinationPath('xxx'), content); ``` +### Read scaffolded file in test +```js +var mixinReadFile = require('../../libs/mixinReadFile'); +var utils = {}; +mixinReadFile.extend(utils); +var body = utils.mixins.readTextFile('./package.json'); +``` + +or we can use the testHelper +```js +var testHelper = require('./testHelper'); +var body = testHelper.mixins.readTextFile('./.yo-rc.json'); +``` + +### Test regex on file content +```js + var expectedContents = [ + ['package.json', /"name": "name_x"/], + ['tsconfig.json', new RegExp('\"' + clientFolder + /\/\*\*\/\*\.ts/.source)] +]; + assert.fileContent(expectedContents); +``` + +### Test object on JSON file content +```js +assert.JSONFileContent('package.json', { + name: 'name-x' +}); +``` + [npm-image]: https://badge.fury.io/js/generator-mcfly-ng2.svg [npm-url]: https://npmjs.org/package/generator-mcfly-ng2 [travis-image]: https://travis-ci.org/mcfly-io/generator-mcfly-ng2.svg?branch=master diff --git a/generators/app/index.js b/generators/app/index.js index db9203c..0556a17 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -3,10 +3,12 @@ var generators = require('yeoman-generator'); var chalk = require('chalk'); var yosay = require('yosay'); var path = require('path'); +var mkdirp = require('mkdirp'); var mixinLodash = require('../../libs/mixinLodash'); var mixinBeautify = require('../../libs/mixinBeautify'); var mixinReadFile = require('../../libs/mixinReadFile'); var mixinNotifier = require('../../libs/mixinNotifier'); +var mixinInspector = require('../../libs/mixinInspector'); module.exports = generators.Base.extend({ constructor: function() { @@ -17,6 +19,7 @@ module.exports = generators.Base.extend({ mixinBeautify.extend(this); mixinReadFile.extend(this); mixinNotifier.extend(this); + mixinInspector.extend(this); // Registering file transforms this.mixins.beautifyJson(); @@ -34,14 +37,6 @@ module.exports = generators.Base.extend({ defaults: this.appname }); - this.argument('mobile', { - desc: 'Indicates that the app is a mobile app', - type: Boolean, - optional: true, - required: false, - defaults: false - }); - this.appname = this.mixins.camelize(this.appname); // ***** arguments ******** @@ -52,6 +47,17 @@ module.exports = generators.Base.extend({ type: Boolean, defaults: false }); + this.option('mobile', { + desc: 'Indicates that the app is a mobile app', + type: Boolean, + defaults: false + }); + + this.option('target', { + desc: 'The name of the default target', + type: String, + defaults: 'app' + }); // ****** options ********* }, @@ -59,47 +65,109 @@ module.exports = generators.Base.extend({ initializing: function() { this.pkg = this.mixins.readJsonFile('../../package.json', __dirname); this.mixins.notifyUpdate(this.pkg); - }, - - configuring: function() { + this.composeWith(this.mixins.getGeneratorShortname() + ':target', { + args: [this.options.target] + }); }, prompting: function() { - this.log('prompting'); - var done = this.async(); // Have Yeoman greet the user. - this.log(yosay('Welcome to the awesome ' + chalk.yellow('generator-mcfly-ng2') + ' generator!')); + this.log(yosay('Welcome to the awesome ' + chalk.yellow(this.mixins.getGeneratorFullname()) + ' generator!')); + var done = this.async(); var prompts = [{ type: 'input', name: 'name', - message: 'Your project name', + message: 'What is your project name?', default: this.appname + }, { + type: 'input', + name: 'clientFolder', + message: 'What is your client folder?', + default: 'client' }]; - this.prompt(prompts, function(answers) { this.answers = answers; - // To access answers later use this.answers.someOption; + // To access answers later use this.answers.someAnswer; + this.answers.clientFolder = this.mixins.dasherize(this.answers.clientFolder); done(); }.bind(this)); }, + configuring: function() { + this.config.set('filenameCase', this.filenameCase); + this.config.set('filenameSuffix', this.filenameSuffix); + this.config.set('appname', this.appname); + this.config.set('clientFolder', this.answers.clientFolder); + + }, + writing: function() { - this.log('writing', this.answers.name); + mkdirp.sync(this.destinationPath(this.answers.clientFolder)); + + this.fs.copyTpl( + this.templatePath('.eslintignore'), + this.destinationPath('.eslintignore') + ); + this.fs.copyTpl( + this.templatePath('.eslintrc.json'), + this.destinationPath('.eslintrc.json') + ); + this.fs.copyTpl( + this.templatePath('.gitignore'), + this.destinationPath('.gitignore') + ); this.fs.copyTpl( - this.templatePath('package.json'), + this.templatePath('.jsbeautifyrc'), + this.destinationPath('.jsbeautifyrc') + ); + this.fs.copyTpl( + this.templatePath('.npmrc'), + this.destinationPath('.npmrc') + ); + this.fs.copyTpl( + this.templatePath('_package.json'), this.destinationPath('package.json'), { - appname: this.appname + appname: this.mixins.dasherize(this.appname), + clientFolder: this.answers.clientFolder + } + ); + this.fs.copyTpl( + this.templatePath('_README.md'), + this.destinationPath('README.md'), { + appname: this.mixins.dasherize(this.appname) } ); + this.fs.copyTpl( + this.templatePath('_spec-bundle.js'), + this.destinationPath('spec-bundle.js') + ); + this.fs.copyTpl( + this.templatePath('_tsconfig.json'), + this.destinationPath('tsconfig.json'), { + clientFolder: this.answers.clientFolder + } + ); + this.fs.copyTpl( + this.templatePath('karma.conf.js'), + this.destinationPath('karma.conf.js') + ); + this.fs.copyTpl( + this.templatePath('tslint.json'), + this.destinationPath('tslint.json') + ); + this.fs.copyTpl( + this.templatePath('webpack.config.js'), + this.destinationPath('webpack.config.js') + ); }, conflicts: function() { - this.log('conflicts'); + }, install: function() { @@ -110,6 +178,6 @@ module.exports = generators.Base.extend({ }, end: function() { - this.log('end'); + this.log('Successfull installation, Woot!!!!'); } -}); \ No newline at end of file +}); diff --git a/generators/app/templates/.eslintignore b/generators/app/templates/.eslintignore new file mode 100644 index 0000000..e377fde --- /dev/null +++ b/generators/app/templates/.eslintignore @@ -0,0 +1,5 @@ +node_modules/** +bower_components/** +dist/** +coverage/** +spec-bundle.js \ No newline at end of file diff --git a/generators/app/templates/.eslintrc.json b/generators/app/templates/.eslintrc.json new file mode 100644 index 0000000..c03d0d0 --- /dev/null +++ b/generators/app/templates/.eslintrc.json @@ -0,0 +1,120 @@ +{ + "env": { + "amd": true, + "browser": true, + "mocha": true, + "es6": true, + "jasmine": true, + "node": true + }, + "globals": { + "assert": true, + "browser": true, + "expect": true, + "protractor": true, + "sinon": true, + "xdescribe": true, + "xit": true, + "by": true + }, + "plugins": [ + "nodeca" + ], + "rules": { + "comma-dangle": [2, "never"], + "camelcase": 0, + "complexity": [0, 11], + "consistent-return": 2, + "consistent-this": [1, "that"], + "curly": [2, "all"], + "dot-notation": 2, + "eol-last": 0, + "eqeqeq": [2, "smart"], + "indent": [0, 4, {"SwitchCase": 1}], + "new-cap": 0, + "nodeca/indent": [2, "spaces", 4], + "max-depth": [0, 4], + "max-len": [0, 80, 4], + "max-nested-callbacks": [0, 2], + "max-params": [0, 15], + "max-statements": [0, 10], + "new-parens": 2, + "no-alert": 2, + "no-array-constructor": 2, + "no-caller": 2, + "no-catch-shadow": 2, + "no-cond-assign": 2, + "no-console": 2, + "no-constant-condition": 2, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-dupe-keys": 2, + "no-empty": 0, + "no-empty-character-class": 2, + "no-empty-label": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": 1, + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-invalid-regexp": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": 2, + "no-lone-blocks": 2, + "no-lonely-if": 0, + "no-loop-func": 2, + "no-mixed-spaces-and-tabs": [2, true], + "no-multi-str": 2, + "no-multiple-empty-lines": [2, {"max": 1}], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-nested-ternary": 0, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 0, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 2, + "no-process-exit": 1, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-return-assign": 2, + "no-script-url": 2, + "no-sequences": 2, + "no-shadow": 0, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-sync": 0, + "no-ternary": 0, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-underscore-dangle": 0, + "no-unreachable": 2, + "no-unused-vars": [2, {"args": "none", "vars": "local"}], + "no-use-before-define": 2, + "no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], + "no-with": 2, + "quotes": [2, "single"], + "semi": 2, + "semi-spacing": 2, + "space-after-keywords": [2, "always"], + "space-infix-ops": [2, {"int32Hint": false}], + "strict": [2, "global"], + "use-isnan": 2, + "valid-jsdoc": [2, { "prefer": { "return": "returns" }, "requireReturn": false, "requireParamDescription": true }], + "valid-typeof": 2, + "wrap-iife": [2, "any"], + "yoda": [2, "never", { "exceptRange": true }] + } +} \ No newline at end of file diff --git a/generators/app/templates/.gitignore b/generators/app/templates/.gitignore new file mode 100644 index 0000000..66315d1 --- /dev/null +++ b/generators/app/templates/.gitignore @@ -0,0 +1,68 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage/ +# Reports directory used by tools like protractor +reports/ + +# Build +build/ +dist/ +.tmp +.cache/ + +# Vendor files +node_modules +bower_components +vendor + +# Temp directories +temp/ +test/tmp +test/temp + +# Other temp +.sass-cache +.grunt + +# Shippable directory +shippable/ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Cordova +platforms/ +plugins/ + +# Visual Studio Code +.vscode/ + +# Visual Studio +*.csproj.user +obj/ +*.suo +*.csproj.user +*.DotSettings.user + +# Fuse +.build/ + +# Changelog +CHANGELOG.md \ No newline at end of file diff --git a/generators/app/templates/.jsbeautifyrc b/generators/app/templates/.jsbeautifyrc new file mode 100644 index 0000000..4c930df --- /dev/null +++ b/generators/app/templates/.jsbeautifyrc @@ -0,0 +1,43 @@ +{ + "html": { + "allowed_file_extensions": ["htm", "html", "xhtml", "shtml", "xml", "svg", "ux", "ngux"], + "brace_style": "collapse", + "indent_char": " ", + "indent_handlebars": false, + "indent_inner_html": false, + "indent_scripts": "keep", + "indent_size": 4, + "max_preserve_newlines": 1, + "preserve_newlines": true, + "unformatted": ["a", "sub", "sup", "b", "i", "u", "pre", "javascript", "style"], + "wrap_line_length": 0 + }, + "css": { + "allowed_file_extensions": ["css", "scss", "sass", "less"], + "end_with_newline": false, + "indent_char": " ", + "indent_size": 4, + "selector_separator": " ", + "selector_separator_newline": false + }, + "js": { + "allowed_file_extensions": ["js", "json", "jshintrc", "jsbeautifyrc", "ts"], + "brace_style": "collapse", + "break_chained_methods": false, + "e4x": true, + "eval_code": false, + "indent_char": " ", + "indent_level": 0, + "indent_size": 4, + "indent_with_tabs": false, + "jslint_happy": false, + "keep_array_indentation": false, + "keep_function_indentation": false, + "max_preserve_newlines": 2, + "preserve_newlines": true, + "space_before_conditional": true, + "space_in_paren": false, + "unescape_strings": false, + "wrap_line_length": 0 + } +} \ No newline at end of file diff --git a/generators/app/templates/.npmrc b/generators/app/templates/.npmrc new file mode 100644 index 0000000..b4c7d1d --- /dev/null +++ b/generators/app/templates/.npmrc @@ -0,0 +1 @@ +loglevel=silent \ No newline at end of file diff --git a/generators/app/templates/_README.md b/generators/app/templates/_README.md new file mode 100644 index 0000000..393e401 --- /dev/null +++ b/generators/app/templates/_README.md @@ -0,0 +1 @@ +# <%=appname%> diff --git a/generators/app/templates/_package.json b/generators/app/templates/_package.json new file mode 100644 index 0000000..ec6f55a --- /dev/null +++ b/generators/app/templates/_package.json @@ -0,0 +1,75 @@ +{ + "name": "<%=appname%>", + "version": "0.0.1", + "description": "Starter kit project with angular2 and webpack", + "main": "", + "repository": { + "type": "git", + "url": "" + }, + "scripts": { + "build": "webpack --progress --profile --colors --display-error-details --display-cached", + "watch": "webpack --watch --progress --profile --colors --display-error-details --display-cached", + "clean": "rm -rf dist coverage", + "tslint": "tslint -c tslint.json \"<%=clientFolder%>/**/*.ts\" ", + "eslint": "eslint .", + "lint": "npm run tslint && npm run eslint", + "browsersync": "npm run watch & browser-sync start --server=dist/${TARGET-app}/${MODE-dev} --files=\"dist/${TARGET-app}/${MODE-dev}/*.*\" --port 5000", + "webpack-server": "webpack-dev-server --hot --colors --progress", + "karma": "karma start", + "pretest": "npm run lint", + "test": "npm run karma", + "fuse.preview": "fuse preview", + "fuse.ios": "fuse build --target=iOS --run", + "fuse.android": "fuse build --target=Android --run" + }, + "dependencies": { + "angular2": "2.0.0-beta.0", + "bootstrap": "^3.3.6", + "es6-shim": "^0.33.3", + "jquery": "^2.1.4", + "reflect-metadata": "0.1.2", + "rxjs": "5.0.0-beta.0", + "zone.js": "^0.5.10" + }, + "devDependencies": { + "browser-sync": "^2.10.1", + "css-loader": "^0.23.1", + "es7-reflect-metadata": "^1.4.0", + "eslint": "^1.10.3", + "eslint-plugin-nodeca": "^1.0.3", + "file-loader": "^0.8.5", + "gulp-mux": "^0.2.24", + "html-loader": "^0.4.0", + "html-webpack-plugin": "^1.7.0", + "istanbul-instrumenter-loader": "^0.1.3", + "json-loader": "^0.5.4", + "karma": "^0.13.11", + "karma-chrome-launcher": "^0.2.1", + "karma-coverage": "^0.5.2", + "karma-jasmine": "^0.3.6", + "karma-mocha-reporter": "^1.1.3", + "karma-phantomjs-launcher": "^0.2.1", + "karma-sourcemap-loader": "^0.3.6", + "karma-webpack": "1.7.0", + "ngux-loader": "mcfly-io/ngux-loader", + "node-sass": "^3.4.2", + "phantomjs": "^1.9.18", + "phantomjs-polyfill": "0.0.1", + "raw-loader": "^0.5.1", + "sass-loader": "^3.1.2", + "style-loader": "^0.13.0", + "ts-loader": "^0.7.2", + "tslint": "^3.2.1", + "tslint-eslint-rules": "^1.0.1", + "tslint-loader": "^2.1.0", + "typescript": "^1.7.5", + "url-loader": "^0.5.7", + "webpack": "^1.12.9", + "webpack-dev-server": "^1.14.0", + "yargs": "^3.31.0" + }, + "keywords": [], + "author": "", + "license": "MIT" +} \ No newline at end of file diff --git a/generators/app/templates/_spec-bundle.js b/generators/app/templates/_spec-bundle.js new file mode 100644 index 0000000..a5b167f --- /dev/null +++ b/generators/app/templates/_spec-bundle.js @@ -0,0 +1,107 @@ +// @AngularClass +/* + * When testing with webpack and ES6, we have to do some extra + * things get testing to work right. Because we are gonna write test + * in ES6 to, we have to compile those as well. That's handled in + * karma.conf.js with the karma-webpack plugin. This is the entry + * file for webpack test. Just like webpack will create a bundle.js + * file for our client, when we run test, it well compile and bundle them + * all here! Crazy huh. So we need to do some setup + */ +var clientFolder = require('./.yo-rc.json')['generator-mclfy-ng2'].clientFolder; + +Error.stackTraceLimit = Infinity; +require('phantomjs-polyfill'); +require('es6-promise'); +require('es6-shim'); +require('es7-reflect-metadata/dist/browser'); +require('zone.js/lib/browser/zone-microtask.js'); +require('zone.js/lib/browser/long-stack-trace-zone.js'); +require('zone.js/lib/browser/jasmine-patch.js'); +// these are global EmitHelpers used by compiled typescript +globalPolyfills(); + +require('angular2/testing'); + +/* + Ok, this is kinda crazy. We can use the the context method on + require that webpack created in order to tell webpack + what files we actually want to require or import. + Below, context will be an function/object with file names as keys. + using that regex we are saying look in client/app and find + any file that ends with spec.js and get its path. By passing in true + we say do this recursively +*/ +var testContext = require.context('./test', true, /\.spec\.ts/); +var appContext = require.context('./' + clientFolder, true, /^((?!vendor)(?!bootstrap).)*\.ts/); + +// get all the files, for each file, call the context function +// that will require the file and load it up here. Context will +// loop and require those spec files here +appContext.keys().forEach(appContext); +testContext.keys().forEach(testContext); +// Select BrowserDomAdapter. +// see https://github.com/AngularClass/angular2-webpack-starter/issues/124 +var domAdapter = require('angular2/src/platform/browser/browser_adapter'); +domAdapter.BrowserDomAdapter.makeCurrent(); + + + + +// these are helpers that typescript uses +// I manually added them by opting out of EmitHelpers by noEmitHelpers: false +function globalPolyfills() { + global.__extends = (this && this.__extends) || function(d, b) { + for (var p in b) + if (b.hasOwnProperty(p)) d[p] = b[p]; + var __ = function() { + this.constructor = d; + }; + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + global.__decorate = global.Reflect.decorate; + global.__metadata = global.Reflect.metadata; + + global.__param = (this && this.__param) || function(paramIndex, decorator) { + return function(target, key) { + decorator(target, key, paramIndex); + }; + }; + + global.__awaiter = (this && this.__awaiter) || + function(thisArg, _arguments, Promise, generator) { + return new Promise(function(resolve, reject) { + generator = generator.call(thisArg, _arguments); + + function cast(value) { + return value instanceof Promise && value.constructor === Promise ? + value : new Promise(function(resolve) { + resolve(value); + }); + } + + function onfulfill(value) { + try { + step('next', value); + } catch (e) { + reject(e); + } + } + + function onreject(value) { + try { + step('throw', value); + } catch (e) { + reject(e); + } + } + + function step(verb, value) { + var result = generator[verb](value); + result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject); + } + step('next', void 0); + }); + }; +} \ No newline at end of file diff --git a/generators/app/templates/_tsconfig.json b/generators/app/templates/_tsconfig.json new file mode 100644 index 0000000..0ee9207 --- /dev/null +++ b/generators/app/templates/_tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": true, + "noEmitHelpers": false, + "noImplicitAny": false + }, + "compileOnSave": false, + "buildOnSave": false, + "exclude": [ + "node_modules" + ], + "filesGlob": [ + "<%=clientFolder%>/**/*.ts", + "!./node_modules/**/*.ts" + ] +} \ No newline at end of file diff --git a/generators/app/templates/karma.conf.js b/generators/app/templates/karma.conf.js new file mode 100644 index 0000000..665fa90 --- /dev/null +++ b/generators/app/templates/karma.conf.js @@ -0,0 +1,107 @@ +'use strict'; +var path = require('path'); +var webpackConfig = require('./webpack.config'); + +module.exports = function(config) { + var _config = { + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine'], + + // list of files / patterns to load in the browser + files: [ + // we are building the test environment in ./spec-bundle.js + { + pattern: 'spec-bundle.js', + watched: false + } + ], + + // list of files to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'spec-bundle.js': ['webpack', 'sourcemap'] + }, + + webpack: { + debug: false, + resolve: { + cache: false, + root: __dirname, + extensions: ['', '.ts', '.js', '.json', '.css', '.html', '.scss', '.sass'] + }, + devtool: 'inline-source-map', + module: { + loaders: webpackConfig.module.loaders, + postLoaders: [ + // instrument only testing sources with Istanbul + { + test: /\.(js|ts)$/, + include: path.resolve('client'), + loader: 'istanbul-instrumenter-loader', + exclude: [/\.e2e\.ts$/, /node_modules/, /\.spec\.ts$/] + } + ] + }, + stats: { + colors: true, + reasons: true + }, + noParse: webpackConfig.noParse + }, + coverageReporter: { + dir: 'coverage/unit', + reporters: [{ + type: 'json' + }, { + type: 'text' + }, { + type: 'text-summary' + }, { + type: 'cobertura', + file: 'coverage.xml' + }, { + type: 'lcov' + }] + }, + webpackServer: { + noInfo: true //please don't spam the console when running in karma! + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha', 'coverage'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }; + + config.set(_config); + +}; \ No newline at end of file diff --git a/generators/app/templates/package.json b/generators/app/templates/package.json deleted file mode 100644 index d67e84d..0000000 --- a/generators/app/templates/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "<%=appname%>", - "version": "0.0.1", - - "scripts": { - "eslint": "eslint .", - "mocha": " istanbul cover --root ./generators --include-all-sources --dir ./coverage/mocha --report text --report text-summary --report lcov --print none _mocha -- test/mocha/**/*.spec.js -R spec", - "test": "npm run eslint && npm run mocha" - } -} \ No newline at end of file diff --git a/generators/app/templates/tslint.json b/generators/app/templates/tslint.json new file mode 100644 index 0000000..b9e1d57 --- /dev/null +++ b/generators/app/templates/tslint.json @@ -0,0 +1,74 @@ +{ + "rulesDirectory": "node_modules/tslint-eslint-rules/dist/rules", + "rules": { + "no-irregular-whitespace": true, + + "class-name": true, + "curly": true, + "eofline": false, + "indent": "spaces", + "max-line-length": [ + true, + 1000 + ], + "member-ordering": [ + true, + "public-before-private", + "static-before-instance", + "variables-before-functions" + ], + "no-arg": true, + "no-consecutive-blank-lines": true, + "no-console": true, + "no-construct": true, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": true, + "no-eval": true, + "no-inferrable-types": true, + "no-internal-module": true, + "no-shadowed-variable": true, + "no-trailing-comma": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-unreachable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": true, + "triple-equals": [ + true, + "allow-null-check" + ], + "use-strict": [ + true, + "check-module" + ], + "variable-name": [ + true, + "check-format", + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} \ No newline at end of file diff --git a/generators/app/templates/webpack.config.js b/generators/app/templates/webpack.config.js new file mode 100644 index 0000000..3d00e94 --- /dev/null +++ b/generators/app/templates/webpack.config.js @@ -0,0 +1,200 @@ +'use strict'; +var path = require('path'); +var webpack = require('webpack'); +var gulpMux = require('gulp-mux'); +var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; +var HtmlwebpackPlugin = require('html-webpack-plugin'); + +var target = process.env.TARGET || 'app'; +var port = process.env.PORT || 5000; +var host = process.env.HOST || 'localhost'; +var mode = process.env.MODE || 'dev'; +var clientFolder = require('./.yo-rc.json')['generator-mcfly-ng2'].clientFolder; +var distFolder = path.join('dist', target, mode); +var suffix = gulpMux.targets.targetToSuffix(target); + +var pluginsProd = mode === 'prod' ? [ + //new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin({ + minimize: true, + mangle: true, + output: { + comments: false + }, + compress: { + warnings: false + } + }) +] : []; + +module.exports = { + devtool: 'source-map', //'eval-source-map', + debug: true, + cache: true, + context: path.resolve(path.join(clientFolder, 'scripts', target)), // the base directory for resolving the entry option + entry: { + 'vendor': './vendor', // clientFolder + '/scripts/' + target + '/vendor', // path.resolve(path.join('.', clientFolder, 'scripts', target, 'vendor')), + 'bundle': './bootstrap' //clientFolder + '/scripts/' + target + '/bootstrap', // path.resolve(path.join('.', clientFolder, 'scripts', target, 'bootstrap')) + }, + + output: { + path: path.resolve(distFolder), + + filename: '[name].js', + sourceMapFilename: '[name].js.map', + chunkFilename: '[id].chunk.js', + devtoolModuleFilenameTemplate: function(info) { + //return 'scripts/app' + info.resourcePath.replace(__dirname, '../..').replace(/~/g, '/node_modules/'); + //return info.resourcePath.replace(clientFolder + '/' + 'scripts', '').replace(/~/g, '/node_modules/'); + }, + devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]' + }, + + resolve: { + extensions: ['', '.ts', '.js', '.json', '.css', '.html', '.scss', '.sass'] + }, + + module: { + preLoaders: [{ + test: /\.ts$/, + loader: 'tslint-loader' + }], + loaders: [{ + test: /\.ts$/, + loader: 'ts', + exclude: [/\.(e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/] + }, + // Support for ngux files + { + test: /\.ngux$/, + loader: 'html-loader!ngux-loader' + }, + // Support for *.json files. + { + test: /\.json$/, + loader: 'json-loader' + }, + // Support for CSS as raw text in client folder + { + test: /\.css$/, + loader: 'css-loader', + include: [new RegExp(clientFolder)] + }, + // Support for CSS as injected style in node_module folder + { + test: /\.css$/, + loader: 'style-loader!css-loader', + include: [/node_modules/] + }, + // Support for SCSS as raw text in client folder + { + test: /\.scss$/, + loader: 'css-loader!sass-loader?sourceMap', + cacheable: true, + include: [new RegExp(clientFolder)] + }, + // Support for SCSS as inject style in node_module folder + { + test: /\.scss$/, + loader: 'style-loader!css-loader!sass-loader?sourceMap', + cacheable: true, + include: [/node_modules/] + }, + // Support for SCSS as raw text in client folder + { + test: /\.sass$/, + // Passing indentedSyntax query param to node-sass + loader: 'css-loader!sass-loader?indentedSyntax&sourceMap', + cacheable: true, + include: [new RegExp(clientFolder)] + }, + // Support for SCSS as inject style in node_module folder + { + test: /\.sass$/, + // Passing indentedSyntax query param to node-sass + loader: 'style-loader!css-loader!sass-loader?indentedSyntax&sourceMap', + cacheable: true, + include: [/node_modules/] + }, + // support for .html as raw text + { + test: /\.html$/, + loader: 'html-loader' + }, { + test: /\.png$/, + loader: 'url-loader?name=images/[hash].[ext]&prefix=img/&limit=5000' + }, { + test: /\.jpg$/, + loader: 'url-loader?name=images/[hash].[ext]&prefix=img/&limit=5000' + }, { + test: /\.gif$/, + loader: 'url-loader?name=images/[hash].[ext]&prefix=img/&limit=5000' + }, { + test: /\.woff$/, + loader: 'url-loader?name=fonts/[hash].[ext]&prefix=font/&limit=5000' + }, { + test: /\.woff2$/, + loader: 'url-loader?name=fonts/[hash].[ext]&prefix=font/&limit=5000' + }, { + test: /\.eot$/, + loader: 'file-loader?name=fonts/[hash].[ext]&prefix=font/' + }, { + test: /\.ttf$/, + loader: 'file-loader?name=fonts/[hash].[ext]&prefix=font/' + }, { + test: /\.svg$/, + loader: 'file-loader?name=fonts/[hash].[ext]&prefix=font/' + } + ], + //noParse: [/.+zone\.js\/dist\/.+/, /.+angular2\/bundles\/.+/] + noParse: [ + /zone\.js\/dist\/zone-microtask\.js/, + /zone\.js\/dist\/long-stack-trace-zone\.js/, + /zone\.js\/dist\/jasmine-patch\.js/, + /es6-shim/, + /reflect-metadata/, + /web-animations/, + /.+angular2\/bundles\/.+/ + ] + }, + tslint: { + emitErrors: false, + failOnHint: false + }, + devServer: { + historyApiFallback: true, + hot: true, + inline: true, + progress: true, + // Display only errors to reduce the amount of output. + stats: 'errors-only', + // Parse host and port from env so this is easy to customize. + host: host, + port: port + }, + plugins: [ + // make sure we can import the chunks on node or fuse + new webpack.BannerPlugin( + 'if (typeof window === "undefined") {window = global;}\n' + + 'if (typeof window["webpackJsonp"]) {webpackJsonp = window.webpackJsonp;}\n', { + raw: true, + entryOnly: true + }), + new CommonsChunkPlugin({ + name: 'vendor', + filename: 'vendor.js', + minChunks: Infinity + }), + new CommonsChunkPlugin({ + name: 'common', + filename: 'common.js', + minChunks: 2, + chunks: ['bundle', 'vendor'] + }), + new HtmlwebpackPlugin({ + title: 'App - ' + target, + template: clientFolder + '/index' + suffix + '.html', + inject: 'body' + }) + ].concat(pluginsProd) +}; diff --git a/generators/target/index.js b/generators/target/index.js new file mode 100644 index 0000000..ef333a8 --- /dev/null +++ b/generators/target/index.js @@ -0,0 +1,27 @@ +'use strict'; +var generators = require('yeoman-generator'); +var path = require('path'); + +module.exports = generators.Base.extend({ + + constructor: function() { + generators.Base.apply(this, arguments); + + //******* arguments *********** + // To access arguments later use this.argumentName + this.argument('targetname', { + desc: 'The target name', + type: String, + optional: false, + required: true + }); + // ***** arguments ******** + }, + + writing: function() { + this.fs.copy( + this.templatePath('dummyfile.txt'), + this.destinationPath(path.join(this.targetname, 'dummyfile.txt')) + ); + } +}); diff --git a/generators/target/templates/dummyfile.txt b/generators/target/templates/dummyfile.txt new file mode 100644 index 0000000..d04a57d --- /dev/null +++ b/generators/target/templates/dummyfile.txt @@ -0,0 +1 @@ +this is a file from target \ No newline at end of file diff --git a/libs/mixinBeautify.js b/libs/mixinBeautify.js index 8ef1101..e5173bf 100644 --- a/libs/mixinBeautify.js +++ b/libs/mixinBeautify.js @@ -4,7 +4,7 @@ var filter = require('gulp-filter'); var prettifyJs = require('gulp-js-prettify'); var utils = {}; require('./mixinReadFile').extend(utils); -var beautifConfig = utils.mixins.readJsonFile('../.jsbeautifyrc'); +var beautifConfig = utils.mixins.readJsonFile('../.jsbeautifyrc', __dirname); /** * Beautify a json stream @@ -113,4 +113,4 @@ module.exports = { mixins.beautifyHtml = beautifyHtml.bind(generator); mixins.beautifyCss = beautifyCss.bind(generator); } -}; \ No newline at end of file +}; diff --git a/libs/mixinInspector.js b/libs/mixinInspector.js new file mode 100644 index 0000000..44f3b2a --- /dev/null +++ b/libs/mixinInspector.js @@ -0,0 +1,31 @@ +'use strict'; + +/** + * Returns this generator full name so we can change it in package.json without altering the code + * @returns {String} The generator full name + */ +var getGeneratorFullname = function() { + var pkg = require('../package.json'); + return pkg.name; +}; + +/** + * Returns this generator short name (without generator) so we can change it in package.json without altering the code + * @returns {String} The generator short name + */ +var getGeneratorShortname = function() { + var pkg = require('../package.json'); + return pkg.name.replace('generator-', ''); +}; +/** + * The exported object + * To apply the mixin execute: this.mixins.extend(generator); + * @type {Object} + */ +module.exports = { + extend: function(generator) { + var mixins = generator.mixins = generator.mixins || {}; + mixins.getGeneratorFullname = getGeneratorFullname.bind(generator); + mixins.getGeneratorShortname = getGeneratorShortname.bind(generator); + } +}; diff --git a/libs/mixinLodash.js b/libs/mixinLodash.js index 203a937..3f6ec78 100644 --- a/libs/mixinLodash.js +++ b/libs/mixinLodash.js @@ -6,7 +6,7 @@ var _ = require('lodash'); * @returns {String} - The camelized string */ var camelize = function(str) { - return _.camelCase(_.snakeCase(str)); + return _.camelCase(str); }; /** @@ -15,7 +15,7 @@ var camelize = function(str) { * @returns {String} - The dasherized string */ var dasherize = function(str) { - return _.snakeCase(camelize(str)); + return _.kebabCase(str); }; /** diff --git a/libs/mixinReadFile.js b/libs/mixinReadFile.js index 688b93e..dee929f 100644 --- a/libs/mixinReadFile.js +++ b/libs/mixinReadFile.js @@ -10,8 +10,8 @@ var stripJsonComments = require('strip-json-comments'); * @returns {String} The file content as a string */ var readTextFile = function(filename, dirname) { - if (!path.isAbsolute(filename)) { - dirname = dirname || __dirname; + // when dirname is null or undefined we read from local path, otherwise we read from absolute path + if (dirname && !path.isAbsolute(filename)) { filename = path.resolve(path.join(dirname, filename)); } var body = fs.readFileSync(filename, 'utf-8'); @@ -35,4 +35,4 @@ module.exports = { mixins.readTextFile = readTextFile.bind(generator); mixins.readJsonFile = readJsonFile.bind(generator); } -}; \ No newline at end of file +}; diff --git a/package.json b/package.json index 452aaa6..5f03c25 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ }, "scripts": { "eslint": "eslint .", - "mocha": " istanbul cover --root ./generators --include-all-sources -x **/templates/** --dir ./coverage/mocha --report text --report text-summary --report lcov --print none _mocha -- test/mocha/**/*.spec.js -R spec --timeout 5000", + "mocha": "istanbul cover --root ./generators --include-all-sources -x **/templates/** --dir ./coverage/mocha --report text --report text-summary --report lcov --print none _mocha -- test/mocha/**/*.spec.js --reporter spec --timeout 10000", + "mocha.watch": "mocha test/mocha/**/*.spec.js -R nyan -w --timeout 10000", "pretest": "npm run eslint", "test": "npm run mocha" }, @@ -40,6 +41,7 @@ "gulp-filter": "^3.0.1", "gulp-js-prettify": "^0.1.0", "lodash": "^4.0.0", + "mkdirp": "^0.5.1", "npm": "^3.5.3", "strip-json-comments": "^2.0.0", "update-notifier": "^0.6.0", diff --git a/test/mocha/app.spec.js b/test/mocha/app.spec.js index 5a497b1..a2be3a1 100644 --- a/test/mocha/app.spec.js +++ b/test/mocha/app.spec.js @@ -1,26 +1,92 @@ 'use strict'; -var path = require('path'); var assert = require('yeoman-assert'); -var helpers = require('yeoman-test'); - -describe('generator-mcfly-ng2:app', function() { - before(function(done) { - helpers.run(path.join(__dirname, '../../generators/app')) - .withOptions({ - someOption: true - }) - .withArguments(['name-x']) - .withPrompts({ - someAnswer: true - }) - .on('end', done); +var testHelper = require('./testHelper'); + +var generatorFullname = testHelper.mixins.getGeneratorFullname(); // generator-mcfly-ng2 +var generatorShortname = testHelper.mixins.getGeneratorShortname(); // mcfly-ng2 + +describe(generatorShortname + ':app', function() { + + var appname = 'Name x'; + var clientFolder = 'myclientfolder'; + + describe('with option mobile false', function() { + before(function(done) { + testHelper.runGenerator('app', null, [generatorShortname + ':target']) + .withArguments([appname]) + .withPrompts({ + clientFolder: clientFolder + }) + .on('end', done); + }); + + it('creates expected files', function() { + var expectedFiles = [ + '.eslintignore', + '.eslintrc.json', + '.gitignore', + '.jsbeautifyrc', + '.npmrc', + '.yo-rc.json', + 'karma.conf.js', + 'package.json', + 'README.md', + 'spec-bundle.js', + 'tsconfig.json', + 'tslint.json', + 'webpack.config.js', + clientFolder + ]; + assert.file(expectedFiles); + assert.JSONFileContent('package.json', { + name: 'name-x' + }); + assert.JSONFileContent('tsconfig.json', { + filesGlob: [ + clientFolder + '/**/*.ts', + '!./node_modules/**/*.ts' + ] + }); + + var expectedContents = [ + ['README.md', /# name-x/] + ]; + assert.fileContent(expectedContents); + }); + + it('creates a .yo-rc.json file', function() { + var content = {}; + content[generatorFullname] = { + appname: appname, + clientFolder: clientFolder + }; + assert.JSONFileContent('.yo-rc.json', content); + + }); + }); + + describe('with option mobile true', function() { + }); - it('creates files', function() { - assert.file([ - 'package.json' - ]); + describe('clientFolder', function() { + before(function(done) { + testHelper.runGenerator('app', null, [generatorShortname + ':target']) + .withArguments([appname]) + .withPrompts({ + clientFolder: 'Dummy Folder' + }) + .on('end', done); + }); + it('should be transformed to snake case', function() { + var content = {}; + content[generatorFullname] = { + appname: appname, + clientFolder: 'dummy-folder' + }; + assert.JSONFileContent('.yo-rc.json', content); + }); }); -}); \ No newline at end of file +}); diff --git a/test/mocha/component.spec.js b/test/mocha/component.spec.js index 1c2a3f9..eeb8566 100644 --- a/test/mocha/component.spec.js +++ b/test/mocha/component.spec.js @@ -1,23 +1,18 @@ 'use strict'; -var path = require('path'); var assert = require('yeoman-assert'); -var helpers = require('yeoman-test'); - -describe('generator-mcfly-ng2:component', function() { +//var helpers = require('yeoman-test'); +var testHelper = require('./testHelper'); +describe('generator:component', function() { before(function(done) { - helpers.run(path.join(__dirname, '../../generators/component')) - .withOptions({ - someOption: true - }) - .withPrompts({ - someAnswer: true - }) + testHelper.runGenerator('component') .on('end', done); }); - it('creates files', function() { - assert.file([ + it('creates expected files', function() { + var expectedFiles = [ 'dummyfile.txt' - ]); + ]; + assert.file(expectedFiles); + }); }); diff --git a/test/mocha/target.spec.js b/test/mocha/target.spec.js new file mode 100644 index 0000000..1907adc --- /dev/null +++ b/test/mocha/target.spec.js @@ -0,0 +1,29 @@ +'use strict'; +var path = require('path'); +var assert = require('yeoman-assert'); +//var helpers = require('yeoman-test'); +var testHelper = require('./testHelper'); + +describe('generator:target', function() { + var targetname = 'dashboard'; + + before(function(done) { + + testHelper.runGenerator('target') + .withArguments([targetname]) + .on('end', done); + }); + + it('creates expected files', function() { + var expectedContents = [ + [path.join(targetname, 'dummyfile.txt'), /this is a file from target/] + ]; + var expectedFiles = [ + path.join(targetname, 'dummyfile.txt') + ]; + assert.file(expectedFiles); + assert.fileContent(expectedContents); + + }); + +}); diff --git a/test/mocha/testHelper.js b/test/mocha/testHelper.js new file mode 100644 index 0000000..7a86f02 --- /dev/null +++ b/test/mocha/testHelper.js @@ -0,0 +1,51 @@ +'use strict'; +var helpers = require('yeoman-test'); +var _ = require('lodash'); +var fs = require('fs'); +var path = require('path'); +var mixinReadFile = require('../../libs/mixinReadFile'); +var mixinInspector = require('../../libs/mixinInspector'); +var utils = {}; +mixinReadFile.extend(utils); +mixinInspector.extend(utils); + +/** + * Get a .yo-rc.json content + * @param {object} config - A config object to apply + * @returns {Object} The json configuration object + */ +var getYoRc = function(config) { + config = config || {}; + var result = {}; + _.defaultsDeep(config, { + appname: 'dummyappname' + }); + result[this.mixins.getGeneratorFullname()] = config; + return result; +}; + +/** + * Run a generator + * @param {String} name - The name of the generator + * @param {Object} config - The config yo-rc object + * @param {String[]} subs - An optional array of sub generators names + * @returns {RunContext} - runContext + */ +var runGenerator = function(name, config, subs) { + var deps = _.map(subs, function(sub) { + return [helpers.createDummyGenerator(), sub]; + }); + var runGen = helpers + .run(path.join(__dirname, '../../generators/' + name)) + .inTmpDir(function(dir) { + fs.writeFileSync('.yo-rc.json', config ? JSON.stringify(config) : '{}'); + }) + .withGenerators(deps); + return runGen; +}; + +module.exports = { + mixins: utils.mixins, + runGenerator: runGenerator, + getYoRc: getYoRc +}; From 388ba84f2efd8c7b6ed9518250c305caef8a676e Mon Sep 17 00:00:00 2001 From: Avi Haiat Date: Mon, 25 Jan 2016 20:41:40 +0200 Subject: [PATCH 2/3] feat(app): Add gulp task for releasing --- README.md | 7 + gulp_tasks/common/changelog-script.js | 215 +++++++++++++++++++++++ gulp_tasks/common/constants.js | 41 +++++ gulp_tasks/common/helper.js | 77 ++++++++ gulp_tasks/tasks/changelog.js | 31 ++++ gulp_tasks/tasks/release.js | 243 ++++++++++++++++++++++++++ gulpfile.js | 14 ++ package.json | 21 +++ 8 files changed, 649 insertions(+) create mode 100644 gulp_tasks/common/changelog-script.js create mode 100644 gulp_tasks/common/constants.js create mode 100644 gulp_tasks/common/helper.js create mode 100644 gulp_tasks/tasks/changelog.js create mode 100644 gulp_tasks/tasks/release.js create mode 100644 gulpfile.js diff --git a/README.md b/README.md index 2eda2d2..991374e 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ Then generate your new project: yo mcfly-ng2 ``` +## Testing +```sh +npm run test # lint + unit tests +npm run mocha # to run without linting first +npm run mocha.watch # to run in watch mode +``` + ## Getting To Know Yeoman Yeoman has a heart of gold. He's a person with feelings and opinions, but he's very easy to work with. If you think he's too opinionated, he can be easily convinced. Feel free to [learn more about him](http://yeoman.io/). diff --git a/gulp_tasks/common/changelog-script.js b/gulp_tasks/common/changelog-script.js new file mode 100644 index 0000000..8e15819 --- /dev/null +++ b/gulp_tasks/common/changelog-script.js @@ -0,0 +1,215 @@ +#!/usr/bin/env node + +'use strict'; +global.Promise = require('bluebird'); +var child = require('child_process'); +var fs = require('fs'); +var util = require('util'); +var gutil = require('gulp-util'); +var constants = require('./constants')(); + +var GIT_LOG_CMD = 'git log --grep="%s" -E --format=%s %s..HEAD'; +var GIT_TAG_CMD = 'git describe --tags --abbrev=0'; + +var HEADER_TPL = '\n# %s (%s)\n\n'; +var LINK_ISSUE = '[#%s](' + constants.repository + '/issues/%s)'; +var LINK_COMMIT = '[%s](' + constants.repository + '/commit/%s)'; + +var EMPTY_COMPONENT = '$$'; + +var warn = function() { + gutil.log('WARNING:', util.format.apply(null, arguments)); +}; + +var parseRawCommit = function(raw) { + if (!raw) { + return null; + } + + var lines = raw.split('\n'); + var msg = {}; + var match; + + msg.hash = lines.shift(); + msg.subject = lines.shift(); + msg.closes = []; + msg.breaks = []; + + lines.forEach(function(line) { + match = line.match(/(?:Closes|Fixes)\s#(\d+)/); + if (match) { + msg.closes.push(parseInt(match[1], 10)); + } + }); + + match = raw.match(/BREAKING CHANGE:([\s\S]*)/); + if (match) { + msg.breaking = match[1]; + } + + msg.body = lines.join('\n'); + match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/); + + if (!match || !match[1] || !match[3]) { + warn('Incorrect message: %s %s', msg.hash, msg.subject); + return null; + } + + msg.type = match[1]; + msg.component = match[2]; + msg.subject = match[3]; + + return msg; +}; + +var linkToIssue = function(issue) { + return util.format(LINK_ISSUE, issue, issue); +}; + +var linkToCommit = function(hash) { + return util.format(LINK_COMMIT, hash.substr(0, 8), hash); +}; + +var currentDate = function() { + var now = new Date(); + var pad = function(i) { + var retval = ('0' + i).substr(-2); + return retval; + }; + + return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())); +}; + +var printSection = function(stream, title, section, printCommitLinks) { + printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks; + var components = Object.getOwnPropertyNames(section).sort(); + + if (!components.length) { + return; + } + + stream.write(util.format('\n### %s\n\n', title)); + + components.forEach(function(name) { + var prefix = '-'; + var nested = section[name].length > 1; + + if (name !== EMPTY_COMPONENT) { + if (nested) { + stream.write(util.format('- **%s:**\n', name)); + prefix = ' -'; + } else { + prefix = util.format('- **%s:**', name); + } + } + + section[name].forEach(function(commit) { + if (printCommitLinks) { + stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash))); + if (commit.closes.length) { + stream.write(',\n ' + commit.closes.map(linkToIssue).join(', ')); + } + stream.write(')\n'); + } else { + stream.write(util.format('%s %s\n', prefix, commit.subject)); + } + }); + }); + + stream.write('\n'); +}; + +var readGitLog = function(grep, from) { + return new Promise(function(resolve, reject) { + child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(error, stdout) { + + if (error) { + reject(error); + } else { + + var commits = []; + + stdout.split('\n==END==\n').forEach(function(rawCommit) { + var commit = parseRawCommit(rawCommit); + if (commit) { + commits.push(commit); + } + }); + + resolve(commits); + } + }); + + }); +}; + +var writeChangelog = function(stream, commits, version) { + var sections = { + fix: {}, + feat: {}, + perf: {}, + breaks: {} + }; + + //sections.breaks[EMPTY_COMPONENT] = []; + + commits.forEach(function(commit) { + var section = sections[commit.type]; + var component = commit.component || EMPTY_COMPONENT; + + if (section) { + section[component] = section[component] || []; + section[component].push(commit); + } + + if (commit.breaking) { + sections.breaks[component] = sections.breaks[component] || []; + sections.breaks[component].push({ + subject: util.format('due to %s,\n %s', linkToCommit(commit.hash), commit.breaking), + hash: commit.hash, + closes: [] + }); + } + }); + + stream.write(util.format(HEADER_TPL, version, version, currentDate())); + printSection(stream, 'Bug Fixes', sections.fix); + printSection(stream, 'Features', sections.feat); + printSection(stream, 'Performance Improvements', sections.perf); + printSection(stream, 'Breaking Changes', sections.breaks, false); +}; + +var getPreviousTag = function() { + return new Promise(function(resolve, reject) { + child.exec(GIT_TAG_CMD, function(error, stdout) { + if (error) { + reject('Cannot get the previous tag.'); + } else { + resolve(stdout.replace('\n', '')); + } + }); + }); +}; + +var generate = function(version, from, file) { + + getPreviousTag().then(function(tag) { + //console.log('Reading git log since', tag); + if (from) { + tag = from; + } + readGitLog('^fix|^feat|^perf|BREAKING', tag).then(function(commits) { + //console.log('Parsed', commits.length, 'commits'); + //console.log('Generating changelog to', file || 'stdout', '(', version, ')'); + writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version); + }); + }); +}; + +// publish for testing +exports.parseRawCommit = parseRawCommit; + +// hacky start if not run by jasmine :-D +if (process.argv.join('').indexOf('jasmine-node') === -1) { + generate(process.argv[2], process.argv[3], process.argv[4]); +} diff --git a/gulp_tasks/common/constants.js b/gulp_tasks/common/constants.js new file mode 100644 index 0000000..a35fc46 --- /dev/null +++ b/gulp_tasks/common/constants.js @@ -0,0 +1,41 @@ +'use strict'; + +var getRepository = function() { + var repository = 'https://github.com/mcfly-io/generator-mcfly-ng2'; + try { + var helper = require('./helper'); + var packageJson = helper.readJsonFile('./package.json'); + var _ = require('lodash'); + if (_.isString(packageJson.repository)) { + repository = packageJson.repository.replace('.git', ''); + } else { + repository = packageJson.repository.url.replace('.git', ''); + } + } catch (err) {} + return repository; +}; + +var getAppname = function() { + var appname; + try { + var helper = require('./helper'); + var packageJson = helper.readJsonFile('./package.json'); + appname = packageJson.name; + } catch (err) {} + return appname; +}; + +module.exports = function() { + var cwd = process.env.INIT_CWD || ''; + var clientFolder = 'client'; // the source file folder + var constants = { + cwd: cwd, + maxBuffer: 1024 * 500, + appname: getAppname(), + clientFolder: clientFolder, + repository: getRepository(), + versionFiles: ['./package.json', './bower.json', './' + clientFolder + '/config*.xml'] + }; + + return constants; +}; diff --git a/gulp_tasks/common/helper.js b/gulp_tasks/common/helper.js new file mode 100644 index 0000000..7edb182 --- /dev/null +++ b/gulp_tasks/common/helper.js @@ -0,0 +1,77 @@ +/*eslint new-cap:0*/ +'use strict'; + +global.Promise = require('bluebird'); + +var fs = require('fs'); +var gutil = require('gulp-util'); +var chalk = require('chalk'); +var stripJsonComments = require('strip-json-comments'); +var _ = require('lodash'); +var path = require('path'); + +/** + * A generic handler for require('child_process').exec + * @param {Object} err - The error object + * @param {String} stdout - The stdout string + * @param {String} stderr - The stderr string + * @param {Object} [opts] - The optional options object + * @param {Boolean} [opts.throwOnError=false] - Ask execHandler to throw + * @param {Boolean} [opts.stderrIsNotError=false] - Don't treat stderr as error info. + */ +var execHandler = function(err, stdout, stderr, opts) { + opts = opts || {}; + if (stdout) { + gutil.log(stdout); + } + if (stderr) { + if (opts.stderrIsNotError) { + gutil.log(stderr); + } else { + gutil.log(chalk.red('Error: ') + stderr); + } + } + if (err) { + gutil.log(chalk.red('An error occured executing a command line action')); + gutil.log(chalk.red(err)); + if (opts.throwOnErr) { + throw err; + } + } +}; + +var readTextFile = function(filename) { + var body = fs.readFileSync(filename, 'utf8'); + return body; +}; + +var readJsonFile = function(filename) { + var body = readTextFile(filename); + return JSON.parse(stripJsonComments(body)); +}; + +var writeTextFile = function(filename, body) { + fs.writeFileSync(filename, body); +}; + +var writeJsonFile = function(filename, json) { + var body = JSON.stringify(json); + writeTextFile(filename, body); +}; + +var filterFiles = function(files, extension) { + return _.filter(files, function(file) { + return path.extname(file) === extension; + }); +}; + +module.exports = { + + execHandler: execHandler, + readTextFile: readTextFile, + readJsonFile: readJsonFile, + writeTextFile: writeTextFile, + writeJsonFile: writeJsonFile, + filterFiles: filterFiles + +}; diff --git a/gulp_tasks/tasks/changelog.js b/gulp_tasks/tasks/changelog.js new file mode 100644 index 0000000..f212ed4 --- /dev/null +++ b/gulp_tasks/tasks/changelog.js @@ -0,0 +1,31 @@ +'use strict'; +global.Promise = require('bluebird'); +var gulp = require('gulp'); +var argv = require('yargs').argv; +var exec = require('gulp-exec'); +var concat = require('gulp-concat'); +var order = require('gulp-order'); +var helper = require('../common/helper'); + +var constants = require('../common/constants')(); + +gulp.task('changelog:script', false, function(done) { + var pkg = helper.readJsonFile('./package.json'); + var options = argv; + var version = options.version || pkg.version; + var from = options.from || ''; + + gulp.src('') + .pipe(exec('node ./gulp_tasks/common/changelog-script.js ' + version + ' ' + from, { + pipeStdout: true, + maxBuffer: constants.maxBuffer + })) + .pipe(concat('updates.md')) + .pipe(helper.addSrc('CHANGELOG.md')) + .pipe(order(['updates.md', 'CHANGELOG.md'])) + .pipe(concat('CHANGELOG.md')) + .pipe(gulp.dest('./')) + .on('end', done); +}); + +gulp.task('changelog', 'Generates a CHANGELOG.md file.', ['changelog:script']); diff --git a/gulp_tasks/tasks/release.js b/gulp_tasks/tasks/release.js new file mode 100644 index 0000000..21911bc --- /dev/null +++ b/gulp_tasks/tasks/release.js @@ -0,0 +1,243 @@ +'use strict'; +global.Promise = require('bluebird'); +// var _ = require('lodash'); +// var path = require('path'); +var gulp = require('gulp'); +var args = require('yargs').argv; +var exec = require('child_process').exec; +// var fs = require('fs'); +// var stripJsonComments = require('strip-json-comments'); +var bump = require('gulp-bump'); +var tap = require('gulp-tap'); +var XML = require('node-jsxml').XML; +var git = require('gulp-git'); +var gulpif = require('gulp-if'); +var gutil = require('gulp-util'); +var GitHubApi = require('github'); +var runSequence = require('run-sequence').use(gulp); +var del = require('del'); +var inquirer = require('inquirer'); +var githubUsername = require('github-username'); +var helper = require('../common/helper'); +var constants = require('../common/constants')(); + +/** + * Bumps any version in the constants.versionFiles + * + * USAGE: + * gulp bump --minor (or --major or --prerelease or --patch which is the default) + * - or - + * gulp bump --ver=1.2.3 + * @param {function} cb - The gulp callback + */ +gulp.task('bump', false, function(cb) { + var bumpType = 'patch'; + // major.minor.patch + if (args.patch) { + bumpType = 'patch'; + } + if (args.minor) { + bumpType = 'minor'; + } + if (args.major) { + bumpType = 'major'; + } + if (args.prerelease) { + bumpType = 'prerelease'; + } + bumpType = process.env.BUMP || bumpType; + + var version; + var srcjson = helper.filterFiles(constants.versionFiles, '.json'); + var srcxml = helper.filterFiles(constants.versionFiles, '.xml'); + + // first we bump the json files + gulp.src(srcjson) + .pipe(gulpif(args.ver !== undefined, bump({ + version: args.ver + }), bump({ + type: bumpType + }))) + .pipe(tap(function(file) { + if (!version) { + var json = JSON.parse(String(file.contents)); + version = json.version; + } + })) + .pipe(gulp.dest('./')) + .on('end', function() { + // then after we have the correct value for version, we take care of the xml files + if (srcxml.length > 0) { + gulp.src(srcxml) + .pipe(tap(function(file) { + var xml = new XML(String(file.contents)); + xml.attribute('version').setValue(version); + file.contents = Buffer.concat([new Buffer(xml.toXMLString())]); + })) + .pipe(gulp.dest('./' + constants.clientFolder)) + .on('end', function() { + cb(); + }); + } else { + cb(); + } + + }); + +}); + +gulp.task('commit', false, ['bump'], function() { + var pkg = helper.readJsonFile('./package.json'); + var message = 'docs(changelog): version ' + pkg.version; + return gulp.src(constants.versionFiles) + .pipe(git.add({ + args: '.' + })) + .pipe(git.commit(message)); +}); + +gulp.task('tag', false, ['commit'], function(cb) { + var pkg = helper.readJsonFile('./package.json'); + var v = 'v' + pkg.version; + var message = pkg.version; + git.tag(v, message, function(err) { + if (err) { + throw new Error(err); + } + cb(); + }); +}); + +gulp.task('push', false, ['tag'], function(cb) { + exec('git push origin master && git push origin master --tags', { + maxBuffer: constants.maxBuffer + }, function(err) { + if (err) { + throw new Error(err); + } + cb(); + }); +}); + +// gulp.task('npm', ['push'], function(done) { +// spawm('npm', ['publish'], { +// stdio: 'inherit' +// }).on('close', done); +// }); + +gulp.task('release', 'Publish a new release version.', ['push']); + +// ############GITHUB SECTION######### + +var github = new GitHubApi({ + version: '3.0.0', + protocol: 'https', + timeout: 0 +}); + +var gitGetEmailAsync = Promise.promisify(git.exec.bind({ + args: 'config --get user.email', + quiet: true +})); + +var githubUsernameAsync = Promise.promisify(githubUsername); + +var inquireAsync = function(result) { + return new Promise(function(resolve, reject) { + + inquirer.prompt(result.questions, function(answers) { + // only resolving what we need + resolve({ + username: answers.username || result.username, + password: answers.password + }); + }); + }); +}; + +var githubAuthSetupAndTestAsync = function(result) { + return new Promise(function(resolve, reject) { + github.authenticate({ + type: 'basic', + username: result.username, + password: result.password + }); + github.misc.rateLimit({}, function(err, res) { + if (err) { + reject(gutil.colors.red('GitHub auth failed! ') + 'Response from server: ' + gutil.colors.yellow(err.message)); + } + resolve(gutil.colors.green('GitHub auth successful!')); + }); + }); +}; + +gulp.task('githubAuth', false, function(cb) { + return gitGetEmailAsync() + .then(githubUsernameAsync) + .catch(function() { + //gutil.log(gutil.colors.red('Username not found')); + return null; + }) + .then(function(username) { + return { + username: username, + questions: [{ + type: 'input', + message: 'Please enter your GitHub username', + name: 'username', + default: username, + validate: function(input) { + return input !== ''; + }, + when: function() { + return username === null; + } + }, { + type: 'password', + message: 'Please enter your GitHub password', + name: 'password', + validate: function(input) { + return input !== ''; + } + }] + }; + }) + .then(inquireAsync) + .then(githubAuthSetupAndTestAsync) + .tap(gutil.log); +}); + +gulp.task('release:createRelease', false, function(cb) { + var pkg = helper.readJsonFile('./package.json'); + var v = 'v' + pkg.version; + var message = pkg.version; + var ownerRepo = constants.repository.split('/').slice(-2); + + return gulp.src('CHANGELOG.md') + .pipe(tap(function(file) { + var body = file.contents.toString(); + body = body.slice(body.indexOf('###')); + var msg = { + owner: ownerRepo[0], + repo: ownerRepo[1], + tag_name: v, + name: v + ': version ' + message, + body: body + }; + github.releases.createRelease(msg, function(err, res) { + if (err) { + gutil.log(gutil.colors.red('Error: ' + err)); + } else { + del('CHANGELOG.md'); + } + }); + })); +}); + +gulp.task('delay', false, function(cb) { + setTimeout(cb, 1000); +}); + +gulp.task('release:full', 'Publish a new release version on GitHub and upload a changelog.', function() { + return runSequence('githubAuth', 'changelog', 'push', 'delay', 'release:createRelease'); +}); diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..bcdc9c1 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,14 @@ +'use strict'; +var gulp = require('gulp'); +global.options = null; +require('gulp-help')(gulp, { + hideDepsMessage: true +}); +require('require-dir')('./gulp_tasks/tasks'); + +// Because we are including gulp-help the syntax of a gulp task has an extra description param at position 2 - refer to https://www.npmjs.org/package/gulp-help + +// add your top gulp tasks here +gulp.task('default', false, function() { + +}); diff --git a/package.json b/package.json index 5f03c25..3362cec 100644 --- a/package.json +++ b/package.json @@ -49,10 +49,31 @@ "yosay": "^1.1.0" }, "devDependencies": { + "bluebird": "^3.1.4", + "chalk": "1.1.1", "coveralls": "^2.11.6", + "del": "^2.2.0", "eslint-plugin-nodeca": "^1.0.3", + "github": "0.2.4", + "github-username": "2.1.0", + "gulp": "3.9.0", + "gulp-bump": "1.0.0", + "gulp-concat": "2.6.0", + "gulp-exec": "2.1.2", + "gulp-git": "^1.6.1", + "gulp-help": "1.6.1", + "gulp-if": "2.0.0", + "gulp-mux": "0.2.24", + "gulp-order": "1.1.1", + "gulp-tap": "0.1.3", + "gulp-util": "3.0.7", "istanbul": "^0.4.2", + "lodash": "4.0.1", "mocha": "^2.3.4", + "require-dir": "0.3.0", + "run-sequence": "^1.1.5", + "strip-json-comments": "2.0.0", + "yargs": "^3.32.0", "yeoman-assert": "^2.1.1", "yeoman-test": "^1.0.0" } From 9434eb931c0868e17a52c003f9ba61d0cc899988 Mon Sep 17 00:00:00 2001 From: Avi Haiat Date: Mon, 25 Jan 2016 20:50:49 +0200 Subject: [PATCH 3/3] feat(app): Add npm key to publish to travis --- .eslintrc.json | 2 +- .travis.yml | 19 ++++++++++++++++--- README.md | 10 ++++++---- generators/app/index.js | 9 ++++----- libs/mixinBeautify.js | 2 +- libs/{mixinReadFile.js => mixinFile.js} | 2 ++ package.json | 5 +++-- test/mocha/testHelper.js | 4 ++-- 8 files changed, 35 insertions(+), 18 deletions(-) rename libs/{mixinReadFile.js => mixinFile.js} (95%) diff --git a/.eslintrc.json b/.eslintrc.json index 5d4ef49..ee4af81 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -30,7 +30,7 @@ "dot-notation": 2, "eol-last": 0, "eqeqeq": [2, "smart"], - "indent": [0, 4, {"SwitchCase": 1}], + "indent": [0, 1, {"SwitchCase": 1}], "nodeca/indent": [2, "spaces", 4 ], "max-depth": [0, 4], "max-len": [0, 80, 4], diff --git a/.travis.yml b/.travis.yml index a5e065e..e136118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,24 @@ node_js: - v4 - '0.12' +env: + global: + secure: ACshkxhxRWLhktp4pgSkdM3PDh9+/JaMt/Mm8Bf70Nl9WCQLwqS7peuVPn3A3bX52UfaIuvIZ2T9PSIsO59V7nXTSVBZmfBdcK1Sg5IuL4A+FTtWN+G30CS7yPhQHuiyMf7j3rtpcUMCrQZrmSBpVbU1bUvNIyCGPa71PrLOoa9Is64HygIfZtwhfxbCeHGH9c7BshKGXyNaMAPXhcnEZbe6mrDsd44EwyP6Iw42maKfcjKEELug/cXhX8cnsJhNEsvQhmLdP+mqAKQPNsds8Ww+8WUqetQNeczYK/etkMDCVskEzdmh+NQFbwi0XtA8C8aeCithmvM722FdjXRrMhOrBP+AKvHOAW2YEWt9wsO49x3PkobbxGyUD6vsfkwI/mjWxgQBYzGiXzspPAQRrtOw3KH56RVuCoVJD6D1p3g8UKOc3GQUqaALKD7mDeldbAZcFRUMRGn+VUAbIiCg9DvneKPolyapwCaVa2CCUkTRDFgoB/aGV97KAnHVjyZfWdldc5j+yHKYyG4XuzSvxWxQHA9q9dMyg36evQNz5Qtu96+CemT/u/CIYUzity98qWvVfdoRDYp19VZme6ipHwpcS7poM0LeJgKLhdp0W35Y/qBxWqwXRTdlJbERdiU4NSnXYWIW7eLEB5XKFkg9IwNMsai/8Nm78We5aWfbNz8= + cache: - directories: - - node_modules - - bower_components + directories: + - node_modules + - bower_components after_success: - cat ./coverage/mocha/lcov.info | ./node_modules/coveralls/bin/coveralls.js --verbose +deploy: + provider: npm + email: thaiat@ipelia.com + api_key: $NPM_API_KEY + on: + tags: true + all_branches: true + node: '0.12' + repo: mcfly-io/generator-mcfly-ng2 diff --git a/README.md b/README.md index 991374e..88d530b 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,10 @@ MIT ## Yeoman notes ### Create directory ```js -var mkdirp = require('mkdirp'); -mkdirp.sync(this.templatePath('xxx')); +var mixinFile = require('../../libs/mixinFile'); +var utils = {}; +mixinFile.extend(utils); +var body = utils.mixins.mkdirp.sync(this.destinationPath('path_to_create')); ``` ### Write file from string @@ -46,9 +48,9 @@ this.fs.write(this.destinationPath('xxx'), content); ### Read scaffolded file in test ```js -var mixinReadFile = require('../../libs/mixinReadFile'); +var mixinFile = require('../../libs/mixinFile'); var utils = {}; -mixinReadFile.extend(utils); +mixinFile.extend(utils); var body = utils.mixins.readTextFile('./package.json'); ``` diff --git a/generators/app/index.js b/generators/app/index.js index 0556a17..85a1483 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -3,10 +3,9 @@ var generators = require('yeoman-generator'); var chalk = require('chalk'); var yosay = require('yosay'); var path = require('path'); -var mkdirp = require('mkdirp'); var mixinLodash = require('../../libs/mixinLodash'); var mixinBeautify = require('../../libs/mixinBeautify'); -var mixinReadFile = require('../../libs/mixinReadFile'); +var mixinFile = require('../../libs/mixinFile'); var mixinNotifier = require('../../libs/mixinNotifier'); var mixinInspector = require('../../libs/mixinInspector'); @@ -17,7 +16,7 @@ module.exports = generators.Base.extend({ // applying mixins mixinLodash.extend(this); mixinBeautify.extend(this); - mixinReadFile.extend(this); + mixinFile.extend(this); mixinNotifier.extend(this); mixinInspector.extend(this); @@ -106,7 +105,7 @@ module.exports = generators.Base.extend({ writing: function() { - mkdirp.sync(this.destinationPath(this.answers.clientFolder)); + this.mixins.mkdirp.sync(this.destinationPath(this.answers.clientFolder)); this.fs.copyTpl( this.templatePath('.eslintignore'), @@ -178,6 +177,6 @@ module.exports = generators.Base.extend({ }, end: function() { - this.log('Successfull installation, Woot!!!!'); + this.log(chalk.green('Woot!!! It appears that everything installed correctly.')); } }); diff --git a/libs/mixinBeautify.js b/libs/mixinBeautify.js index e5173bf..288ad65 100644 --- a/libs/mixinBeautify.js +++ b/libs/mixinBeautify.js @@ -3,7 +3,7 @@ var filter = require('gulp-filter'); var prettifyJs = require('gulp-js-prettify'); var utils = {}; -require('./mixinReadFile').extend(utils); +require('./mixinFile').extend(utils); var beautifConfig = utils.mixins.readJsonFile('../.jsbeautifyrc', __dirname); /** diff --git a/libs/mixinReadFile.js b/libs/mixinFile.js similarity index 95% rename from libs/mixinReadFile.js rename to libs/mixinFile.js index dee929f..d64e4c3 100644 --- a/libs/mixinReadFile.js +++ b/libs/mixinFile.js @@ -1,5 +1,6 @@ 'use strict'; var fs = require('fs'); +var mkdirp = require('mkdirp'); var path = require('path'); var stripJsonComments = require('strip-json-comments'); @@ -34,5 +35,6 @@ module.exports = { var mixins = generator.mixins = generator.mixins || {}; mixins.readTextFile = readTextFile.bind(generator); mixins.readJsonFile = readJsonFile.bind(generator); + mixins.mkdirp = mkdirp; } }; diff --git a/package.json b/package.json index 3362cec..d6e506a 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "scripts": { "eslint": "eslint .", + "lint": "npm run eslint", "mocha": "istanbul cover --root ./generators --include-all-sources -x **/templates/** --dir ./coverage/mocha --report text --report text-summary --report lcov --print none _mocha -- test/mocha/**/*.spec.js --reporter spec --timeout 10000", "mocha.watch": "mocha test/mocha/**/*.spec.js -R nyan -w --timeout 10000", "pretest": "npm run eslint", @@ -40,7 +41,7 @@ "chalk": "^1.1.1", "gulp-filter": "^3.0.1", "gulp-js-prettify": "^0.1.0", - "lodash": "^4.0.0", + "lodash": "3.10.1", "mkdirp": "^0.5.1", "npm": "^3.5.3", "strip-json-comments": "^2.0.0", @@ -53,6 +54,7 @@ "chalk": "1.1.1", "coveralls": "^2.11.6", "del": "^2.2.0", + "eslint": "^1.10.3", "eslint-plugin-nodeca": "^1.0.3", "github": "0.2.4", "github-username": "2.1.0", @@ -68,7 +70,6 @@ "gulp-tap": "0.1.3", "gulp-util": "3.0.7", "istanbul": "^0.4.2", - "lodash": "4.0.1", "mocha": "^2.3.4", "require-dir": "0.3.0", "run-sequence": "^1.1.5", diff --git a/test/mocha/testHelper.js b/test/mocha/testHelper.js index 7a86f02..7734376 100644 --- a/test/mocha/testHelper.js +++ b/test/mocha/testHelper.js @@ -3,10 +3,10 @@ var helpers = require('yeoman-test'); var _ = require('lodash'); var fs = require('fs'); var path = require('path'); -var mixinReadFile = require('../../libs/mixinReadFile'); +var mixinFile = require('../../libs/mixinFile'); var mixinInspector = require('../../libs/mixinInspector'); var utils = {}; -mixinReadFile.extend(utils); +mixinFile.extend(utils); mixinInspector.extend(utils); /**