diff --git a/app/index.js b/app/index.js index 55136f7..94ba957 100644 --- a/app/index.js +++ b/app/index.js @@ -32,7 +32,10 @@ var ReactWebpackGenerator = module.exports = function ReactWebpackGenerator(args this.installDependencies({ skipInstall: options['skip-install'] }); }); + this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json'))); + + this.config.save(); }; util.inherits(ReactWebpackGenerator, yeoman.generators.Base); @@ -60,6 +63,26 @@ ReactWebpackGenerator.prototype.askForReactRouter = function () { }.bind(this)); }; +ReactWebpackGenerator.prototype.askForStylesLanguage = function () { + var done = this.async(); + this.prompt({ + type : 'list', + name : 'stylesLanguage', + message : 'Which styles language you want to use?', + choices: [ + {name: 'CSS', value: 'css'}, + {name: 'SASS', value: 'sass'}, + {name: 'LESS', value: 'less'}, + {name: 'Stylus', value: 'stylus'} + ], + default : 'css' + }, function (props) { + this.env.options.stylesLanguage = props.stylesLanguage; + this.config.set('styles-language', props.stylesLanguage); + done(); + }.bind(this)); +}; + ReactWebpackGenerator.prototype.readIndex = function readIndex() { this.indexFile = this.engine(this.read('../../templates/common/index.html'), this); }; @@ -71,7 +94,10 @@ ReactWebpackGenerator.prototype.createIndexHtml = function createIndexHtml() { ReactWebpackGenerator.prototype.packageFiles = function () { this.reactRouter = this.env.options.reactRouter; + this.stylesLanguage = this.env.options.stylesLanguage; this.template('../../templates/common/_package.json', 'package.json'); + this.template('../../templates/common/_webpack.config.js', 'webpack.config.js'); + this.template('../../templates/common/_webpack.dist.config.js', 'webpack.dist.config.js'); this.copy('../../templates/common/Gruntfile.js', 'Gruntfile.js'); this.copy('../../templates/common/gitignore', '.gitignore'); }; diff --git a/script-base.js b/script-base.js index 6ee2e39..37e4a73 100644 --- a/script-base.js +++ b/script-base.js @@ -19,6 +19,7 @@ var Generator = module.exports = function Generator() { this.scriptAppName = this._.camelize(this._.capitalize(this.appname)) + generalUtils.appName(this); this.classedFileName = this._.capitalizeFile(this.name); this.classedName = this._.capitalizeClass(this.name); + this.stylesLanguage = this.config.get('styles-language'); if (typeof this.options.appPath === 'undefined') { this.options.appPath = this.options.appPath || 'src/scripts'; @@ -38,6 +39,18 @@ var Generator = module.exports = function Generator() { this.stylesSuffix = '.css'; + switch(this.stylesLanguage) { + case 'sass': + this.stylesSuffix = '.sass'; + break; + case 'less': + this.stylesSuffix = '.less'; + break; + case 'stylus': + this.stylesSuffix = '.styl'; + break; + } + this.sourceRoot(path.join(__dirname, sourceRoot)); }; diff --git a/templates/common/_package.json b/templates/common/_package.json index 3b8c387..d17a184 100644 --- a/templates/common/_package.json +++ b/templates/common/_package.json @@ -35,7 +35,10 @@ "grunt-open": "~0.2.3", "jshint-loader": "~0.8.0", "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-clean": "~0.6.0", + "grunt-contrib-clean": "~0.6.0",<% if (stylesLanguage === 'sass') { %> + "sass-loader": "^0.2.0",<% } %><% if (stylesLanguage === 'less') { %> + "less-loader": "^0.7.7",<% } %><% if (stylesLanguage === 'stylus') { %> + "stylus-loader": "^0.4.0",<% } %> "react-hot-loader": "^0.4.5" } } diff --git a/templates/common/root/webpack.config.js b/templates/common/_webpack.config.js similarity index 67% rename from templates/common/root/webpack.config.js rename to templates/common/_webpack.config.js index 4c69e48..8e41144 100644 --- a/templates/common/root/webpack.config.js +++ b/templates/common/_webpack.config.js @@ -20,7 +20,7 @@ module.exports = { devtool: false, entry: [ 'webpack/hot/only-dev-server', - './src/scripts/components/<%= pkg.mainInput %>.jsx' + './src/scripts/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.jsx' ], stats: { @@ -38,11 +38,19 @@ module.exports = { exclude: 'node_modules', loader: 'jshint' }], - loaders: [{ test: /\.jsx$/, loader: 'react-hot!jsx-loader?harmony' - }, { + },<% if (stylesLanguage === 'sass') { %> { + test: /\.sass/, + loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' + },<% } %><% if (stylesLanguage === 'less') { %> { + test: /\.less/, + loader: 'style-loader!css-loader!less-loader' + },<% } %><% if (stylesLanguage === 'stylus') { %> { + test: /\.styl/, + loader: 'style-loader!css-loader!stylus-loader' + },<% } %> { test: /\.css$/, loader: 'style-loader!css-loader' }, { diff --git a/templates/common/root/webpack.dist.config.js b/templates/common/_webpack.dist.config.js similarity index 65% rename from templates/common/root/webpack.dist.config.js rename to templates/common/_webpack.dist.config.js index 287c0be..9a27ac8 100644 --- a/templates/common/root/webpack.dist.config.js +++ b/templates/common/_webpack.dist.config.js @@ -18,7 +18,7 @@ module.exports = { debug: false, devtool: false, - entry: './src/scripts/components/<%= pkg.mainInput %>.jsx', + entry: './src/scripts/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.jsx', stats: { colors: true, @@ -49,7 +49,16 @@ module.exports = { }, { test: /\.css$/, loader: 'style-loader!css-loader' - }, { + },<% if (stylesLanguage === 'sass') { %> { + test: /\.sass/, + loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' + },<% } %><% if (stylesLanguage === 'less') { %> { + test: /\.less/, + loader: 'style-loader!css-loader!less-loader' + },<% } %><% if (stylesLanguage === 'stylus') { %> { + test: /\.styl/, + loader: 'style-loader!stylus-loader!less-loader' + },<% } %> { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }] diff --git a/templates/javascript/Component.jsx b/templates/javascript/Component.jsx index 7ce6a48..ae0869a 100644 --- a/templates/javascript/Component.jsx +++ b/templates/javascript/Component.jsx @@ -5,7 +5,10 @@ 'use strict'; var React = require('react/addons'); -require('../../styles/<%= classedName %>.css'); +<% if (stylesLanguage === 'css') { %>require('../../styles/<%= classedName %>.css');<% } %> +<% if (stylesLanguage === 'sass') { %>require('../../styles/<%= classedName %>.sass');<% } %> +<% if (stylesLanguage === 'less') { %>require('../../styles/<%= classedName %>.less');<% } %> +<% if (stylesLanguage === 'stylus') { %>require('../../styles/<%= classedName %>.styl');<% } %> var <%= classedName %> = React.createClass({ render: function () { diff --git a/templates/styles/Component.less b/templates/styles/Component.less new file mode 100644 index 0000000..2bb362b --- /dev/null +++ b/templates/styles/Component.less @@ -0,0 +1,3 @@ +.<%= classedName %>{ + border: 1px dashed #f00; +} \ No newline at end of file diff --git a/templates/styles/Component.sass b/templates/styles/Component.sass new file mode 100644 index 0000000..9811abb --- /dev/null +++ b/templates/styles/Component.sass @@ -0,0 +1,2 @@ +.<%= classedName %> + border: 1px dashed #f00 diff --git a/templates/styles/Component.styl b/templates/styles/Component.styl new file mode 100644 index 0000000..4cc329f --- /dev/null +++ b/templates/styles/Component.styl @@ -0,0 +1,2 @@ +.<%= classedName %> + border 1px dashed #f00 diff --git a/test/test-creation.js b/test/test-creation.js index b006aa5..dbbfa44 100644 --- a/test/test-creation.js +++ b/test/test-creation.js @@ -48,6 +48,7 @@ describe('react-webpack generator', function() { it('should generate dotfiles', function(done) { react.run({}, function() { helpers.assertFile([].concat(expected, [ + '.yo-rc.json', '.editorconfig', '.gitignore', '.jshintrc' @@ -110,6 +111,46 @@ describe('react-webpack generator', function() { }); + describe('Generator', function () { + + it('should contain info about used style lang', function (done) { + react.run({}, function() { + assert.ok(react.config.get('styles-language')); + done(); + }); + }); + + it('by default should use css style lang', function (done) { + react.run({}, function() { + assert.equal(react.config.get('styles-language'), 'css'); + done(); + }); + }); + + var assertStyle = function (lang, done) { + helpers.mockPrompt(react, { + stylesLanguage: lang + }); + react.run({}, function() { + assert.equal(react.config.get('styles-language'), lang); + done(); + }); + }; + + it('should use sass style lang', function (done) { + assertStyle('sass', done); + }); + + it('should use less style lang', function (done) { + assertStyle('less', done); + }); + + it('should use stylus style lang', function (done) { + assertStyle('stylus', done); + }); + + }); + describe('Subgenerators', function() { var generatorTest = function(generatorType, specType, targetDirectory, scriptNameFn, specNameFn, suffix, done) {