diff --git a/app/index.js b/app/index.js index 82b02691..37a782e1 100644 --- a/app/index.js +++ b/app/index.js @@ -44,6 +44,7 @@ require('./src/techs')(GulpAngularGenerator); require('./src/ui')(GulpAngularGenerator); require('./src/router')(GulpAngularGenerator); require('./src/preprocessors')(GulpAngularGenerator); +require('./src/bower')(GulpAngularGenerator); require('./src/write')(GulpAngularGenerator); diff --git a/app/src/bower.js b/app/src/bower.js new file mode 100644 index 00000000..ae300945 --- /dev/null +++ b/app/src/bower.js @@ -0,0 +1,76 @@ +'use strict'; + +var _ = require('lodash'); + +module.exports = function(GulpAngularGenerator) { + + /** + * Prepare Bower overrides property to fix external bower.json with missing + * or incomplete main property (needed by wiredep) + */ + GulpAngularGenerator.prototype.prepareBowerOverrides = function prepareBowerOverrides() { + + var bowerOverrides = {}; + + if (this.props.ui.key === 'bootstrap') { + bowerOverrides.bootstrap = { + main: [ + 'dist/fonts/glyphicons-halflings-regular.eot', + 'dist/fonts/glyphicons-halflings-regular.svg', + 'dist/fonts/glyphicons-halflings-regular.ttf', + 'dist/fonts/glyphicons-halflings-regular.woff', + 'dist/fonts/glyphicons-halflings-regular.woff2' + ] + }; + + if (this.props.bootstrapComponents.key === 'official') { + bowerOverrides.bootstrap.main.unshift('dist/js/bootstrap.js'); + } + + if (this.props.cssPreprocessor.key === 'none') { + bowerOverrides.bootstrap.main.unshift('dist/css/bootstrap.css'); + } + + if (this.props.cssPreprocessor.key === 'less') { + bowerOverrides.bootstrap.main.unshift('less/bootstrap.less'); + } + } + + if (_.isEmpty(bowerOverrides)) { + this.bowerOverrides = null; + } else { + this.bowerOverrides = JSON.stringify(bowerOverrides, null, 2) + .replace(/\n/g, '\n '); + } + + }; + + /** + * Compute wiredep exclusions depending on the props + */ + GulpAngularGenerator.prototype.computeWiredepExclusions = function computeWiredepExclusions() { + this.wiredepExclusions = []; + if (this.props.jQuery.key === 'none') { + this.wiredepExclusions.push('/jquery/'); + } + if (this.props.ui.key === 'bootstrap') { + if(this.props.bootstrapComponents.key !== 'official') { + this.wiredepExclusions.push('/bootstrap\.js$/'); + if(this.props.cssPreprocessor.extension === 'scss') { + this.wiredepExclusions.push('/bootstrap-sass-official\\/.*\\.js/'); + } + } + if(this.props.cssPreprocessor.key !== 'none') { + this.wiredepExclusions.push('/bootstrap\\.css/'); + } + } else if (this.props.ui.key === 'foundation') { + if(this.props.foundationComponents.key !== 'official') { + this.wiredepExclusions.push('/foundation\\.js/'); + } + if(this.props.cssPreprocessor.extension === 'scss') { + this.wiredepExclusions.push('/foundation\\.css/'); + } + } + }; + +}; diff --git a/app/src/ui.js b/app/src/ui.js index ac8f7037..10ca7b58 100644 --- a/app/src/ui.js +++ b/app/src/ui.js @@ -40,32 +40,4 @@ module.exports = function(GulpAngularGenerator) { }); }; - /** - * Compute wiredep exclusions depending on the props - */ - GulpAngularGenerator.prototype.computeWiredepExclusions = function computeWiredepExclusions() { - this.wiredepExclusions = []; - if (this.props.jQuery.key === 'none') { - this.wiredepExclusions.push('/jquery/'); - } - if (this.props.ui.key === 'bootstrap') { - if(this.props.bootstrapComponents.key !== 'official') { - this.wiredepExclusions.push('/bootstrap\.js$/'); - if(this.props.cssPreprocessor.extension === 'scss') { - this.wiredepExclusions.push('/bootstrap-sass-official\\/.*\\.js/'); - } - } - if(this.props.cssPreprocessor.key !== 'none') { - this.wiredepExclusions.push('/bootstrap\\.css/'); - } - } else if (this.props.ui.key === 'foundation') { - if(this.props.foundationComponents.key !== 'official') { - this.wiredepExclusions.push('/foundation\\.js/'); - } - if(this.props.cssPreprocessor.extension === 'scss') { - this.wiredepExclusions.push('/foundation\\.css/'); - } - } - }; - }; diff --git a/app/templates/_bower.json b/app/templates/_bower.json index c79a283b..ff38c033 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -56,15 +56,8 @@ "devDependencies": { "angular-mocks": "<%- props.angularVersion %>" }, -<% if (props.cssPreprocessor.key === 'none' && props.ui.key === 'bootstrap') { -%> - "overrides": { - "bootstrap": { - "main": [ - "dist/css/bootstrap.css", - "dist/js/bootstrap.js" - ] - } - }, +<% if (bowerOverrides !== null) { -%> + "overrides": <%- bowerOverrides %>, <% } -%> "resolutions": { <% if (props.jQuery.key === 'jquery1') { -%> diff --git a/test/node/test-bower.js b/test/node/test-bower.js new file mode 100644 index 00000000..75cb39f3 --- /dev/null +++ b/test/node/test-bower.js @@ -0,0 +1,179 @@ +'use strict'; + +var chai = require('chai'); +chai.should(); +var expect = chai.expect; + +var Generator = require('./mock-generator'); +var generator; + +var bower = require('../../app/src/bower.js'); + +describe('gulp-angular generator bower script', function () { + + before(function() { + bower(Generator); + }); + + beforeEach(function() { + generator = new Generator(); + }); + + describe('select bower overrides depending the choices', function () { + function allFonts(array) { + array.forEach(function(line) { + line.should.match(/\.(eot|svg|ttf|woff|woff2)$/); + }); + } + + it('should return null if bootstrap is not selected', function() { + generator.props = { + ui: { key: 'notbootstrap' } + }; + generator.prepareBowerOverrides(); + expect(generator.bowerOverrides).to.be.null; + }); + + it('should add fonts and js for bootstrap and official js', function() { + generator.props = { + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'official' }, + cssPreprocessor: { key: 'something' } + }; + generator.prepareBowerOverrides(); + var bootstrapMain = JSON.parse(generator.bowerOverrides).bootstrap.main; + var first = bootstrapMain.shift(); + first.should.match(/bootstrap\.js/); + allFonts(bootstrapMain); + }); + + it('should add fonts and css for bootstrap and no css prepro', function() { + generator.props = { + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'something' }, + cssPreprocessor: { key: 'none' } + }; + generator.prepareBowerOverrides(); + var bootstrapMain = JSON.parse(generator.bowerOverrides).bootstrap.main; + var first = bootstrapMain.shift(); + first.should.match(/bootstrap\.css/); + allFonts(bootstrapMain); + }); + + it('should add fonts and css for bootstrap and less as css prepro', function() { + generator.props = { + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'something' }, + cssPreprocessor: { key: 'less' } + }; + generator.prepareBowerOverrides(); + var bootstrapMain = JSON.parse(generator.bowerOverrides).bootstrap.main; + var first = bootstrapMain.shift(); + first.should.match(/bootstrap\.less/); + allFonts(bootstrapMain); + }); + + it('should keep indent in bower.json', function() { + generator.props = { + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'something' }, + cssPreprocessor: { key: 'something' } + }; + generator.prepareBowerOverrides(); + generator.bowerOverrides.should.match(/^{.*\n {4}/); + }); + }); + + describe('select wiredep exclusions depending the choices', function () { + it('should exclude bootstrap if angular-boostrap and scss', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'angular-bootstrap' }, + cssPreprocessor: { extension: 'scss' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions[0].should.be.equal('/bootstrap\.js$/'); + generator.wiredepExclusions[1].should.be.equal('/bootstrap-sass-official\\/.*\\.js/'); + generator.wiredepExclusions[2].should.be.equal('/bootstrap\\.css/'); + }); + + it('should exclude only bootstrap.js if angular-boostrap and less', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'angular-bootstrap' }, + cssPreprocessor: { extension: 'less' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions[0].should.be.equal('/bootstrap\.js$/'); + generator.wiredepExclusions[1].should.be.equal('/bootstrap\\.css/'); + }); + + it('should exclude foundation if foundation and sass', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'foundation' }, + foundationComponents: { key: 'angular-foundation' }, + cssPreprocessor: { extension: 'scss' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions[0].should.be.equal('/foundation\\.js/'); + generator.wiredepExclusions[1].should.be.equal('/foundation\\.css/'); + }); + + it('should exclude foundation if foundation and not sass', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'foundation' }, + foundationComponents: { key: 'angular-foundation' }, + cssPreprocessor: { extension: 'notscss' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions[0].should.be.equal('/foundation\\.js/'); + }); + + it('should exclude nothing if no ui', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'none' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions.length.should.be.equal(0); + }); + + it('should exclude nothing if bootstrap but nothing else', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'bootstrap' }, + bootstrapComponents: { key: 'official' }, + cssPreprocessor: { key: 'none' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions.length.should.be.equal(0); + }); + + it('should exclude nothing if foundation but nothing else', function() { + generator.props = { + jQuery: { key: 'jquery1' }, + ui: { key: 'foundation' }, + foundationComponents: { key: 'official' }, + cssPreprocessor: { key: 'none' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions.length.should.be.equal(0); + }); + + it('should exclude jQuery if select "None"', function() { + generator.props = { + jQuery: { key: 'none' }, + ui: { key: 'foundation' }, + foundationComponents: { key: 'official' }, + cssPreprocessor: { key: 'none' } + }; + generator.computeWiredepExclusions(); + generator.wiredepExclusions[0].should.be.equal('/jquery/'); + }); + }); + +}); diff --git a/test/node/test-ui.js b/test/node/test-ui.js index b6422168..2193fda4 100644 --- a/test/node/test-ui.js +++ b/test/node/test-ui.js @@ -51,96 +51,4 @@ describe('gulp-angular generator ui script', function () { }); }); - describe('select wiredep exclusions depending the choices', function () { - it('should exclude bootstrap if angular-boostrap and scss', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'bootstrap' }, - bootstrapComponents: { key: 'angular-bootstrap' }, - cssPreprocessor: { extension: 'scss' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions[0].should.be.equal('/bootstrap\.js$/'); - generator.wiredepExclusions[1].should.be.equal('/bootstrap-sass-official\\/.*\\.js/'); - generator.wiredepExclusions[2].should.be.equal('/bootstrap\\.css/'); - }); - - it('should exclude only bootstrap.js if angular-boostrap and less', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'bootstrap' }, - bootstrapComponents: { key: 'angular-bootstrap' }, - cssPreprocessor: { extension: 'less' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions[0].should.be.equal('/bootstrap\.js$/'); - generator.wiredepExclusions[1].should.be.equal('/bootstrap\\.css/'); - }); - - it('should exclude foundation if foundation and sass', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'foundation' }, - foundationComponents: { key: 'angular-foundation' }, - cssPreprocessor: { extension: 'scss' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions[0].should.be.equal('/foundation\\.js/'); - generator.wiredepExclusions[1].should.be.equal('/foundation\\.css/'); - }); - - it('should exclude foundation if foundation and not sass', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'foundation' }, - foundationComponents: { key: 'angular-foundation' }, - cssPreprocessor: { extension: 'notscss' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions[0].should.be.equal('/foundation\\.js/'); - }); - - it('should exclude nothing if no ui', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'none' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions.length.should.be.equal(0); - }); - - it('should exclude nothing if bootstrap but nothing else', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'bootstrap' }, - bootstrapComponents: { key: 'official' }, - cssPreprocessor: { key: 'none' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions.length.should.be.equal(0); - }); - - it('should exclude nothing if foundation but nothing else', function() { - generator.props = { - jQuery: { key: 'jquery1' }, - ui: { key: 'foundation' }, - foundationComponents: { key: 'official' }, - cssPreprocessor: { key: 'none' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions.length.should.be.equal(0); - }); - - it('should exclude jQuery if select "None"', function() { - generator.props = { - jQuery: { key: 'none' }, - ui: { key: 'foundation' }, - foundationComponents: { key: 'official' }, - cssPreprocessor: { key: 'none' } - }; - generator.computeWiredepExclusions(); - generator.wiredepExclusions[0].should.be.equal('/jquery/'); - }); - }); - }); diff --git a/test/template-tools.js b/test/template-tools.js index 9f4af0e7..f87f9f71 100644 --- a/test/template-tools.js +++ b/test/template-tools.js @@ -94,7 +94,8 @@ function deps() { function processTemplate(buffer) { var data = { appName: 'appName', - props: { angularVersion: angularVersion } + props: { angularVersion: angularVersion }, + bowerOverrides: '{}' }; var string = buffer.toString().replace(/<%[^-].*?%>/g, ''); diff --git a/test/template/mock-model.js b/test/template/mock-model.js index fed504e0..a9f6ec6a 100644 --- a/test/template/mock-model.js +++ b/test/template/mock-model.js @@ -29,6 +29,7 @@ module.exports = function() { processedFileExtension: null, includeModernizr: false, imageMin: false, - qrCode: false + qrCode: false, + bowerOverrides: null }); }; diff --git a/test/template/test-bower.js b/test/template/test-bower.js index 69e802e5..d0c745f6 100644 --- a/test/template/test-bower.js +++ b/test/template/test-bower.js @@ -176,12 +176,14 @@ describe('gulp-angular bower template', function () { result.should.match(/traceur-runtime/); }); - it('should add overrides pprt for css bootstrap', function() { - model.props.ui.key = 'bootstrap'; - model.props.cssPreprocessor.key = 'none'; - + it('should add overrides if needed', function() { + model.bowerOverrides = null; var result = bower(model); - result.should.match(/overrides/); - result.should.match(/dist\/css\/bootstrap.css/); + result.should.not.match(/overrides/); + + model.bowerOverrides = 'test value'; + result = bower(model); + result.should.match(/"overrides": test value,/); }); + });