diff --git a/.gitignore b/.gitignore index cae3194..5a2ac84 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ $RECYCLE.BIN/ # App specific node_modules/ +/test/temp-test/ /test/temp/ diff --git a/.travis.yml b/.travis.yml index 3f16ce8..92d91d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - '0.8' - '0.10' before_install: - currentfolder=${PWD##*/} diff --git a/README.md b/README.md index 1406758..e2e46a0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# generator-react-webpack [](https://travis-ci.org/newtriks/generator-react-webpack) [](http://gruntjs.com/) +# generator-react-webpack [](https://travis-ci.org/eddhannay/generator-react-webpack) [](http://gruntjs.com/) > Yeoman generator for [ReactJS](http://facebook.github.io/react/) - lets you quickly set up a project including karma test runner and [Webpack](http://webpack.github.io/) module system. @@ -54,7 +54,7 @@ Example: yo react-webpack:component foo ``` -Produces `src/scripts/components/Foo.js` (*javascript - JSX*): +Produces `src/scripts/components/Foo.jsx` (*javascript - JSX*): ``` /** * @jsx React.DOM @@ -98,6 +98,14 @@ describe('Foo', function () { }); ``` +And `src/styles/Foo.css`: +``` + +.Foo{ + border: 1px dashed #f00; +} +``` + ## Testing Running `grunt test` will run the unit tests with karma. Tests are written using [Jasmine](http://pivotal.github.io/jasmine/) by default. @@ -148,7 +156,7 @@ Each component is a module and can be required using the [Webpack](http://webpac Out the box the [Gruntfile](http://gruntjs.com/api/grunt.file) is configured with the following: 1. **webpack**: uses the [grunt-webpack](https://github.com/webpack/grunt-webpack) plugin to load all required modules and output to a single JS file `src/scripts/main.js`. This is included in the `src/index.html` file by default and will reload in the browser as and when it is recompiled. -2. **watch**: uses the [grunt-watch](https://github.com/gruntjs/grunt-contrib-watch) plugin and watches for file changes. Livereload support is included by default and thus on file change the *webpack* task is run and the browser will auto update. +2. **webpack-dev-server**: uses the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) to watch for file changes and also serve the webpack app in development. 3. **connect**: uses the [grunt-connect](https://github.com/gruntjs/grunt-contrib-connect) plugin to start a webserver at [localhost](http://localhost:8000). 4. **karma**: uses the [grunt-karma](https://github.com/karma-runner/grunt-karma) plugin to load the Karma configuration file `karma.conf.js` located in the project root. This will run all tests using [PhantomJS](http://phantomjs.org/) by default but supports many other browsers. @@ -167,7 +175,3 @@ Contributions are welcomed. When submitting a bugfix, write a test that exposes ## License [BSD license](http://opensource.org/licenses/bsd-license.php) - - -[](https://bitdeli.com/free "Bitdeli Badge") - diff --git a/component/index.js b/component/index.js index a5b6541..5e37c8f 100644 --- a/component/index.js +++ b/component/index.js @@ -12,6 +12,7 @@ ComponentGenerator.prototype.createComponentFile = function createComponentFile( this.generateSourceAndTest( 'Component', 'spec/Component', + 'styles/Component', 'components' ); }; diff --git a/main/index.js b/main/index.js index 96e85c5..fde7d63 100644 --- a/main/index.js +++ b/main/index.js @@ -1,4 +1,5 @@ 'use strict'; + var util = require('util'); var ScriptBase = require('../script-base.js'); @@ -9,5 +10,6 @@ var MainGenerator = module.exports = function MainGenerator(args, options, confi util.inherits(MainGenerator, ScriptBase); MainGenerator.prototype.createAppFile = function createAppFile() { - this.appTemplate('App', 'scripts/components/'+this.scriptAppName); + this.appTemplate('App', 'scripts/components/' + this.scriptAppName); + this.testTemplate('spec/App', 'components/' + this.scriptAppName); }; diff --git a/package.json b/package.json index 6935b2c..2cb43b7 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,7 @@ "yo": ">=1.0.0" }, "engines": { - "node": ">=0.8.0", - "npm": ">=1.2.10" + "node": ">=0.10.0" }, "licenses": [ { diff --git a/script-base.js b/script-base.js index f0510b3..8b4029d 100644 --- a/script-base.js +++ b/script-base.js @@ -8,7 +8,8 @@ var Generator = module.exports = function Generator() { yeoman.generators.NamedBase.apply(this, arguments); // Add capitalize mixin - this._.mixin({ 'capitalize': generalUtils.capitalize }); + this._.mixin({ 'capitalize': generalUtils.capitalize }); + this._.mixin({ 'lowercase': generalUtils.lowercase }); this.appname = path.basename(process.cwd()); @@ -24,8 +25,16 @@ var Generator = module.exports = function Generator() { this.env.options.testPath = this.env.options.testPath || 'test/spec'; } - var sourceRoot = '/templates/javascript'; + if (typeof this.env.options.stylesPath === 'undefined') { + this.env.options.stylesPath = this.env.options.stylesPath || 'src/styles'; + } + + var sourceRoot = '/templates/'; this.scriptSuffix = '.js'; + this.reactSuffix = '.jsx'; + + var stylesRoot = '/templates/styles'; + this.stylesSuffix = '.css'; this.sourceRoot(path.join(__dirname, sourceRoot)); }; @@ -34,8 +43,8 @@ util.inherits(Generator, yeoman.generators.NamedBase); Generator.prototype.appTemplate = function (src, dest) { yeoman.generators.Base.prototype.template.apply(this, [ - src + this.scriptSuffix, - path.join(this.env.options.appPath, dest) + this.scriptSuffix + path.join('javascript', src + this.reactSuffix), + path.join(this.env.options.appPath, dest) + this.reactSuffix ]); }; @@ -46,6 +55,14 @@ Generator.prototype.testTemplate = function (src, dest) { ]); }; +Generator.prototype.stylesTemplate = function (src, dest) { + console.log(src); + yeoman.generators.Base.prototype.template.apply(this, [ + src + this.stylesSuffix, + path.join(this.env.options.stylesPath, dest) + this.stylesSuffix + ]); +}; + Generator.prototype.htmlTemplate = function (src, dest) { yeoman.generators.Base.prototype.template.apply(this, [ src, @@ -53,7 +70,8 @@ Generator.prototype.htmlTemplate = function (src, dest) { ]); }; -Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory) { +Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, stylesTemplate, targetDirectory) { this.appTemplate(appTemplate, path.join('scripts', targetDirectory, this._.capitalize(this.name))); this.testTemplate(testTemplate, path.join(targetDirectory, this._.capitalize(this.name))); + this.stylesTemplate(stylesTemplate, path.join(this._.capitalize(this.name))); }; diff --git a/templates/common/Gruntfile.js b/templates/common/Gruntfile.js index 03ef33d..0840e42 100644 --- a/templates/common/Gruntfile.js +++ b/templates/common/Gruntfile.js @@ -1,101 +1,51 @@ 'use strict'; -var LIVERELOAD_PORT = 35729; -var lrSnippet = require('connect-livereload')({ - port: LIVERELOAD_PORT -}); + var mountFolder = function (connect, dir) { return connect.static(require('path').resolve(dir)); }; +var webpackDistConfig = require('./webpack.dist.config.js'), + webpackDevConfig = require('./webpack.config.js'); + module.exports = function (grunt) { // Let *load-grunt-tasks* require everything require('load-grunt-tasks')(grunt); + // Read configuration from package.json var pkgConfig = grunt.file.readJSON('package.json'); - var jshintConfig = grunt.file.readJSON('.jshintrc'); - - var loaders = [{ - test: /\.css$/, - loader: 'style!css' - }, { - test: /\.gif/, - loader: 'url-loader?limit=10000&minetype=image/gif' - }, { - test: /\.jpg/, - loader: 'url-loader?limit=10000&minetype=image/jpg' - }, { - test: /\.png/, - loader: 'url-loader?limit=10000&minetype=image/png' - }, { - test: /\.js$/, - loader: 'jsx-loader' - }]; - + grunt.initConfig({ pkg: pkgConfig, + webpack: { - development: { - entry: './<%= pkg.src %>/scripts/components/<%= pkg.mainInput %>.js', - output: { - path: '<%= pkg.src %>/scripts/', - filename: '<%= pkg.mainOutput %>.js' - }, - debug: true, - cache: true, - stats: { - colors: true, - reasons: true - }, - jshint: grunt.util._.merge(jshintConfig, { - emitErrors: false, - failOnHint: false - }), - module: { - preLoaders: [{ - test: '\\.js$', - exclude: 'node_modules', - loader: 'jshint' - }], - loaders: loaders - } + options: webpackDistConfig, + + dist: { + cache: false } }, - watch: { - webpack: { - files: ['<%= pkg.src %>/scripts/{,*/}*.js', - '<%= pkg.src %>/styles/{,*/}*.css', - '!<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js' - ], - tasks: ['webpack:development'] - }, - livereload: { - options: { - livereload: LIVERELOAD_PORT - }, - files: [ - '<%= pkg.src %>/{,*/}*.html', - '<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js' - ] - } - }, - connect: { + + 'webpack-dev-server': { options: { port: 8000, - // Change this to '0.0.0.0' to access the server from outside. - hostname: 'localhost' + webpack: webpackDevConfig, + publicPath: '/scripts/', + contentBase: './<%= pkg.src %>/', }, - livereload: { - options: { - middleware: function (connect) { - return [ - lrSnippet, - mountFolder(connect, pkgConfig.src) - ]; - } - } + + start: { + keepAlive: true, + } + }, + + connect: { + options: { + port: 8000 }, + dist: { options: { + keepalive: true, middleware: function (connect) { return [ mountFolder(connect, pkgConfig.dist) @@ -104,34 +54,72 @@ module.exports = function (grunt) { } } }, + open: { - server: { - url: 'http://localhost:<%= connect.options.port %>' + options: { + delay: 500 + }, + dev: { + path: 'http://localhost:<%= connect.options.port %>/webpack-dev-server/' + }, + dist: { + path: 'http://localhost:<%= connect.options.port %>/' } }, + karma: { unit: { configFile: 'karma.conf.js' } + }, + + copy: { + dist: { + files: [ + // includes files within path + { + flatten: true, + expand: true, + src: ['<%= pkg.src %>/*'], + dest: '<%= pkg.dist %>/', + filter: 'isFile' + }, + { + flatten: true, + expand: true, + src: ['<%= pkg.src %>/images/*'], + dest: '<%= pkg.dist %>/images/' + }, + ] + } + }, + + clean: { + dist: { + files: [{ + dot: true, + src: [ + '<%= pkg.dist %>' + ] + }] + } } }); grunt.registerTask('serve', function (target) { if (target === 'dist') { - return grunt.task.run(['build', 'open', 'connect:dist:keepalive']); + return grunt.task.run(['build', 'open:dist', 'connect:dist']); } grunt.task.run([ - 'connect:livereload', - 'webpack:development', - 'open', - 'watch' + 'open:dev', + 'webpack-dev-server' ]); }); grunt.registerTask('test', ['karma']); - grunt.registerTask('build', []); + grunt.registerTask('build', ['clean', 'copy', 'webpack']); grunt.registerTask('default', []); }; diff --git a/templates/common/_package.json b/templates/common/_package.json index 1442665..106ef8f 100644 --- a/templates/common/_package.json +++ b/templates/common/_package.json @@ -11,15 +11,13 @@ }, "devDependencies": { "grunt": "~0.4.4", - "load-grunt-tasks": "~0.2.1", - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-connect": "~0.6.0", - "connect-livereload": "~0.3.1", + "load-grunt-tasks": "~0.4.0", + "grunt-contrib-connect": "~0.7.1", "webpack": "~1.1.2", "jsx-loader": "~0.9.0", "grunt-webpack": "~1.0.0", - "style-loader": "~0.6.0", - "url-loader": "~0.5.2", + "style-loader": "~0.6.3", + "url-loader": "~0.5.4", "css-loader": "~0.6.6", "karma-script-launcher": "~0.1.0", "karma-chrome-launcher": "~0.1.2", @@ -29,8 +27,10 @@ "karma": "~0.10.9", "grunt-karma": "~0.6.2", "karma-webpack-plugin": "~1.0.0", - "webpack-dev-server": "~1.0.2", - "grunt-open": "~0.2.2", - "jshint-loader": "~0.6.0" + "webpack-dev-server": "~1.2.4", + "grunt-open": "~0.2.3", + "jshint-loader": "~0.6.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-clean": "~0.5.0" } } diff --git a/templates/common/gitignore b/templates/common/gitignore index cfb1a09..e6a2bd4 100644 --- a/templates/common/gitignore +++ b/templates/common/gitignore @@ -29,4 +29,5 @@ $RECYCLE.BIN/ node_modules/ .tmp +dist /src/scripts/main.js diff --git a/templates/common/index.html b/templates/common/index.html index 71fa2a1..654d53a 100644 --- a/templates/common/index.html +++ b/templates/common/index.html @@ -12,7 +12,7 @@
You are using an outdated browser. Please upgrade your browser to improve your experience.