diff --git a/README.md b/README.md index c3cce2ee..475c997e 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ The root directory generated for a app with name `gulpAngular` : * *Unit test (karma)* : out of the box unit test configuration with karma * *e2e test (protractor)* : out of the box e2e test configuration with protractor * *browser sync* : full-featured development web server with livereload and devices sync -* *ngHtml2js* : all HTML partials will be converted to JS to be bundled in the application +* *angular-templatecache* : all HTML partials will be converted to JS to be bundled in the application * **TODO** lazy : don't process files which haven't changed when possible ## Questions the generator will ask @@ -115,10 +115,10 @@ The root directory generated for a app with name `gulpAngular` : * *Angular modules*: animate, cookies, touch, sanitize * *Resource handler*: ngResource, Restangular, none * *Router*: ngRoute, UI Router, none -* *UI Framework*: Bootstrap, Foundation, none (depends on the chosen CSS preprocessor) +* *UI Framework*: Bootstrap, Foundation, Angular Material, none (depends on the chosen CSS preprocessor) * *CSS pre-processor*: Less, Sass with Ruby and Node, Stylus, none -* **TODO** Bootstrap directives : UI Bootstrap, Angular Strap, none (only if you chose Bootstrap) -* **TODO** JS preprocessor: CoffeeScript, TypeScript, ECMAScript6 (Traceur) +* *Bootstrap directives* : UI Bootstrap, Angular Strap, official Bootstrap JavaScript, none (only if you chose Bootstrap) +* **TODO** JS preprocessor: CoffeeScript, TypeScript, ECMAScript6 (Traceur and 6to5) * **TODO** HTML preprocessor: Jade ? * **TODO** Script loader: Require, Browserify, ES6 with Require?, none * **TODO** Test framework: Jasmine, Mocha, Qunit diff --git a/app/index.js b/app/index.js index 6e4f5e71..64befcdc 100644 --- a/app/index.js +++ b/app/index.js @@ -54,11 +54,24 @@ var GulpAngularGenerator = yeoman.generators.Base.extend({ var done = this.async(); + this._.findWhere(prompts, {name: 'bootstrapComponents'}).when = function(props) { + return props.ui.key === 'bootstrap'; + }; + this.prompt(prompts, function (props) { + if(props.ui.key !== 'bootstrap') { + props.bootstrapComponents = { + name: null, + version: null, + key: null, + module: null + }; + } + this.props = props; + done(); }.bind(this)); - }, saveSettings: function() { diff --git a/app/prompts.json b/app/prompts.json index 19772236..d9963f9f 100644 --- a/app/prompts.json +++ b/app/prompts.json @@ -151,13 +151,14 @@ { "type": "list", "name": "ui", - "message": "Which UI framework do you want ?", + "message": "Which UI framework do you want?", "choices": [ { "value": { "name": "bootstrap-sass-official", "version": "3.2.x", - "key": "bootstrap" + "key": "bootstrap", + "module": null }, "name": "Bootstrap, the most popular HTML, CSS, and JS framework" }, @@ -165,20 +166,74 @@ "value": { "name": "foundation", "version": "5.4.x", - "key": "foundation" + "key": "foundation", + "module": null }, - "name": "Foundation, \"The most advanced responsive front-end framework in the world\"" + "name": "Foundation, \"The most advanced responsive front-end framework in the world\"" }, { "value": { + "name": "angular-material", + "version": "0.5.x", + "key": "angular-material", + "module": "ngMaterial" + }, + "name": "Angular Material, the reference implementation of the Google's Material Design specification" + }, + { + "value": { + "key": "none", "name": null, "version": null, - "key": "default" + "module": null }, "name": "None" } ] }, + { + "type": "list", + "name": "bootstrapComponents", + "message": "How do you want to implements your Bootstrap components?", + "choices": [ + { + "value": { + "name": "angular-bootstrap", + "version": "0.12.x", + "key": "ui-bootstrap", + "module": "ui.bootstrap" + }, + "name": "Angular UI Bootstrap, Bootstrap components written in pure AngularJS by the AngularUI Team" + }, + { + "value": { + "name": "angular-strap", + "version": "2.1.x", + "key": "angular-strap", + "module": "mgcrea.ngStrap" + }, + "name": "AngularStrap, AngularJS 1.2+ native directives for Bootstrap 3" + }, + { + "value": { + "name": null, + "version": null, + "key": "official", + "module": null + }, + "name": "The official jQuery implementation of Bootstrap" + }, + { + "value": { + "name": null, + "version": null, + "key": "none", + "module": null + }, + "name": "No JavaScript, just CSS" + } + ] + }, { "type": "list", "name": "cssPreprocessor", diff --git a/app/src/format.js b/app/src/format.js index 653f71de..2adea7b0 100644 --- a/app/src/format.js +++ b/app/src/format.js @@ -16,7 +16,9 @@ module.exports = function () { ngModules = _.flatten([ ngModules, this.props.resource.module, - this.props.router.module + this.props.router.module, + this.props.ui.module, + this.props.bootstrapComponents.module ]); this.modulesDependencies = _.chain(ngModules) @@ -25,8 +27,7 @@ module.exports = function () { return '\'' + dependency + '\''; }) .valueOf() - .join(', ') - ; + .join(', '); // Format list techs used to generate app included in main view of sample var listTechs = require('../techs.json'); @@ -35,30 +36,35 @@ module.exports = function () { 'angular', 'browsersync', 'gulp', 'jasmine', 'karma', 'protractor', this.props.jQuery.name, this.props.ui.key, + this.props.bootstrapComponents.key, this.props.cssPreprocessor.key ] .filter(_.isString) .filter(function(tech) { - return tech !== 'default' && tech !== 'css'; - }) - ; + return tech !== 'default' && tech !== 'css' && tech !== 'official' && tech !== 'none'; + }); var techsContent = _.map(usedTechs, function(value) { return listTechs[value]; }); - this.technologies = JSON.stringify(techsContent, null, 2).replace(/"/g, '\'').replace(/\n/g, '\n '); + this.technologies = JSON.stringify(techsContent, null, 2) + .replace(/'/g, '\\\'') + .replace(/"/g, '\'') + .replace(/\n/g, '\n '); this.technologiesLogoCopies = _.map(usedTechs, function(value) { return 'src/assets/images/' + listTechs[value].logo; }); // Select partials relative to props.ui + var uiFileKey = this.props.ui.key === 'ui-bootstrap' ? 'bootstrap' : this.props.ui.key; + this.partialCopies = {}; - var navbarPartialSrc = 'src/components/navbar/__' + this.props.ui.key + '-navbar.html'; + var navbarPartialSrc = 'src/components/navbar/__' + uiFileKey + '-navbar.html'; this.partialCopies[navbarPartialSrc] = 'src/components/navbar/navbar.html'; - var routerPartialSrc = 'src/app/main/__' + this.props.ui.key + '.html'; + var routerPartialSrc = 'src/app/main/__' + uiFileKey + '.html'; if(this.props.router.module !== null) { this.partialCopies[routerPartialSrc] = 'src/app/main/main.html'; } @@ -81,25 +87,50 @@ module.exports = function () { this.routerJs = ''; } + // Wiredep exclusions + this.wiredepExclusions = []; + if(this.props.bootstrapComponents.key !== 'official') { + if(this.props.cssPreprocessor.extension === 'scss') { + this.wiredepExclusions.push('/bootstrap-sass-official/'); + } else { + this.wiredepExclusions.push('/bootstrap.js/'); + } + } + if(this.props.cssPreprocessor.key !== 'css') { + this.wiredepExclusions.push('/bootstrap.css/'); + } + // Format choice UI Framework - if(this.props.ui.key === 'bootstrap' && this.props.cssPreprocessor.extension !== 'scss') { + if(this.props.ui.key.indexOf('bootstrap') !== -1 && this.props.cssPreprocessor.extension !== 'scss') { this.props.ui.name = 'bootstrap'; } this.styleCopies = {}; - var styleAppSrc = 'src/app/__' + this.props.ui.key + '-index.' + this.props.cssPreprocessor.extension; + var styleAppSrc = 'src/app/__' + uiFileKey + '-index.' + this.props.cssPreprocessor.extension; this.styleCopies[styleAppSrc] = 'src/app/index.' + this.props.cssPreprocessor.extension; - // ## Special case for Foundation and LESS: Foundation dont have a LESS version so we include css - if ((this.props.cssPreprocessor.extension === 'less' && this.props.ui.key === 'foundation') || this.props.cssPreprocessor.extension === 'css' || this.props.cssPreprocessor.extension === 'styl') { - this.isVendorStylesPreprocessed = false; - } else { - this.isVendorStylesPreprocessed = true; + // There is 2 ways of dealing with vendor styles + // - If the vendor styles exist in the css preprocessor chosen, + // the best is to include directly the source files + // - If not, the vendor styles are simply added as standard css links + // + // isVendorStylesPreprocessed defines which solution has to be used + // regarding the ui framework and the css preprocessor chosen. + this.isVendorStylesPreprocessed = false; + + if(this.props.cssPreprocessor.extension === 'scss') { + if(this.props.ui.key === 'bootstrap' || this.props.ui.key === 'foundation') { + this.isVendorStylesPreprocessed = true; + } + } else if(this.props.cssPreprocessor.extension === 'less') { + if(this.props.ui.key === 'bootstrap') { + this.isVendorStylesPreprocessed = true; + } } if(this.isVendorStylesPreprocessed && this.props.ui.name !== null) { - var styleVendorSource = 'src/app/__' + this.props.ui.key + '-vendor.' + this.props.cssPreprocessor.extension; + var styleVendorSource = 'src/app/__' + uiFileKey + '-vendor.' + this.props.cssPreprocessor.extension; this.styleCopies[styleVendorSource] = 'src/app/vendor.' + this.props.cssPreprocessor.extension; } }; diff --git a/app/techs.json b/app/techs.json index f3c5de4e..b3cf4f87 100644 --- a/app/techs.json +++ b/app/techs.json @@ -11,6 +11,24 @@ "description": "Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.", "logo": "bootstrap.png" }, + "ui-bootstrap": { + "title": "Angular UI Bootstrap", + "url": "http://angular-ui.github.io/bootstrap/", + "description": "Bootstrap components written in pure AngularJS by the AngularUI Team.", + "logo": "ui-bootstrap.png" + }, + "angular-strap": { + "title": "Angular Strap", + "url": "http://mgcrea.github.io/angular-strap/", + "description": "AngularJS 1.2+ native directives for Bootstrap 3.", + "logo": "angular-strap.png" + }, + "angular-material": { + "title": "Angular Material Design", + "url": "https://material.angularjs.org/#/", + "description": "The Angular reference implementation of the Google's Material Design specification.", + "logo": "angular-material.png" + }, "browsersync": { "title": "BrowserSync", "url": "http://browsersync.io/", diff --git a/app/templates/_bower.json b/app/templates/_bower.json index a3f20e48..2d6afc73 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -8,8 +8,9 @@ "angular-resource": "<%= props.angularVersion %>",<% } else if (props.resource.name === 'restangular') { %> "restangular": "1.4.x",<% } if (props.router.name === 'angular-route') { %> "angular-route": "<%= props.angularVersion %>",<% } else if (props.router.name === 'angular-ui-router') { %> - "angular-ui-router": "0.2.x",<% } if (props.ui.name !== null) { %> - "<%= props.ui.name %>": "<%= props.ui.version %>",<% } %> + "angular-ui-router": "0.2.x",<% } if(props.ui.name !== null) { %> + "<%= props.ui.name %>": "<%= props.ui.version %>",<% } if(props.bootstrapComponents && props.bootstrapComponents.name !== null) { %> + "<%= props.bootstrapComponents.name %>": "<%= props.bootstrapComponents.version %>",<% } %> "angular": "<%= props.angularVersion %>" }, "devDependencies": { diff --git a/app/templates/gulp/_wiredep.js b/app/templates/gulp/_wiredep.js index 68289591..f9c8d70e 100644 --- a/app/templates/gulp/_wiredep.js +++ b/app/templates/gulp/_wiredep.js @@ -8,8 +8,8 @@ gulp.task('wiredep', function () { return gulp.src('src/index.html') .pipe(wiredep({ - directory: 'bower_components', - exclude: [/bootstrap-sass-official/, /bootstrap.js/<% if(props.cssPreprocessor.key !== 'css') { %>, /bootstrap.css/<% } %>], + directory: 'bower_components'<% if(wiredepExclusions.length > 0) { %>, + exclude: [<%= wiredepExclusions.join(', ') %>]<% } %> })) .pipe(gulp.dest('src')); }); diff --git a/app/templates/src/_index.html b/app/templates/src/_index.html index 07a73d8b..5bcd6fba 100644 --- a/app/templates/src/_index.html +++ b/app/templates/src/_index.html @@ -9,8 +9,7 @@ <% if (props.ui.name !== null) { %> <% if (isVendorStylesPreprocessed) { %> <% } else if (props.ui.key === 'bootstrap') { %> - <% } else if (props.ui.key === 'foundation') { %> - <% } %> + <% } %> diff --git a/app/templates/src/app/__angular-material-index.css b/app/templates/src/app/__angular-material-index.css new file mode 100644 index 00000000..1cfccf9a --- /dev/null +++ b/app/templates/src/app/__angular-material-index.css @@ -0,0 +1,55 @@ +@import url(http://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Roboto:400,700,700italic,400italic); + +html { + font-family: 'Roboto Slab', serif; +} + +[layout=row] { + flex-direction: row; +} + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +.thumbnail { + height: 200px; +} + +.thumbnail img.pull-right { + width: 50px; +} + +md-toolbar.md-default-theme { + background-color: black; +} + +section.jumbotron { + margin-bottom: 30px; + padding: 1px 30px; + background-color: #5aadbb; + text-align: center; + + color: white; +} + +section.jumbotron h1 { + font-size: 3em; +} + +.techs { + display: flex; + flex-flow: row wrap; +} + +.techs md-card { + width: 30%; +} + +.techs md-card img.pull-right { + float: right; + width: 50px; +} diff --git a/app/templates/src/app/__angular-material-index.less b/app/templates/src/app/__angular-material-index.less new file mode 100644 index 00000000..c5d26eaa --- /dev/null +++ b/app/templates/src/app/__angular-material-index.less @@ -0,0 +1,55 @@ +@import url(http://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Roboto:400,700,700italic,400italic); + +html { + font-family: 'Roboto Slab', serif; +} + +[layout=row] { + flex-direction: row; +} + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +.thumbnail { + height: 200px; + + img.pull-right { + width: 50px; + } +} + +md-toolbar.md-default-theme { + background-color: black; +} + +section.jumbotron { + margin-bottom: 30px; + padding: 1px 30px; + background-color: #5aadbb; + text-align: center; + + color: white; + + h1 { + font-size: 3em; + } +} + +.techs { + display: flex; + flex-flow: row wrap; + + md-card { + width: 30%; + + img.pull-right { + float: right; + width: 50px; + } + } +} diff --git a/app/templates/src/app/__angular-material-index.scss b/app/templates/src/app/__angular-material-index.scss new file mode 100644 index 00000000..c5d26eaa --- /dev/null +++ b/app/templates/src/app/__angular-material-index.scss @@ -0,0 +1,55 @@ +@import url(http://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Roboto:400,700,700italic,400italic); + +html { + font-family: 'Roboto Slab', serif; +} + +[layout=row] { + flex-direction: row; +} + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +.thumbnail { + height: 200px; + + img.pull-right { + width: 50px; + } +} + +md-toolbar.md-default-theme { + background-color: black; +} + +section.jumbotron { + margin-bottom: 30px; + padding: 1px 30px; + background-color: #5aadbb; + text-align: center; + + color: white; + + h1 { + font-size: 3em; + } +} + +.techs { + display: flex; + flex-flow: row wrap; + + md-card { + width: 30%; + + img.pull-right { + float: right; + width: 50px; + } + } +} diff --git a/app/templates/src/app/__angular-material-index.styl b/app/templates/src/app/__angular-material-index.styl new file mode 100644 index 00000000..dc4671e3 --- /dev/null +++ b/app/templates/src/app/__angular-material-index.styl @@ -0,0 +1,43 @@ +@import url("http://fonts.googleapis.com/css?family=Roboto\+Slab:400,700|Roboto:400,700,700italic,400italic") + +html + font-family 'Roboto Slab', serif + +[layout=row] + flex-direction row + +.browsehappy + margin 0.2em 0 + background #ccc + color #000 + padding 0.2em 0 + +.thumbnail + height 200px + img + &.pull-right + width 50px + +md-toolbar + &.md-default-theme + background-color black + +section + &.jumbotron + margin-bottom 30px + padding 1px 30px + background-color #5aadbb + text-align center + color white + h1 + font-size 3em + +.techs + display flex + flex-flow row wrap + md-card + width 30% + img + &.pull-right + float right + width 50px diff --git a/app/templates/src/app/main/__angular-material.html b/app/templates/src/app/main/__angular-material.html new file mode 100644 index 00000000..351e1db2 --- /dev/null +++ b/app/templates/src/app/main/__angular-material.html @@ -0,0 +1,35 @@ +
+ 
+ Always a pleasure scaffolding your apps.
+