From 9867271cbbd4063f4626194b796cdd1b7dba025f Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 14 Jun 2016 10:28:09 +0200 Subject: [PATCH] Refactored component subgenerator to use es2015 classes --- generators/app/postcss.js | 82 ++++++++++++++++++-------- generators/component/index.js | 17 +++--- package.json | 1 + test/generators/app/indexTest.js | 31 +++++----- test/generators/component/indexTest.js | 8 +-- utils/configopts.json | 22 +++---- 6 files changed, 101 insertions(+), 60 deletions(-) diff --git a/generators/app/postcss.js b/generators/app/postcss.js index 9bf2377..2466cc1 100644 --- a/generators/app/postcss.js +++ b/generators/app/postcss.js @@ -1,39 +1,75 @@ 'use strict'; -let fs = require('fs'); -let esprima = require('esprima'); -let walk = require('esprima-walk'); -let escodegen = require('escodegen'); +const fs = require('fs'); +const esprima = require('esprima'); +const walk = require('esprima-walk'); +const escodegen = require('escodegen'); module.exports = { + + /** + * Add postcss support to the given webpack base configuration object + * @param {String} path The config file name + */ write: function(path) { - let baseConfigPath = path; - let cssDialects = ['/\\.css$/', '/\\.sass/', '/\\.scss/', '/\\.less/', '/\\.styl/']; - let postcss = 'var postcss = { postcss: function() { return []; } }'; - postcss = esprima.parse(postcss); - postcss = postcss.body[0].declarations[0].init.properties[0]; + const data = fs.readFileSync(path, 'utf8'); + const ast = esprima.parse(data); - let data = fs.readFileSync(baseConfigPath, 'utf8'); - let parsed = esprima.parse(data); + // List of css dialects we want to add postCSS for + const cssDialects = [ + '/\\.css$/', + '/\\.sass$/', + '/\\.scss$/', + '/\\.less$/', + '/\\.styl$/' + ]; - walk.walkAddParent(parsed, function(node) { - if(node.type === 'AssignmentExpression' && node.left.object.name === 'module') { - node.right.properties.push(postcss); + // Prepare postCSS statement for inclusion + const postcssFunction = 'var postcss = { postcss: function() { return []; } }'; + const postcssAst = esprima.parse(postcssFunction); + const postcss = postcssAst.body[0].declarations[0].init.properties[0]; + + // Add postcss to the loaders array + walk.walkAddParent(ast, (node) => { + + // Add the postcss key to the global configuration + if( + node.type === 'MethodDefinition' && + node.key.name === 'defaultSettings' + ) { + const returnStatement = node.value.body.body[0]; + returnStatement.argument.properties.push(postcss); } - if(node.type === 'Property' && node.key.name === 'test') { - if(cssDialects.indexOf(node.value.raw) > -1) { - let current = node.parent.properties[1].value.value; - let position = current.split('!', 2).join('!').length; - current = [current.slice(0, position), '!postcss-loader', current.slice(position)].join(''); + // Parse all property nodes that use a regex. + // This should only be available under module.(pre)loaders + if( + node.type === 'Property' && + node.key.type === 'Identifier' && + node.key.name === 'test' && + typeof node.value.regex !== 'undefined' + ) { - node.parent.properties[1].value.value = current; + // Make sure we only parse style based items! + if(cssDialects.indexOf(node.value.raw) !== -1) { + + const loaderData = node.parent.properties[1]; + loaderData.value.elements[1].value += '!postcss'; } } }); - let options = { format: { indent: { style: ' ' } } }; - let code = escodegen.generate(parsed, options); - fs.writeFileSync(baseConfigPath, code, 'utf8'); + // Prepare the final code and write it back + const finalCode = escodegen.generate(ast, { + format: { + indent: { + adjustMultilineComment: true, + style: ' ' + } + }, + comment: true + }); + + fs.writeFileSync(path, finalCode, 'utf8'); } } diff --git a/generators/component/index.js b/generators/component/index.js index 05bb33d..42bc6d8 100644 --- a/generators/component/index.js +++ b/generators/component/index.js @@ -1,19 +1,20 @@ 'use strict'; -let generator = require('yeoman-generator'); +const Generators = require('yeoman-generator'); let utils = require('../../utils/all'); -module.exports = generator.Base.extend({ +class ComponentGenerator extends Generators.Base { - constructor: function() { - generator.Base.apply(this, arguments); + constructor(args, options) { + + super(args, options); this.argument('name', { type: String, required: true }); this.option('stateless', { desc: 'Create a stateless component instead of a full one', defaults: false }); - }, + } - writing: function() { + writing() { let settings = utils.yeoman.getAllSettingsFromComponentName(this.name, this.config.get('style')); let componentType = this.options.stateless ? 'Stateless' : 'Base'; @@ -39,4 +40,6 @@ module.exports = generator.Base.extend({ settings ); } -}); +} + +module.exports = ComponentGenerator; diff --git a/package.json b/package.json index e61a87c..2388fdc 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ }, "scripts": { "test": "mocha", + "test:watch": "mocha -w", "release:major": "npm version major && npm publish && git push --follow-tags", "release:minor": "npm version minor && npm publish && git push --follow-tags", "release:patch": "npm version patch && npm publish && git push --follow-tags" diff --git a/test/generators/app/indexTest.js b/test/generators/app/indexTest.js index 37c1a88..bdf9ef2 100644 --- a/test/generators/app/indexTest.js +++ b/test/generators/app/indexTest.js @@ -122,9 +122,12 @@ describe.skip('react-webpack:app with PostCSS support', () => { for(let p of defaultPrompts) { prompts[p.name] = p.default; } - prompts.postcss = true; + before(() => { + return beforeLoad(prompts); + }); + describe('#config', () => { it('should set the generatedWith key to the current generator major version', () => { @@ -163,18 +166,15 @@ describe.skip('react-webpack:app with PostCSS support', () => { it('should generate the webpack configuration', () => { assert.file([ - 'cfg/base.js', - 'cfg/defaults.js', - 'cfg/dev.js', - 'cfg/dist.js', - 'cfg/test.js', - 'server.js', + 'conf/webpack/Base.js', + 'conf/webpack/Dev.js', + 'conf/webpack/Dist.js', + 'conf/webpack/Test.js', 'webpack.config.js' ]); }); it('should insert the postcss loader into the style pipes', () => { - assert.fileContent('cfg/defaults.js', 'loader: \'style-loader!css-loader!postcss-loader\''); assert.fileContent('cfg/defaults.js', 'loader: \'style-loader!css-loader!postcss-loader!sass-loader?outputStyle=expanded&indentedSyntax\''); assert.fileContent('cfg/defaults.js', 'loader: \'style-loader!css-loader!postcss-loader!sass-loader?outputStyle=expanded\''); @@ -182,7 +182,7 @@ describe.skip('react-webpack:app with PostCSS support', () => { assert.fileContent('cfg/defaults.js', 'loader: \'style-loader!css-loader!postcss-loader!stylus-loader\''); }); - it('should append the postcss function to the base config', () => { + it.skip('should append the postcss function to the base config', () => { assert.fileContent('cfg/defaults.js', ',\n postcss: function () {\n return [];\n }'); }); @@ -192,13 +192,13 @@ describe.skip('react-webpack:app with PostCSS support', () => { assert.file([ 'src/actions/README.md', 'src/index.js', - 'src/components/Main.js', + 'src/components/App.js', + 'src/components/app.css', 'src/favicon.ico', 'src/images/yeoman.png', 'src/index.html', 'src/sources/README.md', - 'src/stores/README.md', - 'src/styles/App.css' + 'src/stores/README.md' ]); }); @@ -206,9 +206,10 @@ describe.skip('react-webpack:app with PostCSS support', () => { assert.file([ 'karma.conf.js', - 'test/components/MainTest.js', - 'test/helpers/shallowRenderHelper.js', - 'test/loadtests.js' + 'test/components/AppTest.js', + 'test/config/ConfigTest.js', + 'test/loadtests.js', + 'test/.eslintrc' ]); }); }); diff --git a/test/generators/component/indexTest.js b/test/generators/component/indexTest.js index ef99f63..4749c05 100644 --- a/test/generators/component/indexTest.js +++ b/test/generators/component/indexTest.js @@ -108,7 +108,7 @@ describe('react-webpack:component', () => { it('should always import REACT', (done) => { createGeneratedComponent('mycomponent', style.type, options, () => { - assert.fileContent('src/components/MycomponentComponent.js', `import React from 'react';`); + assert.fileContent('src/components/MycomponentComponent.js', 'import React from \'react\';'); done(); }); }); @@ -122,19 +122,19 @@ describe('react-webpack:component', () => { it('should have its displayName set per default', (done) => { createGeneratedComponent('mycomponent', style.type, options, () => { - assert.fileContent('src/components/MycomponentComponent.js', `displayName = 'MycomponentComponent';`); + assert.fileContent('src/components/MycomponentComponent.js', 'displayName = \'MycomponentComponent\';'); done(); }); }); it('should export the created component', (done) => { createGeneratedComponent('mycomponent', style.type, options, () => { - assert.fileContent('src/components/MycomponentComponent.js', `export default MycomponentComponent`); + assert.fileContent('src/components/MycomponentComponent.js', 'export default MycomponentComponent'); done(); }); }); - it(`should be possible to create components in a subfolder`, (done) => { + it('should be possible to create components in a subfolder', (done) => { createGeneratedComponent('my/little !special/test', style.type, options, () => { assert.file([ diff --git a/utils/configopts.json b/utils/configopts.json index 8d5a0a6..67c9b64 100644 --- a/utils/configopts.json +++ b/utils/configopts.json @@ -45,8 +45,8 @@ "name": "postcss", "value": "postcss", "packages": [ - { "name": "postcss", "version": "^5.0.11" }, - { "name": "postcss-loader", "version": "^0.8.0" } + { "name": "postcss", "version": "^5.0.21" }, + { "name": "postcss-loader", "version": "^0.9.1" } ] } ] @@ -63,8 +63,8 @@ "value": "sass", "suffix": ".sass", "packages": [ - { "name": "sass-loader", "version": "^3.1.2" }, - { "name": "node-sass", "version": "^3.4.2" } + { "name": "sass-loader", "version": "^3.2.0" }, + { "name": "node-sass", "version": "^3.7.0" } ] }, { @@ -72,8 +72,8 @@ "value": "scss", "suffix": ".scss", "packages": [ - { "name": "sass-loader", "version": "^3.1.2" }, - { "name": "node-sass", "version": "^3.4.2" } + { "name": "sass-loader", "version": "^3.2.0" }, + { "name": "node-sass", "version": "^3.7.0" } ] }, { @@ -81,8 +81,8 @@ "value": "less", "suffix": ".less", "packages": [ - { "name": "less-loader", "version": "^2.0.0" }, - { "name": "less", "version": "^2.5.3" } + { "name": "less-loader", "version": "^2.2.3" }, + { "name": "less", "version": "^2.7.1" } ] }, { @@ -90,9 +90,9 @@ "value": "stylus", "suffix": ".styl", "packages": [ - { "name": "stylus-loader", "version": "^0.5.0" }, - { "name": "stylus", "version": "~0.49.2" }, - { "name": "nib", "version": "~1.0.4" } + { "name": "stylus-loader", "version": "^2.1.0" }, + { "name": "stylus", "version": "^0.54.5" }, + { "name": "nib", "version": "~1.1.0" } ] } ],