├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── .yo-rc.json ├── README.md ├── app ├── index.js └── templates │ ├── _bower.json │ ├── _config.xml │ ├── _gulpfile.browserify.js │ ├── _gulpfile.js │ ├── _package.browserify.json │ ├── _package.json │ ├── app │ ├── fonts │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-Light.ttf │ │ └── Roboto-Thin.ttf │ ├── icons │ │ └── own-icons-template.css │ ├── styles │ │ ├── _fonts.scss │ │ ├── _variables.scss │ │ ├── ionic-styles.scss │ │ ├── layout │ │ │ └── layout.scss │ │ ├── main.scss │ │ ├── menu │ │ │ └── menu.scss │ │ └── views │ │ │ └── home.scss │ └── templates │ │ ├── main.html │ │ └── views │ │ └── settings.html │ ├── bower.rc │ ├── editorconfig │ ├── gitignore │ ├── gitignore.browserify │ ├── helpers │ └── emulateios │ ├── home.html │ ├── hooks │ ├── README.md │ └── after_prepare │ │ └── 010_add_platform_class.js │ ├── icon.png │ ├── index.html │ ├── jshintrc │ ├── scripts │ ├── ApiService.js │ ├── ExampleService.js │ ├── apiEndpoint.js │ ├── app.js │ ├── homeController.js │ ├── lodash.js │ ├── mainController.js │ └── settingsController.js │ ├── splash.png │ └── src │ ├── app.js │ ├── controllers │ ├── homeController.js │ ├── mainController.js │ └── settingsController.js │ └── services │ ├── ApiService.js │ └── ExampleService.js ├── package.json └── test └── test-app.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "undef": true, 15 | "unused": true, 16 | "strict": true 17 | } 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-ionic-gulp' ]; then cd .. && eval "mv $currentfolder generator-ionic-gulp" && cd generator-ionic-gulp; fi 7 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-generator": {} 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A [Yeoman](http://yeoman.io) generator for Ionic Projects with Gulp 2 | 3 | This is a yeoman generator for my [Ionic Gulp Seed](https://github.com/tmaximini/ionic-gulp-seed), a minimal Ionic app template. It sets up everything to get you started with [Gulp](http://gulpjs.com/) and [Ionic](http://ionicframework.com/) in no time. 4 | Currently using Ionic 1.3.0 and Angular 1.5.3. 5 | 6 | 7 | ### Features 8 | 9 | * Gulp jobs for development, building, emulating and running your app 10 | * Compiles and concatenates your Sass 11 | * Local development server with live reload, even inside ios emulator 12 | * Automatically inject all your JS sources into `index.html` 13 | * Auto min-safe all Angular DI through `ng-annotate`, no need to use weird bracket notation 14 | * Easily customize Ionic styles from within your Sass 15 | * Comes already with [ng-cordova](http://ngcordova.com/) and [lodash](https://lodash.com) included 16 | * generate icon font from svg files 17 | * optional browserify support 18 | * Blazing fast 19 | 20 | 21 | ### Installation 22 | 23 | [![NPM](https://nodei.co/npm/generator-ionic-gulp.png?downloads=true)](https://nodei.co/npm/generator-ionic-gulp/) 24 | 25 | You should have Yeoman installed globally 26 | 27 | ```bash 28 | npm install -g yo 29 | ``` 30 | 31 | To install generator-ionic-gulp from npm, run: 32 | 33 | ```bash 34 | npm install -g generator-ionic-gulp 35 | ``` 36 | 37 | Finally, initiate the generator: 38 | 39 | ```bash 40 | yo ionic-gulp 41 | ``` 42 | 43 | after installation, just run: 44 | ```bash 45 | gulp 46 | ``` 47 | to start up the build job and file watchers. 48 | 49 | ~~In order to compile Sass, you need to have ruby and the sass ruby gem installed: `gem install sass`.~~ 50 | Now using https://github.com/sass/node-sass instead 51 | 52 | ## Workflow 53 | 54 | This doc assumes you have `gulp` globally installed (`npm install -g gulp`). 55 | If you do not have / want gulp globally installed, you can run `npm run gulp` instead. 56 | 57 | #### Development mode 58 | 59 | By running just `gulp`, we start our development build process, consisting of: 60 | 61 | - compiling, concatenating, auto-prefixing of all `.scss` files required by `app/styles/main.scss` 62 | - creating `vendor.js` file from ~~external sources defined in `./vendor.json`~~ from `bower.json` using `wiredep` 63 | - linting all `*.js` files `app/scripts` (or src/ if using browserify), see `.jshintrc` for ruleset 64 | - automatically inject sources into `index.html` so we don't have to add / remove sources manually 65 | - build everything into `.tmp` folder (also gitignored) 66 | - start local development server and serve from `.tmp` 67 | - start watchers to automatically lint javascript source files, compile scss and reload browser on changes 68 | 69 | #### Browserify support 70 | 71 | If you opted for browserify support all your sources will be kept in app/src instead of app/scripts. 72 | Please check app/src/app.js to see how modules can be added to your angular module. 73 | Browserify will automatically bundle only the code you require and you can require any module you installed with npm (provided they can be used in a webbrowser) 74 | 75 | If you opted for browserify support you have sourcemaps available in development mode. 76 | The script bundle and map file will be written in scripts/ and are .gitignored. 77 | The only other file in the scripts/ folder is the configuration.js file for your constants and other settings. 78 | 79 | NOTE: Beware that if you bundle (and uglify) angular modules you need to use the pattern where you provide an array with named parameters. See code below for an example of the difference. 80 | ``` 81 | // When not bundling you can do this 82 | .run( function( $ionicPlatform ) { ... } ) 83 | 84 | // If you bundle you need to use the following pattern: 85 | .run( [ '$ionicPlatform', function( $ionicPlatform ) { ... } ] ) 86 | 87 | // You can keep adding parameters like so: 88 | .run( [ '$ionicPlatform', '$q', '$http', function( $ionicPlatform, $q, $http ) { ... } ] ) 89 | ``` 90 | 91 | See the browserify website for what you can and cannot do with browserify: 92 | http://browserify.org/ 93 | 94 | If you need to add transpiling to browserify the location to do so has been marked in the gulpfile.js 95 | 96 | #### Build mode 97 | 98 | By running just `gulp --build` or short `gulp -b`, we start gulp in build mode 99 | 100 | - concat all `.js` sources into single `app.js` file 101 | - version `main.css` and `app.js` 102 | - build everything into `www` 103 | - remove debugs messages such as `console.log` or `alert` with passing `--release` 104 | 105 | 106 | #### Emulate 107 | 108 | By running `gulp -e `, we can run our app in the simulator 109 | 110 | - can be either `ios` or `android`, defaults to `ios` 111 | - make sure to have iOS Simulator installed in XCode, as well as `ios-sim` package globally installed (`npm install -g ios-sim`) 112 | - for Android, [Ripple](http://ripple.incubator.apache.org/) or [Genymotion](https://www.genymotion.com/) seem to be the emulators of choice 113 | - It will run the `gulp --build` before, so we have a fresh version to test 114 | - In iOS, it will livereload any code changes in iOS simulator 115 | 116 | #### Emulate a specific iOS device 117 | 118 | By running `gulp select` you will see a prompt where you can choose which ios device to emulate. This works only when you have the `gulp -e` task running in one terminal window and run `gulp select` in another terminal window. 119 | 120 | 121 | #### Ripple Emulator 122 | 123 | Run `gulp ripple` to open your app in a browser using ripple. This is useful for emuating a bunch of different Android devices and settings, such as geolocation, battery status, globalization and more. Note that ripple is still in beta and will show weird debug messages from time to time. 124 | 125 | 126 | #### Run 127 | 128 | By running `gulp -r `, we can run our app on a connected device 129 | 130 | - can be either `ios` or `android`, defaults to `ios` 131 | - It will run the `gulp --build` before, so we have a fresh version to test 132 | 133 | ### splash screens and icons 134 | 135 | Replace `splash.png` and `icon.png` inside `/resources`. Then run `ionic resources`. If you only want to regenerate icons or splashs, you can run `gulp icon` or `gulp splash` shorthand. 136 | 137 | ### customizing themes 138 | 139 | Just override any Ionic variables in `app/styles/ionic-styles.scss`. 140 | 141 | 142 | ## Changelog 143 | 144 | #### 1.5.2 145 | - add ES6 support for browserify builds, thanks @mattrothenberg 146 | 147 | #### 1.5.0 148 | - update app template to ionic 1.3.0 / angular 1.5.3 / ngCordova 0.1.26-alpha 149 | 150 | #### 1.4.0 151 | - update to ionic 1.2.1, changelog http://blog.ionic.io/announcing-ionic-1-2/ 152 | - remove `vendor.json` dependency, use `wiredep` instead, close #21 153 | - remove templates task #13 154 | 155 | #### 1.3.3 156 | - bugfix for infinite livereload when using browserify 157 | 158 | #### 1.3.2 159 | - added optional browserify support (thanks @Qwerios) 160 | 161 | #### 1.3.1 162 | - bump to ionic 1.1.0 which uses angular 1.4.x - changelog http://forum.ionicframework.com/t/1-1-0-xenon-xerus-released/30475 163 | 164 | #### 1.3.0 165 | - easier handling of custom ionic theming through `app/styles/ionic-styles.scss` thanks @superthing001 166 | - use `ionic.bundle.js` to reduce bower dependencies in `vendor.json` 167 | - fix iconfont: missing own-icons-template.css 168 | 169 | #### 1.2.2 170 | - update to ionic 1.0.1 171 | - keep angular explicitly on 1.3.x branch until Ionic officialy supports 1.4.x [see this thread](http://forum.ionicframework.com/t/angular-1-4-and-ionic/21458/12) 172 | 173 | 174 | #### 1.2.0 175 | - Drop rubySass in favor of libsass 176 | - compile Ionic .scss dynamically so we can support custom themes 177 | - update to ionic 1.0.0 178 | - update to ngCordova 0.1.17-alpha 179 | - update ro lodash 3.9.3 180 | 181 | ## License 182 | 183 | MIT 184 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var yeoman = require( 'yeoman-generator' ); 3 | var chalk = require( 'chalk' ); 4 | var yosay = require( 'yosay' ); 5 | var path = require( 'path' ); 6 | 7 | var appPath = path.join(process.cwd(), 'app'); 8 | 9 | 10 | module.exports = yeoman.generators.Base.extend({ 11 | initializing: function () { 12 | this.pkg = require('../package.json'); 13 | }, 14 | 15 | prompting: { 16 | 17 | askForNames: function askForNames() { 18 | var done = this.async(); 19 | 20 | // Have Yeoman greet the user. 21 | this.log(yosay( 22 | 'Welcome to the ' + chalk.red('ionic-gulp') + ' generator. Let\'s build an ionic app, shall we?' 23 | )); 24 | 25 | var prompts = [{ 26 | type: 'input', 27 | name: 'appName', 28 | message: 'What\'s the app name?', 29 | default : this.appname // Default to current folder name 30 | }, 31 | { 32 | type: 'confirm', 33 | name: 'browserify', 34 | message: 'Would you like to use Browserify?', 35 | default : false 36 | }, 37 | { 38 | type: 'input', 39 | name: 'userName', 40 | message: 'The author\'s name? (for config files)', 41 | default : this.user.git.name || 'Your Name' 42 | }, 43 | { 44 | type: 'input', 45 | name: 'userMail', 46 | message: 'Author email? (for config files)', 47 | default : this.user.git.email || 'email@example.com' 48 | 49 | }]; 50 | 51 | this.prompt(prompts, function(props) { 52 | this.appName = props.appName; 53 | this.userName = props.userName; 54 | this.userMail = props.userMail; 55 | 56 | // Store the Browserify preference for future sub-generator use 57 | // 58 | this.config.set( 'browserify', props.browserify ); 59 | 60 | done(); 61 | }.bind(this)); 62 | }, 63 | 64 | askForAppId: function askForAppId() { 65 | var done = this.async(); 66 | this.prompt([{ 67 | type: 'input', 68 | name: 'appId', 69 | message: 'The app id?', 70 | default : 'com.' + this._.classify(this.userName).toLowerCase() + '.' + this._.classify(this.appName).toLowerCase() 71 | }], function (props) { 72 | this.appId = props.appId; 73 | done(); 74 | }.bind(this)); 75 | } 76 | 77 | }, 78 | 79 | writing: { 80 | 81 | setup: function () { 82 | var browserifyEnabled = this.config.get( 'browserify' ) === true; 83 | 84 | this.fs.copyTpl( 85 | this.templatePath(browserifyEnabled ? '_package.browserify.json' : '_package.json'), 86 | this.destinationPath('package.json'), 87 | { appName: this._.underscored(this.appName), 88 | userName: this.userName, 89 | userEmail: this.userMail } 90 | ); 91 | this.fs.copyTpl( 92 | this.templatePath('_bower.json'), 93 | this.destinationPath('bower.json'), 94 | { appName: this._.classify(this.appName), 95 | userName: this.userName, 96 | userEmail: this.userMail } 97 | ); 98 | this.fs.copyTpl( 99 | this.templatePath('_config.xml'), 100 | this.destinationPath('config.xml'), 101 | { appName: this.appName, 102 | userName: this.userName, 103 | userEmail: this.userMail, 104 | widgetId: this.appId } 105 | ); 106 | 107 | this.fs.copyTpl( 108 | this.templatePath(browserifyEnabled ? '_gulpfile.browserify.js' : '_gulpfile.js'), 109 | this.destinationPath('gulpfile.js'), 110 | { ngModulName: this._.classify(this.appName) } 111 | ); 112 | 113 | this.fs.copy( 114 | this.templatePath('editorconfig'), 115 | this.destinationPath('.editorconfig') 116 | ); 117 | this.fs.copy( 118 | this.templatePath(browserifyEnabled ? 'gitignore.browserify' : 'gitignore'), 119 | this.destinationPath('.gitignore') 120 | ); 121 | this.fs.copy( 122 | this.templatePath('jshintrc'), 123 | this.destinationPath('.jshintrc') 124 | ); 125 | 126 | this.mkdir('helpers'); 127 | this.mkdir('www'); 128 | 129 | this.fs.copy( 130 | this.templatePath('helpers/emulateios'), 131 | this.destinationPath('helpers/emulateios') 132 | ); 133 | 134 | }, 135 | 136 | projectfiles: function () { 137 | var browserifyEnabled = this.config.get( 'browserify' ) === true; 138 | 139 | this.directory('app', 'app'); 140 | this.directory('hooks', 'hooks'); 141 | 142 | this.mkdir('app/icons'); 143 | this.mkdir('app/images'); 144 | this.mkdir('resources'); 145 | 146 | this.fs.copyTpl( 147 | this.templatePath('index.html'), 148 | this.destinationPath('app/index.html'), 149 | { title: this.appName, ngModulName: this._.classify(this.appName) } 150 | ); 151 | 152 | this.fs.copyTpl( 153 | this.templatePath('home.html'), 154 | this.destinationPath('app/templates/views/home.html'), 155 | { title: this.appName } 156 | ); 157 | 158 | if ( browserifyEnabled ) 159 | { 160 | // config 161 | this.fs.copyTpl( 162 | this.templatePath('scripts/apiEndpoint.js'), 163 | this.destinationPath('app/scripts/configuration.js'), 164 | { ngModulName: this._.classify(this.appName) } 165 | ); 166 | 167 | // app 168 | this.fs.copyTpl( 169 | this.templatePath('src/app.js'), 170 | this.destinationPath('app/src/app.js'), 171 | { ngModulName: this._.classify(this.appName) } 172 | ); 173 | 174 | // controllers 175 | this.fs.copyTpl( 176 | this.templatePath('src/controllers/homeController.js'), 177 | this.destinationPath('app/src/controllers/homeController.js'), 178 | { ngModulName: this._.classify(this.appName) } 179 | ); 180 | 181 | this.fs.copyTpl( 182 | this.templatePath('src/controllers/mainController.js'), 183 | this.destinationPath('app/src/controllers/mainController.js'), 184 | { ngModulName: this._.classify(this.appName) } 185 | ); 186 | 187 | this.fs.copyTpl( 188 | this.templatePath('src/controllers/settingsController.js'), 189 | this.destinationPath('app/src/controllers/settingsController.js'), 190 | { ngModulName: this._.classify(this.appName) } 191 | ); 192 | 193 | // services 194 | this.fs.copyTpl( 195 | this.templatePath('src/services/ExampleService.js'), 196 | this.destinationPath('app/src/services/ExampleService.js'), 197 | { ngModulName: this._.classify(this.appName) } 198 | ); 199 | 200 | this.fs.copyTpl( 201 | this.templatePath('src/services/ApiService.js'), 202 | this.destinationPath('app/src/services/ApiService.js'), 203 | { ngModulName: this._.classify(this.appName) } 204 | ); 205 | } 206 | else 207 | { 208 | // controllers 209 | this.fs.copyTpl( 210 | this.templatePath('scripts/homeController.js'), 211 | this.destinationPath('app/scripts/controllers/homeController.js'), 212 | { ngModulName: this._.classify(this.appName) } 213 | ); 214 | 215 | this.fs.copyTpl( 216 | this.templatePath('scripts/mainController.js'), 217 | this.destinationPath('app/scripts/controllers/mainController.js'), 218 | { ngModulName: this._.classify(this.appName) } 219 | ); 220 | 221 | this.fs.copyTpl( 222 | this.templatePath('scripts/settingsController.js'), 223 | this.destinationPath('app/scripts/controllers/settingsController.js'), 224 | { ngModulName: this._.classify(this.appName) } 225 | ); 226 | 227 | // services 228 | this.fs.copyTpl( 229 | this.templatePath('scripts/ExampleService.js'), 230 | this.destinationPath('app/scripts/services/ExampleService.js'), 231 | { ngModulName: this._.classify(this.appName) } 232 | ); 233 | 234 | this.fs.copyTpl( 235 | this.templatePath('scripts/ApiService.js'), 236 | this.destinationPath('app/scripts/services/ApiService.js'), 237 | { ngModulName: this._.classify(this.appName) } 238 | ); 239 | 240 | // config 241 | this.fs.copyTpl( 242 | this.templatePath('scripts/apiEndpoint.js'), 243 | this.destinationPath('app/scripts/config/apiEndpoint.js'), 244 | { ngModulName: this._.classify(this.appName) } 245 | ); 246 | 247 | // utils 248 | this.fs.copyTpl( 249 | this.templatePath('scripts/lodash.js'), 250 | this.destinationPath('app/scripts/utils/lodash.js'), 251 | { ngModulName: this._.classify(this.appName) } 252 | ); 253 | 254 | // app 255 | 256 | this.fs.copyTpl( 257 | this.templatePath('scripts/app.js'), 258 | this.destinationPath('app/scripts/app.js'), 259 | { ngModulName: this._.classify(this.appName) } 260 | ); 261 | } 262 | 263 | this.fs.copy( 264 | this.templatePath('splash.png'), 265 | this.destinationPath('resources/splash.png') 266 | ); 267 | 268 | this.fs.copy( 269 | this.templatePath('icon.png'), 270 | this.destinationPath('resources/icon.png') 271 | ); 272 | } 273 | 274 | }, 275 | 276 | install: function () { 277 | this.installDependencies({ 278 | skipInstall: this.options['skip-install'] 279 | }); 280 | } 281 | }); 282 | -------------------------------------------------------------------------------- /app/templates/_bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= appName %>", 3 | "author": "<%= userName %> <<%= userEmail %>>", 4 | "private": "true", 5 | "devDependencies": {}, 6 | "dependencies": { 7 | "angular": "~1.5.3", 8 | "ngCordova": "~0.1.26-alpha", 9 | "angular-resource": "~1.5.3", 10 | "ionic": "~1.3.0" 11 | }, 12 | "resolutions": { 13 | "angular": "1.5.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/templates/_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%= appName %> 4 | 5 | Add your desription here 6 | 7 | 8 | <%= userName %> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/templates/_gulpfile.browserify.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var appName = '<%= ngModulName %>'; 4 | 5 | var gulp = require('gulp'); 6 | var plugins = require('gulp-load-plugins')(); 7 | var del = require('del'); 8 | var beep = require('beepbeep'); 9 | var express = require('express'); 10 | var path = require('path'); 11 | var open = require('open'); 12 | var stylish = require('jshint-stylish'); 13 | var connectLr = require('connect-livereload'); 14 | var streamqueue = require('streamqueue'); 15 | var runSequence = require('run-sequence'); 16 | var merge = require('merge-stream'); 17 | var ripple = require('ripple-emulator'); 18 | var browserify = require('browserify'); 19 | var source = require('vinyl-source-stream'); 20 | var buffer = require('vinyl-buffer'); 21 | var uglify = require('gulp-uglify'); 22 | var sourcemaps = require('gulp-sourcemaps'); 23 | var gutil = require('gulp-util'); 24 | var wiredep = require('wiredep'); 25 | var babel = require('babelify'); 26 | 27 | /** 28 | * Parse arguments 29 | */ 30 | var args = require('yargs') 31 | .alias('e', 'emulate') 32 | .alias('b', 'build') 33 | .alias('r', 'run') 34 | // remove all debug messages (console.logs, alerts etc) from release build 35 | .alias('release', 'strip-debug') 36 | .default('build', false) 37 | .default('port', 9000) 38 | .default('strip-debug', false) 39 | .argv; 40 | 41 | var build = !!(args.build || args.emulate || args.run); 42 | var emulate = args.emulate; 43 | var run = args.run; 44 | var port = args.port; 45 | var stripDebug = !!args.stripDebug; 46 | var targetDir = path.resolve(build ? 'www' : '.tmp'); 47 | 48 | // if we just use emualate or run without specifying platform, we assume iOS 49 | // in this case the value returned from yargs would just be true 50 | if (emulate === true) { 51 | emulate = 'ios'; 52 | } 53 | if (run === true) { 54 | run = 'ios'; 55 | } 56 | 57 | // global error handler 58 | var errorHandler = function(error) { 59 | if (build) { 60 | throw error; 61 | } else { 62 | beep(2, 170); 63 | plugins.util.log(error); 64 | } 65 | }; 66 | 67 | 68 | // clean target dir 69 | gulp.task('clean', function(done) { 70 | return del([targetDir, 'app/scripts/bundle.js','app/scripts/bundle.js.map'], done); 71 | }); 72 | 73 | // precompile .scss and concat with ionic.css 74 | gulp.task('styles', function() { 75 | 76 | var options = build ? { style: 'compressed' } : { style: 'expanded' }; 77 | 78 | var sassStream = gulp.src('app/styles/main.scss') 79 | .pipe(plugins.sass(options)) 80 | .on('error', function(err) { 81 | console.log('err: ', err); 82 | beep(); 83 | }); 84 | 85 | // build ionic css dynamically to support custom themes 86 | var ionicStream = gulp.src('app/styles/ionic-styles.scss') 87 | .pipe(plugins.cached('ionic-styles')) 88 | .pipe(plugins.sass(options)) 89 | // cache and remember ionic .scss in order to cut down re-compile time 90 | .pipe(plugins.remember('ionic-styles')) 91 | .on('error', function(err) { 92 | console.log('err: ', err); 93 | beep(); 94 | }); 95 | 96 | return streamqueue({ objectMode: true }, ionicStream, sassStream) 97 | .pipe(plugins.autoprefixer('last 1 Chrome version', 'last 3 iOS versions', 'last 3 Android versions')) 98 | .pipe(plugins.concat('main.css')) 99 | .pipe(plugins.if(build, plugins.stripCssComments())) 100 | .pipe(plugins.if(build && !emulate, plugins.rev())) 101 | .pipe(gulp.dest(path.join(targetDir, 'styles'))) 102 | .on('error', errorHandler); 103 | }); 104 | 105 | // bundle all the src files into scripts/bundle.js 106 | gulp.task('browserify', function () { 107 | // set up the browserify instance on a task basis 108 | var b = browserify({ 109 | entries: './app/src/app.js', 110 | debug: !build 111 | }).transform('babelify', {presets: ['es2015']}); 112 | 113 | return b.bundle() 114 | .pipe(source('bundle.js')) 115 | .pipe(buffer()) 116 | .pipe(sourcemaps.init({loadMaps: true})) 117 | // Add transformation tasks to the pipeline here. 118 | .pipe(uglify()) 119 | .on('error', gutil.log) 120 | .pipe(plugins.if(!build,sourcemaps.write('./'))) 121 | .pipe(gulp.dest('./app/scripts/')); 122 | }); 123 | 124 | // build templatecache, copy scripts. 125 | // if build: concat, minsafe, uglify and versionize 126 | gulp.task('scripts', ['browserify'], function() { 127 | var dest = path.join(targetDir, 'scripts'); 128 | 129 | var minifyConfig = { 130 | collapseWhitespace: true, 131 | collapseBooleanAttributes: true, 132 | removeAttributeQuotes: true, 133 | removeComments: true 134 | }; 135 | 136 | // prepare angular template cache from html templates 137 | // (remember to change appName var to desired module name) 138 | var templateStream = gulp 139 | .src('**/*.html', { cwd: 'app/templates'}) 140 | .pipe(plugins.angularTemplatecache('templates.js', { 141 | root: 'templates/', 142 | module: appName, 143 | htmlmin: build && minifyConfig 144 | })); 145 | 146 | var scriptStream = gulp 147 | .src( ['bundle.js', 'bundle.js.map', 'configuration.js', 'templates.js' ], { cwd: 'app/scripts' }) 148 | 149 | .pipe(plugins.if(!build, plugins.changed(dest))); 150 | 151 | return streamqueue({ objectMode: true }, scriptStream, templateStream) 152 | .pipe(plugins.if(build, plugins.ngAnnotate())) 153 | .pipe(plugins.if(stripDebug, plugins.stripDebug())) 154 | .pipe(plugins.if(build, plugins.concat('app.js'))) 155 | .pipe(plugins.if(build, plugins.uglify())) 156 | .pipe(plugins.if(build && !emulate, plugins.rev())) 157 | 158 | .pipe(gulp.dest(dest)) 159 | 160 | .on('error', errorHandler); 161 | }); 162 | 163 | // copy fonts 164 | gulp.task('fonts', function() { 165 | return gulp 166 | .src(['app/fonts/*.*', 'bower_components/ionic/release/fonts/*.*']) 167 | 168 | .pipe(gulp.dest(path.join(targetDir, 'fonts'))) 169 | 170 | .on('error', errorHandler); 171 | }); 172 | 173 | 174 | 175 | // generate iconfont 176 | gulp.task('iconfont', function(){ 177 | return gulp.src('app/icons/*.svg', { 178 | buffer: false 179 | }) 180 | .pipe(plugins.iconfontCss({ 181 | fontName: 'ownIconFont', 182 | path: 'app/icons/own-icons-template.css', 183 | targetPath: '../styles/own-icons.css', 184 | fontPath: '../fonts/' 185 | })) 186 | .pipe(plugins.iconfont({ 187 | fontName: 'ownIconFont' 188 | })) 189 | .pipe(gulp.dest(path.join(targetDir, 'fonts'))) 190 | .on('error', errorHandler); 191 | }); 192 | 193 | // copy images 194 | gulp.task('images', function() { 195 | return gulp.src('app/images/**/*.*') 196 | .pipe(gulp.dest(path.join(targetDir, 'images'))) 197 | 198 | .on('error', errorHandler); 199 | }); 200 | 201 | 202 | // lint js sources based on .jshintrc ruleset 203 | gulp.task('jsHint', function() { 204 | return gulp 205 | .src('app/src/**/*.js') 206 | .pipe(plugins.jshint()) 207 | .pipe(plugins.jshint.reporter(stylish)) 208 | .on('error', errorHandler); 209 | }); 210 | 211 | // concatenate and minify vendor sources 212 | gulp.task('vendor', function() { 213 | var vendorFiles = wiredep().js; 214 | 215 | return gulp.src(vendorFiles) 216 | .pipe(plugins.concat('vendor.js')) 217 | .pipe(plugins.if(build, plugins.uglify())) 218 | .pipe(plugins.if(build, plugins.rev())) 219 | 220 | .pipe(gulp.dest(targetDir)) 221 | 222 | .on('error', errorHandler); 223 | }); 224 | 225 | 226 | // inject the files in index.html 227 | gulp.task('index', ['jsHint', 'scripts'], function() { 228 | 229 | // build has a '-versionnumber' suffix 230 | var cssNaming = 'styles/main*'; 231 | 232 | // injects 'src' into index.html at position 'tag' 233 | var _inject = function(src, tag) { 234 | return plugins.inject(src, { 235 | starttag: '', 236 | read: false, 237 | addRootSlash: false 238 | }); 239 | }; 240 | 241 | // get all our javascript sources 242 | // in development mode, it's better to add each file seperately. 243 | // it makes debugging easier. 244 | var _getAllScriptSources = function() { 245 | var scriptStream = gulp.src(['scripts/app.js', 'scripts/**/*.js'], { cwd: targetDir }); 246 | return streamqueue({ objectMode: true }, scriptStream); 247 | }; 248 | 249 | return gulp.src('app/index.html') 250 | // inject css 251 | .pipe(_inject(gulp.src(cssNaming, { cwd: targetDir }), 'app-styles')) 252 | // inject vendor.js 253 | .pipe(_inject(gulp.src('vendor*.js', { cwd: targetDir }), 'vendor')) 254 | // inject app.js (build) or all js files indivually (dev) 255 | .pipe(plugins.if(build, 256 | _inject(gulp.src('scripts/app*.js', { cwd: targetDir }), 'app'), 257 | _inject(_getAllScriptSources(), 'app') 258 | )) 259 | 260 | .pipe(gulp.dest(targetDir)) 261 | .on('error', errorHandler); 262 | }); 263 | 264 | // start local express server 265 | gulp.task('serve', function() { 266 | express() 267 | .use(!build ? connectLr() : function(){}) 268 | .use(express.static(targetDir)) 269 | .listen(port); 270 | open('http://localhost:' + port + '/'); 271 | }); 272 | 273 | // ionic emulate wrapper 274 | gulp.task('ionic:emulate', plugins.shell.task([ 275 | 'ionic emulate ' + emulate + ' --livereload --consolelogs' 276 | ])); 277 | 278 | // ionic run wrapper 279 | gulp.task('ionic:run', plugins.shell.task([ 280 | 'ionic run ' + run 281 | ])); 282 | 283 | // ionic resources wrapper 284 | gulp.task('icon', plugins.shell.task([ 285 | 'ionic resources --icon' 286 | ])); 287 | gulp.task('splash', plugins.shell.task([ 288 | 'ionic resources --splash' 289 | ])); 290 | gulp.task('resources', plugins.shell.task([ 291 | 'ionic resources' 292 | ])); 293 | 294 | // select emulator device 295 | gulp.task('select', plugins.shell.task([ 296 | './helpers/emulateios' 297 | ])); 298 | 299 | // ripple emulator 300 | gulp.task('ripple', ['scripts', 'styles', 'watchers'], function() { 301 | 302 | var options = { 303 | keepAlive: false, 304 | open: true, 305 | port: 4400 306 | }; 307 | 308 | // Start the ripple server 309 | ripple.emulate.start(options); 310 | 311 | open('http://localhost:' + options.port + '?enableripple=true'); 312 | }); 313 | 314 | 315 | // start watchers 316 | gulp.task('watchers', function() { 317 | plugins.livereload.listen(); 318 | gulp.watch('app/styles/**/*.scss', ['styles']); 319 | gulp.watch('app/fonts/**', ['fonts']); 320 | gulp.watch('app/icons/**', ['iconfont']); 321 | gulp.watch('app/images/**', ['images']); 322 | gulp.watch(['app/scripts/**/*.js','!app/scripts/bundle.js'], ['index']); 323 | gulp.watch('./bower.json', ['vendor']); 324 | gulp.watch('app/templates/**/*.html', ['index']); 325 | gulp.watch('app/index.html', ['index']); 326 | gulp.watch('app/src/**/*.js', ['scripts']); 327 | gulp.watch(targetDir + '/**') 328 | .on('change', plugins.livereload.changed) 329 | .on('error', errorHandler); 330 | }); 331 | 332 | // no-op = empty function 333 | gulp.task('noop', function() {}); 334 | 335 | // our main sequence, with some conditional jobs depending on params 336 | gulp.task('default', function(done) { 337 | runSequence( 338 | 'clean', 339 | 'iconfont', 340 | [ 341 | 'fonts', 342 | 'styles', 343 | 'images', 344 | 'vendor' 345 | ], 346 | 'index', 347 | build ? 'noop' : 'watchers', 348 | build ? 'noop' : 'serve', 349 | emulate ? ['ionic:emulate', 'watchers'] : 'noop', 350 | run ? 'ionic:run' : 'noop', 351 | done); 352 | }); 353 | -------------------------------------------------------------------------------- /app/templates/_gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var appName = '<%= ngModulName %>'; 4 | 5 | var gulp = require('gulp'); 6 | var plugins = require('gulp-load-plugins')(); 7 | var del = require('del'); 8 | var beep = require('beepbeep'); 9 | var express = require('express'); 10 | var path = require('path'); 11 | var open = require('open'); 12 | var stylish = require('jshint-stylish'); 13 | var connectLr = require('connect-livereload'); 14 | var streamqueue = require('streamqueue'); 15 | var runSequence = require('run-sequence'); 16 | var merge = require('merge-stream'); 17 | var ripple = require('ripple-emulator'); 18 | var wiredep = require('wiredep'); 19 | 20 | /** 21 | * Parse arguments 22 | */ 23 | var args = require('yargs') 24 | .alias('e', 'emulate') 25 | .alias('b', 'build') 26 | .alias('r', 'run') 27 | // remove all debug messages (console.logs, alerts etc) from release build 28 | .alias('release', 'strip-debug') 29 | .default('build', false) 30 | .default('port', 9000) 31 | .default('strip-debug', false) 32 | .argv; 33 | 34 | var build = !!(args.build || args.emulate || args.run); 35 | var emulate = args.emulate; 36 | var run = args.run; 37 | var port = args.port; 38 | var stripDebug = !!args.stripDebug; 39 | var targetDir = path.resolve(build ? 'www' : '.tmp'); 40 | 41 | // if we just use emualate or run without specifying platform, we assume iOS 42 | // in this case the value returned from yargs would just be true 43 | if (emulate === true) { 44 | emulate = 'ios'; 45 | } 46 | if (run === true) { 47 | run = 'ios'; 48 | } 49 | 50 | // global error handler 51 | var errorHandler = function(error) { 52 | if (build) { 53 | throw error; 54 | } else { 55 | beep(2, 170); 56 | plugins.util.log(error); 57 | } 58 | }; 59 | 60 | 61 | // clean target dir 62 | gulp.task('clean', function(done) { 63 | return del([targetDir], done); 64 | }); 65 | 66 | // precompile .scss and concat with ionic.css 67 | gulp.task('styles', function() { 68 | 69 | var options = build ? { style: 'compressed' } : { style: 'expanded' }; 70 | 71 | var sassStream = gulp.src('app/styles/main.scss') 72 | .pipe(plugins.sass(options)) 73 | .on('error', function(err) { 74 | console.log('err: ', err); 75 | beep(); 76 | }); 77 | 78 | // build ionic css dynamically to support custom themes 79 | var ionicStream = gulp.src('app/styles/ionic-styles.scss') 80 | .pipe(plugins.cached('ionic-styles')) 81 | .pipe(plugins.sass(options)) 82 | // cache and remember ionic .scss in order to cut down re-compile time 83 | .pipe(plugins.remember('ionic-styles')) 84 | .on('error', function(err) { 85 | console.log('err: ', err); 86 | beep(); 87 | }); 88 | 89 | return streamqueue({ objectMode: true }, ionicStream, sassStream) 90 | .pipe(plugins.autoprefixer('last 1 Chrome version', 'last 3 iOS versions', 'last 3 Android versions')) 91 | .pipe(plugins.concat('main.css')) 92 | .pipe(plugins.if(build, plugins.stripCssComments())) 93 | .pipe(plugins.if(build && !emulate, plugins.rev())) 94 | .pipe(gulp.dest(path.join(targetDir, 'styles'))) 95 | .on('error', errorHandler); 96 | }); 97 | 98 | 99 | // build templatecache, copy scripts. 100 | // if build: concat, minsafe, uglify and versionize 101 | gulp.task('scripts', function() { 102 | var dest = path.join(targetDir, 'scripts'); 103 | 104 | var minifyConfig = { 105 | collapseWhitespace: true, 106 | collapseBooleanAttributes: true, 107 | removeAttributeQuotes: true, 108 | removeComments: true 109 | }; 110 | 111 | // prepare angular template cache from html templates 112 | // (remember to change appName var to desired module name) 113 | var templateStream = gulp 114 | .src('**/*.html', { cwd: 'app/templates'}) 115 | .pipe(plugins.angularTemplatecache('templates.js', { 116 | root: 'templates/', 117 | module: appName, 118 | htmlmin: build && minifyConfig 119 | })); 120 | 121 | var scriptStream = gulp 122 | .src(['templates.js', 'app.js', '**/*.js'], { cwd: 'app/scripts' }) 123 | 124 | .pipe(plugins.if(!build, plugins.changed(dest))); 125 | 126 | return streamqueue({ objectMode: true }, scriptStream, templateStream) 127 | .pipe(plugins.if(build, plugins.ngAnnotate())) 128 | .pipe(plugins.if(stripDebug, plugins.stripDebug())) 129 | .pipe(plugins.if(build, plugins.concat('app.js'))) 130 | .pipe(plugins.if(build, plugins.uglify())) 131 | .pipe(plugins.if(build && !emulate, plugins.rev())) 132 | 133 | .pipe(gulp.dest(dest)) 134 | 135 | .on('error', errorHandler); 136 | }); 137 | 138 | // copy fonts 139 | gulp.task('fonts', function() { 140 | return gulp 141 | .src(['app/fonts/*.*', 'bower_components/ionic/release/fonts/*.*']) 142 | 143 | .pipe(gulp.dest(path.join(targetDir, 'fonts'))) 144 | 145 | .on('error', errorHandler); 146 | }); 147 | 148 | 149 | // generate iconfont 150 | gulp.task('iconfont', function(){ 151 | return gulp.src('app/icons/*.svg', { 152 | buffer: false 153 | }) 154 | .pipe(plugins.iconfontCss({ 155 | fontName: 'ownIconFont', 156 | path: 'app/icons/own-icons-template.css', 157 | targetPath: '../styles/own-icons.css', 158 | fontPath: '../fonts/' 159 | })) 160 | .pipe(plugins.iconfont({ 161 | fontName: 'ownIconFont' 162 | })) 163 | .pipe(gulp.dest(path.join(targetDir, 'fonts'))) 164 | .on('error', errorHandler); 165 | }); 166 | 167 | // copy images 168 | gulp.task('images', function() { 169 | return gulp.src('app/images/**/*.*') 170 | .pipe(gulp.dest(path.join(targetDir, 'images'))) 171 | 172 | .on('error', errorHandler); 173 | }); 174 | 175 | 176 | // lint js sources based on .jshintrc ruleset 177 | gulp.task('jsHint', function(done) { 178 | return gulp 179 | .src('app/scripts/**/*.js') 180 | .pipe(plugins.jshint()) 181 | .pipe(plugins.jshint.reporter(stylish)) 182 | 183 | .on('error', errorHandler); 184 | done(); 185 | }); 186 | 187 | // concatenate and minify vendor sources 188 | gulp.task('vendor', function() { 189 | var vendorFiles = wiredep().js; 190 | 191 | return gulp.src(vendorFiles) 192 | .pipe(plugins.concat('vendor.js')) 193 | .pipe(plugins.if(build, plugins.uglify())) 194 | .pipe(plugins.if(build, plugins.rev())) 195 | 196 | .pipe(gulp.dest(targetDir)) 197 | 198 | .on('error', errorHandler); 199 | }); 200 | 201 | 202 | // inject the files in index.html 203 | gulp.task('index', ['jsHint', 'scripts'], function() { 204 | 205 | // build has a '-versionnumber' suffix 206 | var cssNaming = 'styles/main*'; 207 | 208 | // injects 'src' into index.html at position 'tag' 209 | var _inject = function(src, tag) { 210 | return plugins.inject(src, { 211 | starttag: '', 212 | read: false, 213 | addRootSlash: false 214 | }); 215 | }; 216 | 217 | // get all our javascript sources 218 | // in development mode, it's better to add each file seperately. 219 | // it makes debugging easier. 220 | var _getAllScriptSources = function() { 221 | var scriptStream = gulp.src(['scripts/app.js', 'scripts/**/*.js'], { cwd: targetDir }); 222 | return streamqueue({ objectMode: true }, scriptStream); 223 | }; 224 | 225 | return gulp.src('app/index.html') 226 | // inject css 227 | .pipe(_inject(gulp.src(cssNaming, { cwd: targetDir }), 'app-styles')) 228 | // inject vendor.js 229 | .pipe(_inject(gulp.src('vendor*.js', { cwd: targetDir }), 'vendor')) 230 | // inject app.js (build) or all js files indivually (dev) 231 | .pipe(plugins.if(build, 232 | _inject(gulp.src('scripts/app*.js', { cwd: targetDir }), 'app'), 233 | _inject(_getAllScriptSources(), 'app') 234 | )) 235 | 236 | .pipe(gulp.dest(targetDir)) 237 | .on('error', errorHandler); 238 | }); 239 | 240 | // start local express server 241 | gulp.task('serve', function() { 242 | express() 243 | .use(!build ? connectLr() : function(){}) 244 | .use(express.static(targetDir)) 245 | .listen(port); 246 | open('http://localhost:' + port + '/'); 247 | }); 248 | 249 | // ionic emulate wrapper 250 | gulp.task('ionic:emulate', plugins.shell.task([ 251 | 'ionic emulate ' + emulate + ' --livereload --consolelogs' 252 | ])); 253 | 254 | // ionic run wrapper 255 | gulp.task('ionic:run', plugins.shell.task([ 256 | 'ionic run ' + run 257 | ])); 258 | 259 | // ionic resources wrapper 260 | gulp.task('icon', plugins.shell.task([ 261 | 'ionic resources --icon' 262 | ])); 263 | gulp.task('splash', plugins.shell.task([ 264 | 'ionic resources --splash' 265 | ])); 266 | gulp.task('resources', plugins.shell.task([ 267 | 'ionic resources' 268 | ])); 269 | 270 | // select emulator device 271 | gulp.task('select', plugins.shell.task([ 272 | './helpers/emulateios' 273 | ])); 274 | 275 | // ripple emulator 276 | gulp.task('ripple', ['scripts', 'styles', 'watchers'], function() { 277 | 278 | var options = { 279 | keepAlive: false, 280 | open: true, 281 | port: 4400 282 | }; 283 | 284 | // Start the ripple server 285 | ripple.emulate.start(options); 286 | 287 | open('http://localhost:' + options.port + '?enableripple=true'); 288 | }); 289 | 290 | 291 | // start watchers 292 | gulp.task('watchers', function() { 293 | plugins.livereload.listen(); 294 | gulp.watch('app/styles/**/*.scss', ['styles']); 295 | gulp.watch('app/fonts/**', ['fonts']); 296 | gulp.watch('app/icons/**', ['iconfont']); 297 | gulp.watch('app/images/**', ['images']); 298 | gulp.watch('app/scripts/**/*.js', ['index']); 299 | gulp.watch('./bower.json', ['vendor']); 300 | gulp.watch('app/templates/**/*.html', ['index']); 301 | gulp.watch('app/index.html', ['index']); 302 | gulp.watch(targetDir + '/**') 303 | .on('change', plugins.livereload.changed) 304 | .on('error', errorHandler); 305 | }); 306 | 307 | // no-op = empty function 308 | gulp.task('noop', function() {}); 309 | 310 | // our main sequence, with some conditional jobs depending on params 311 | gulp.task('default', function(done) { 312 | runSequence( 313 | 'clean', 314 | 'iconfont', 315 | [ 316 | 'fonts', 317 | 'styles', 318 | 'images', 319 | 'vendor' 320 | ], 321 | 'index', 322 | build ? 'noop' : 'watchers', 323 | build ? 'noop' : 'serve', 324 | emulate ? ['ionic:emulate', 'watchers'] : 'noop', 325 | run ? 'ionic:run' : 'noop', 326 | done); 327 | }); 328 | -------------------------------------------------------------------------------- /app/templates/_package.browserify.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= appName %>", 3 | "version": "1.0.0", 4 | "author": "<%= userName %> <<%= userEmail %>>", 5 | "description": "", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "babel-preset-es2015": "^6.14.0", 9 | "babelify": "^7.3.0", 10 | "beepbeep": "^1.2.0", 11 | "connect-livereload": "^0.5.2", 12 | "del": "^2.2.0", 13 | "express": "^4.11.1", 14 | "glob": "^4.3.5", 15 | "gulp": "^3.8.10", 16 | "gulp-angular-templatecache": "^1.8.0", 17 | "gulp-autoprefixer": "^3.1.0", 18 | "gulp-cached": "^1.1.0", 19 | "gulp-changed": "^1.3.0", 20 | "gulp-concat": "^2.6.0", 21 | "gulp-iconfont": "^5.0.1", 22 | "gulp-iconfont-css": "2.0.0", 23 | "gulp-if": "^2.0.0", 24 | "gulp-inject": "^3.0.0", 25 | "gulp-jshint": "^2.0.0", 26 | "gulp-livereload": "^3.8.1", 27 | "gulp-load-plugins": "^1.1.0", 28 | "gulp-ng-annotate": "^1.1.0", 29 | "gulp-remember": "^0.3.0", 30 | "gulp-rev": "^6.0.0", 31 | "gulp-sass": "^2.1.1", 32 | "gulp-shell": "^0.5.1", 33 | "gulp-strip-css-comments": "^1.2.0", 34 | "gulp-strip-debug": "^1.1.0", 35 | "gulp-uglify": "^1.5.1", 36 | "gulp-util": "^3.0.0", 37 | "jshint": "2.9.1", 38 | "jshint-stylish": "^2.1.0", 39 | "lodash": "^3.10.1", 40 | "lodash._basecopy": "latest", 41 | "merge-stream": "^1.0.0", 42 | "node-sass": "^3.4.2", 43 | "open": "0.0.5", 44 | "ripple-emulator": "^0.9.32", 45 | "run-sequence": "^1.1.5", 46 | "shelljs": "^0.5.3", 47 | "streamqueue": "^1.1.1", 48 | "wiredep": "^4.0.0", 49 | "yargs": "^3.31.0", 50 | "browserify": "^12.0.1", 51 | "gulp-sourcemaps": "^1.6.0", 52 | "vinyl-buffer": "^1.0.0", 53 | "vinyl-source-stream": "^1.1.0" 54 | }, 55 | "scripts": { 56 | "gulp": "./node_modules/.bin/gulp" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= appName %>", 3 | "version": "1.0.0", 4 | "author": "<%= userName %> <<%= userEmail %>>", 5 | "description": "", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "beepbeep": "^1.2.0", 9 | "connect-livereload": "^0.5.2", 10 | "del": "^2.2.0", 11 | "express": "^4.11.1", 12 | "glob": "^4.3.5", 13 | "gulp": "^3.8.10", 14 | "gulp-angular-templatecache": "^1.8.0", 15 | "gulp-autoprefixer": "^3.1.0", 16 | "gulp-cached": "^1.1.0", 17 | "gulp-changed": "^1.3.0", 18 | "gulp-concat": "^2.6.0", 19 | "gulp-iconfont": "^5.0.1", 20 | "gulp-iconfont-css": "2.0.0", 21 | "gulp-if": "^2.0.0", 22 | "gulp-inject": "^3.0.0", 23 | "gulp-jshint": "^2.0.0", 24 | "gulp-livereload": "^3.8.1", 25 | "gulp-load-plugins": "^1.1.0", 26 | "gulp-ng-annotate": "^1.1.0", 27 | "gulp-remember": "^0.3.0", 28 | "gulp-rev": "^6.0.0", 29 | "gulp-sass": "^2.1.1", 30 | "gulp-shell": "^0.5.1", 31 | "gulp-strip-css-comments": "^1.2.0", 32 | "gulp-strip-debug": "^1.1.0", 33 | "gulp-uglify": "^1.5.1", 34 | "gulp-util": "^3.0.0", 35 | "jshint": "2.9.1", 36 | "jshint-stylish": "^2.1.0", 37 | "lodash": "^3.10.1", 38 | "lodash._basecopy": "latest", 39 | "merge-stream": "^1.0.0", 40 | "node-sass": "^3.4.2", 41 | "open": "0.0.5", 42 | "ripple-emulator": "^0.9.32", 43 | "run-sequence": "^1.1.5", 44 | "shelljs": "^0.5.3", 45 | "streamqueue": "^1.1.1", 46 | "wiredep": "^4.0.0", 47 | "yargs": "^3.31.0" 48 | }, 49 | "scripts": { 50 | "gulp": "./node_modules/.bin/gulp" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/templates/app/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmaximini/generator-ionic-gulp/d2bd9d3bab1d58e29e5f9a638b9334c4b22143bc/app/templates/app/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /app/templates/app/fonts/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmaximini/generator-ionic-gulp/d2bd9d3bab1d58e29e5f9a638b9334c4b22143bc/app/templates/app/fonts/Roboto-Light.ttf -------------------------------------------------------------------------------- /app/templates/app/fonts/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmaximini/generator-ionic-gulp/d2bd9d3bab1d58e29e5f9a638b9334c4b22143bc/app/templates/app/fonts/Roboto-Thin.ttf -------------------------------------------------------------------------------- /app/templates/app/icons/own-icons-template.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "<%= fontName %>"; 3 | src: url('<%= fontPath %><%= fontName %>.eot'); 4 | src: url('<%= fontPath %><%= fontName %>.eot?#iefix') format('eot'), 5 | url('<%= fontPath %><%= fontName %>.woff') format('woff'), 6 | url('<%= fontPath %><%= fontName %>.ttf') format('truetype'), 7 | url('<%= fontPath %><%= fontName %>.svg#<%= fontName %>') format('svg'); 8 | } 9 | 10 | .icon:before { 11 | font-family: "<%= fontName %>"; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | font-style: normal; 15 | font-variant: normal; 16 | font-weight: normal; 17 | /* speak: none; only necessary if not using the private unicode range (firstGlyph option) */ 18 | text-decoration: none; 19 | text-transform: none; 20 | } 21 | 22 | <% _.each(glyphs, function(glyph) { %> 23 | .icon-<%= glyph.fileName %>:before { 24 | content: "\<%= glyph.codePoint %>"; 25 | } 26 | <% }); %> 27 | -------------------------------------------------------------------------------- /app/templates/app/styles/_fonts.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Import fonts either via @import url (e.g. from Googlee Fonts) 3 | * or via @font-face when font files are stored locally in /app/fonts 4 | */ 5 | 6 | 7 | // @import url(http://fonts.googleapis.com/css?family=Roboto:700,400,300); 8 | 9 | @font-face { 10 | font-family: 'Roboto'; 11 | src: url(../fonts/Roboto-Light.ttf) format("truetype"); 12 | font-weight: 300; 13 | font-style: normal; 14 | } 15 | 16 | @font-face { 17 | font-family: 'Roboto'; 18 | src: url(../fonts/Roboto-Thin.ttf) format("truetype"); 19 | font-weight: 400; 20 | font-style: normal; 21 | } 22 | 23 | @font-face { 24 | font-family: 'Roboto'; 25 | src: url(../fonts/Roboto-Bold.ttf) format("truetype"); 26 | font-weight: 700; 27 | font-style: normal; 28 | } 29 | -------------------------------------------------------------------------------- /app/templates/app/styles/_variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Define variables here 3 | */ 4 | 5 | $textColor: #ccc; 6 | -------------------------------------------------------------------------------- /app/templates/app/styles/ionic-styles.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Override Ionic variables here 3 | * 4 | * e.g. $positive: #387ef5 !default; 5 | */ 6 | 7 | // Include all of Ionic for compilation 8 | @import 'bower_components/ionic/scss/ionic'; 9 | -------------------------------------------------------------------------------- /app/templates/app/styles/layout/layout.scss: -------------------------------------------------------------------------------- 1 | .loader { 2 | text-align: center; 3 | width: 100%; 4 | padding: 20px 0; 5 | } 6 | -------------------------------------------------------------------------------- /app/templates/app/styles/main.scss: -------------------------------------------------------------------------------- 1 | /************************************ 2 | * 3 | * Main Styles to compile. Here only @imports! 4 | * 5 | ************************************/ 6 | 7 | @import "_variables"; 8 | @import "_fonts"; 9 | 10 | /** 11 | * LAYOUT 12 | */ 13 | 14 | @import "layout/layout"; 15 | 16 | 17 | /** 18 | * MENU 19 | */ 20 | 21 | @import "menu/menu"; 22 | 23 | /** 24 | * VIEWS 25 | */ 26 | 27 | @import "views/home"; -------------------------------------------------------------------------------- /app/templates/app/styles/menu/menu.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmaximini/generator-ionic-gulp/d2bd9d3bab1d58e29e5f9a638b9334c4b22143bc/app/templates/app/styles/menu/menu.scss -------------------------------------------------------------------------------- /app/templates/app/styles/views/home.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | 3 | } 4 | 5 | .content { 6 | padding: 1rem; 7 | } -------------------------------------------------------------------------------- /app/templates/app/templates/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Side Menu

15 |
16 | 17 | 18 | 28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /app/templates/app/templates/views/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Settings

5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | Allow Push Notifications 15 | 16 | 17 | 18 | 19 | 20 | Allow cookies 21 | 22 | 23 | 24 |
25 |
26 | 27 |
28 | -------------------------------------------------------------------------------- /app/templates/bower.rc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /app/templates/editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /app/templates/gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | node_modules/ 5 | platforms/ 6 | plugins/ 7 | bower_components/ 8 | 9 | .tmp/ 10 | www/ 11 | .sass-cache 12 | *.DS_Store 13 | *.log 14 | -------------------------------------------------------------------------------- /app/templates/gitignore.browserify: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | node_modules/ 5 | platforms/ 6 | plugins/ 7 | bower_components/ 8 | 9 | .tmp/ 10 | www/ 11 | .sass-cache 12 | *.DS_Store 13 | *.log 14 | 15 | app/scripts/bundle.js 16 | app/scripts/bundle.js.map -------------------------------------------------------------------------------- /app/templates/helpers/emulateios: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export DEVICES=`ios-sim showdevicetypes 2>&1` 3 | export DEVICES=\"`echo $DEVICES | sed -e 's/ com./" "com./g' | sed -e 's/, /,~/g'`\" 4 | PS3='Please enter your choice: ' 5 | options=($DEVICES) 6 | curpath="$(cd "$(dirname "$1")"; pwd)/$(basename "$1")" 7 | app="`find $curpath/platforms/ios/build/emulator -name *.app -print`" 8 | escaped_app="\"$app\"" 9 | 10 | echo $app 11 | select opt in "${options[@]}" 12 | do 13 | case $opt in 14 | *) echo ios-sim launch "$escaped_app" --devicetypeid "`echo $opt | sed -e "s/~/ /g"`" --stderr ./platforms/ios/cordova/console.log --stdout ./platforms/ios/cordova/console.log > tmp.run.file;chmod +x tmp.run.file;./tmp.run.file;rm tmp.run.file;exit; 15 | esac 16 | done 17 | -------------------------------------------------------------------------------- /app/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

<%= title %>

5 |
6 | 7 | 8 | 11 | 12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /app/templates/hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | This directory may contain scripts used to customize cordova commands. This 24 | directory used to exist at `.cordova/hooks`, but has now been moved to the 25 | project root. Any scripts you add to these directories will be executed before 26 | and after the commands corresponding to the directory name. Useful for 27 | integrating your own build systems or integrating with version control systems. 28 | 29 | __Remember__: Make your scripts executable. 30 | 31 | ## Hook Directories 32 | The following subdirectories will be used for hooks: 33 | 34 | after_build/ 35 | after_compile/ 36 | after_docs/ 37 | after_emulate/ 38 | after_platform_add/ 39 | after_platform_rm/ 40 | after_platform_ls/ 41 | after_plugin_add/ 42 | after_plugin_ls/ 43 | after_plugin_rm/ 44 | after_plugin_search/ 45 | after_prepare/ 46 | after_run/ 47 | after_serve/ 48 | before_build/ 49 | before_compile/ 50 | before_docs/ 51 | before_emulate/ 52 | before_platform_add/ 53 | before_platform_rm/ 54 | before_platform_ls/ 55 | before_plugin_add/ 56 | before_plugin_ls/ 57 | before_plugin_rm/ 58 | before_plugin_search/ 59 | before_prepare/ 60 | before_run/ 61 | before_serve/ 62 | pre_package/ <-- Windows 8 and Windows Phone only. 63 | 64 | ## Script Interface 65 | 66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 67 | 68 | * CORDOVA_VERSION - The version of the Cordova-CLI. 69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 71 | * CORDOVA_HOOK - Path to the hook that is being executed. 72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 73 | 74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 75 | 76 | 77 | ## Writing hooks 78 | 79 | We highly recommend writting your hooks using Node.js so that they are 80 | cross-platform. Some good examples are shown here: 81 | 82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 83 | 84 | -------------------------------------------------------------------------------- /app/templates/hooks/after_prepare/010_add_platform_class.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Add Platform Class 4 | // v1.0 5 | // Automatically adds the platform class to the body tag 6 | // after the `prepare` command. By placing the platform CSS classes 7 | // directly in the HTML built for the platform, it speeds up 8 | // rendering the correct layout/style for the specific platform 9 | // instead of waiting for the JS to figure out the correct classes. 10 | 11 | var fs = require('fs'); 12 | var path = require('path'); 13 | 14 | var rootdir = process.argv[2]; 15 | 16 | function addPlatformBodyTag(indexPath, platform) { 17 | // add the platform class to the body tag 18 | try { 19 | var platformClass = 'platform-' + platform; 20 | var cordovaClass = 'platform-cordova platform-webview'; 21 | 22 | var html = fs.readFileSync(indexPath, 'utf8'); 23 | 24 | var bodyTag = findBodyTag(html); 25 | if(!bodyTag) return; // no opening body tag, something's wrong 26 | 27 | if(bodyTag.indexOf(platformClass) > -1) return; // already added 28 | 29 | var newBodyTag = bodyTag; 30 | 31 | var classAttr = findClassAttr(bodyTag); 32 | if(classAttr) { 33 | // body tag has existing class attribute, add the classname 34 | var endingQuote = classAttr.substring(classAttr.length-1); 35 | var newClassAttr = classAttr.substring(0, classAttr.length-1); 36 | newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote; 37 | newBodyTag = bodyTag.replace(classAttr, newClassAttr); 38 | 39 | } else { 40 | // add class attribute to the body tag 41 | newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">'); 42 | } 43 | 44 | html = html.replace(bodyTag, newBodyTag); 45 | 46 | fs.writeFileSync(indexPath, html, 'utf8'); 47 | 48 | process.stdout.write('add to body class: ' + platformClass + '\n'); 49 | } catch(e) { 50 | process.stdout.write(e); 51 | } 52 | } 53 | 54 | function findBodyTag(html) { 55 | // get the body tag 56 | try{ 57 | return html.match(/])(.*?)>/gi)[0]; 58 | }catch(e){} 59 | } 60 | 61 | function findClassAttr(bodyTag) { 62 | // get the body tag's class attribute 63 | try{ 64 | return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0]; 65 | }catch(e){} 66 | } 67 | 68 | if (rootdir) { 69 | 70 | // go through each of the platform directories that have been prepared 71 | var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); 72 | 73 | for(var x=0; x 2 | 3 | 4 | 5 | 6 | <%= title %> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/templates/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": false, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false, 23 | "cordova": false, 24 | "StatusBar": false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/templates/scripts/ApiService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name <%= ngModulName %>.ApiService 6 | * @description 7 | * # ApiService 8 | * Retrieves correct api to make requests against. 9 | * Uses settings from API_ENDPOINT defined in /config/apiEndpoint.js 10 | * 11 | * Usage example: $http({ 12 | * url: ApiService.getEndPoint() + '/things', 13 | * method: 'GET' 14 | * }) 15 | * 16 | */ 17 | angular.module('<%= ngModulName %>') 18 | .factory('ApiService', function($window, $http, API_ENDPOINT) { 19 | 20 | var _api = API_ENDPOINT; 21 | var endpoint = _api.port ? (_api.host + ':' + _api.port + _api.path) : (_api.host + _api.path); 22 | 23 | // activate for basic auth 24 | if (_api.needsAuth) { 25 | $http.defaults.headers.common.Authorization = 'Basic ' + $window.btoa(_api.username + ':' + _api.password); 26 | } 27 | 28 | // public api 29 | return { 30 | getEndpoint: function() { return endpoint; } 31 | }; 32 | 33 | }); 34 | 35 | -------------------------------------------------------------------------------- /app/templates/scripts/ExampleService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.service:ExampleService 6 | * @description 7 | * # ExampleService 8 | */ 9 | angular.module('<%= ngModulName %>') 10 | // use factory for services 11 | .factory('ExampleService', function($http, $timeout, $q) { 12 | 13 | var kindOfPrivateVariable = 42; 14 | 15 | var doSomethingAsync = function() { 16 | var deferred = $q.defer(); 17 | $timeout(deferred.resolve.bind(null, kindOfPrivateVariable), 1000); 18 | return deferred.promise; 19 | }; 20 | 21 | var fetchSomethingFromServer = function() { 22 | return $http({ 23 | url: 'http://hipsterjesus.com/api', 24 | params: { 25 | paras: 2 26 | }, 27 | method: 'GET' 28 | }) 29 | .success(function(data) { 30 | console.log('fetched this stuff from server:', data); 31 | }) 32 | .error(function(error) { 33 | console.log('an error occured', error); 34 | }); 35 | }; 36 | 37 | // public api 38 | return { 39 | doSomethingAsync: doSomethingAsync, 40 | fetchSomethingFromServer: fetchSomethingFromServer 41 | }; 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /app/templates/scripts/apiEndpoint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc constant 5 | * @name <%= ngModulName %>.API_ENDPOINT 6 | * @description 7 | * # API_ENDPOINT 8 | * Defines the API endpoint where our resources will make requests against. 9 | * Is used inside /services/ApiService.js to generate correct endpoint dynamically 10 | */ 11 | 12 | 13 | angular.module('<%= ngModulName %>') 14 | 15 | // development 16 | .constant('API_ENDPOINT', { 17 | host: 'http://localhost', 18 | port: 3000, 19 | path: '', 20 | needsAuth: false 21 | }); 22 | 23 | 24 | // live example with HTTP Basic Auth 25 | /* 26 | .constant('API_ENDPOINT', { 27 | host: 'http://yourserver.com', 28 | path: '/api/v2', 29 | needsAuth: true, 30 | username: 'whatever', 31 | password: 'foobar' 32 | }); 33 | */ 34 | 35 | -------------------------------------------------------------------------------- /app/templates/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc overview 5 | * @name <%= ngModulName %> 6 | * @description 7 | * # Initializes main application and routing 8 | * 9 | * Main module of the application. 10 | */ 11 | 12 | 13 | angular.module('<%= ngModulName %>', ['ionic', 'ngCordova', 'ngResource']) 14 | 15 | .run(function($ionicPlatform) { 16 | 17 | $ionicPlatform.ready(function() { 18 | // save to use plugins here 19 | }); 20 | 21 | // add possible global event handlers here 22 | 23 | }) 24 | 25 | .config(function($httpProvider, $stateProvider, $urlRouterProvider) { 26 | // register $http interceptors, if any. e.g. 27 | // $httpProvider.interceptors.push('interceptor-name'); 28 | 29 | // Application routing 30 | $stateProvider 31 | .state('app', { 32 | url: '/app', 33 | abstract: true, 34 | templateUrl: 'templates/main.html', 35 | controller: 'MainController' 36 | }) 37 | .state('app.home', { 38 | url: '/home', 39 | cache: true, 40 | views: { 41 | 'viewContent': { 42 | templateUrl: 'templates/views/home.html', 43 | controller: 'HomeController' 44 | } 45 | } 46 | }) 47 | .state('app.settings', { 48 | url: '/settings', 49 | cache: true, 50 | views: { 51 | 'viewContent': { 52 | templateUrl: 'templates/views/settings.html', 53 | controller: 'SettingsController' 54 | } 55 | } 56 | }); 57 | 58 | 59 | // redirects to default route for undefined routes 60 | $urlRouterProvider.otherwise('/app/home'); 61 | }); 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/templates/scripts/homeController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:HomeController 6 | * @description 7 | * # HomeController 8 | */ 9 | angular.module('<%= ngModulName %>') 10 | .controller('HomeController', function($scope, ExampleService) { 11 | 12 | $scope.myHTML = null; 13 | 14 | // just an example... 15 | $scope.fetchRandomText = function() { 16 | ExampleService.doSomethingAsync() 17 | .then(ExampleService.fetchSomethingFromServer) 18 | .then(function(response) { 19 | $scope.myHTML = response.data.text; 20 | // close pull to refresh loader 21 | $scope.$broadcast('scroll.refreshComplete'); 22 | }); 23 | }; 24 | 25 | $scope.fetchRandomText(); 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /app/templates/scripts/lodash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.util:lodash 6 | * @description 7 | * # Lo-Dash 8 | * Expose Lo-Dash through injectable factory, so we don't pollute / rely on global namespace 9 | * just inject lodash as _ 10 | */ 11 | 12 | angular.module('<%= ngModulName %>') 13 | .factory('_', function($window) { 14 | return $window._; 15 | }); 16 | -------------------------------------------------------------------------------- /app/templates/scripts/mainController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:MainController 6 | * @description 7 | * # MainController 8 | */ 9 | angular.module('<%= ngModulName %>') 10 | .controller('MainController', function($scope) { 11 | 12 | // do something with $scope 13 | 14 | }); 15 | -------------------------------------------------------------------------------- /app/templates/scripts/settingsController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:SettingsController 6 | * @description 7 | * # SettingsController 8 | */ 9 | angular.module('<%= ngModulName %>') 10 | .controller('SettingsController', function($scope) { 11 | 12 | // do something with $scope 13 | 14 | }); 15 | -------------------------------------------------------------------------------- /app/templates/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmaximini/generator-ionic-gulp/d2bd9d3bab1d58e29e5f9a638b9334c4b22143bc/app/templates/splash.png -------------------------------------------------------------------------------- /app/templates/src/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc overview 5 | * @name <%= ngModulName %> 6 | * @description 7 | * # Initializes main application and routing 8 | * 9 | * Main module of the application. 10 | */ 11 | 12 | // Example to require lodash 13 | // This is resolved and bundled by browserify 14 | // 15 | // var _ = require( 'lodash' ); 16 | 17 | angular.module( '<%= ngModulName %>', [ 18 | 'ionic', 19 | 'ngCordova', 20 | 'ngResource' 21 | ] ) 22 | .run( [ 23 | '$ionicPlatform', 24 | 25 | function( $ionicPlatform ) 26 | { 27 | 28 | $ionicPlatform.ready(function() { 29 | // save to use plugins here 30 | }); 31 | 32 | // add possible global event handlers here 33 | 34 | } ] ) 35 | 36 | .config( [ 37 | '$httpProvider', 38 | '$stateProvider', 39 | '$urlRouterProvider', 40 | 41 | function( $httpProvider, $stateProvider, $urlRouterProvider ) 42 | { 43 | // register $http interceptors, if any. e.g. 44 | // $httpProvider.interceptors.push('interceptor-name'); 45 | 46 | // Application routing 47 | $stateProvider 48 | .state('app', { 49 | url: '/app', 50 | abstract: true, 51 | templateUrl: 'templates/main.html', 52 | controller: 'MainController' 53 | }) 54 | .state('app.home', { 55 | url: '/home', 56 | cache: true, 57 | views: { 58 | 'viewContent': { 59 | templateUrl: 'templates/views/home.html', 60 | controller: 'HomeController' 61 | } 62 | } 63 | }) 64 | .state('app.settings', { 65 | url: '/settings', 66 | cache: true, 67 | views: { 68 | 'viewContent': { 69 | templateUrl: 'templates/views/settings.html', 70 | controller: 'SettingsController' 71 | } 72 | } 73 | }); 74 | 75 | 76 | // redirects to default route for undefined routes 77 | $urlRouterProvider.otherwise('/app/home'); 78 | } 79 | ] ) 80 | 81 | // Angular module controllers 82 | // 83 | .controller( 'MainController', require( './controllers/mainController' ) ) 84 | .controller( 'HomeController', require( './controllers/homeController' ) ) 85 | .controller( 'SettingsController', require( './controllers/settingsController' ) ) 86 | 87 | // Angular module services 88 | // 89 | .factory( 'ExampleService', require( './services/ExampleService' ) ) 90 | .factory( 'ApiService', require( './services/ApiService' ) ) 91 | ; 92 | -------------------------------------------------------------------------------- /app/templates/src/controllers/homeController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:HomeController 6 | * @description 7 | * # HomeController 8 | */ 9 | module.exports = [ 10 | '$scope', 11 | 'ExampleService', 12 | 13 | function( $scope, ExampleService ) 14 | { 15 | $scope.myHTML = null; 16 | 17 | // just an example... 18 | $scope.fetchRandomText = function() { 19 | ExampleService.doSomethingAsync() 20 | .then(ExampleService.fetchSomethingFromServer) 21 | .then(function(response) { 22 | $scope.myHTML = response.data.text; 23 | // close pull to refresh loader 24 | $scope.$broadcast('scroll.refreshComplete'); 25 | }); 26 | }; 27 | 28 | $scope.fetchRandomText(); 29 | } 30 | ]; 31 | -------------------------------------------------------------------------------- /app/templates/src/controllers/mainController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:MainController 6 | * @description 7 | * # MainController 8 | */ 9 | module.exports = [ 10 | '$scope', 11 | 12 | function( $scope ) 13 | { 14 | // do something with $scope 15 | } 16 | ]; 17 | -------------------------------------------------------------------------------- /app/templates/src/controllers/settingsController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.controller:SettingsController 6 | * @description 7 | * # SettingsController 8 | */ 9 | module.exports = [ 10 | '$scope', 11 | 12 | function( $scope ) 13 | { 14 | // do something with $scope 15 | } 16 | ]; 17 | -------------------------------------------------------------------------------- /app/templates/src/services/ApiService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name <%= ngModulName %>.ApiService 6 | * @description 7 | * # ApiService 8 | * Retrieves correct api to make requests against. 9 | * Uses settings from API_ENDPOINT defined in /config/apiEndpoint.js 10 | * 11 | * Usage example: $http({ 12 | * url: ApiService.getEndPoint() + '/things', 13 | * method: 'GET' 14 | * }) 15 | * 16 | */ 17 | module.exports = [ 18 | '$window', 19 | '$http', 20 | 'API_ENDPOINT', 21 | 22 | function( $window, $http, API_ENDPOINT ) 23 | { 24 | var _api = API_ENDPOINT; 25 | var endpoint = _api.port ? (_api.host + ':' + _api.port + _api.path) : (_api.host + _api.path); 26 | 27 | // activate for basic auth 28 | if (_api.needsAuth) { 29 | $http.defaults.headers.common.Authorization = 'Basic ' + $window.btoa(_api.username + ':' + _api.password); 30 | } 31 | 32 | // public api 33 | return { 34 | getEndpoint: function() { return endpoint; } 35 | }; 36 | } 37 | ]; 38 | -------------------------------------------------------------------------------- /app/templates/src/services/ExampleService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name <%= ngModulName %>.service:ExampleService 6 | * @description 7 | * # ExampleService 8 | */ 9 | module.exports = [ 10 | '$http', 11 | '$timeout', 12 | '$q', 13 | 14 | function( $http, $timeout, $q ) 15 | { 16 | var kindOfPrivateVariable = 42; 17 | 18 | var doSomethingAsync = function() { 19 | var deferred = $q.defer(); 20 | $timeout(deferred.resolve.bind(null, kindOfPrivateVariable), 1000); 21 | return deferred.promise; 22 | }; 23 | 24 | var fetchSomethingFromServer = function() { 25 | return $http({ 26 | url: 'http://hipsterjesus.com/api', 27 | params: { 28 | paras: 2 29 | }, 30 | method: 'GET' 31 | }) 32 | .success(function(data) { 33 | console.log('fetched this stuff from server:', data); 34 | }) 35 | .error(function(error) { 36 | console.log('an error occured', error); 37 | }); 38 | }; 39 | 40 | // public api 41 | return { 42 | doSomethingAsync: doSomethingAsync, 43 | fetchSomethingFromServer: fetchSomethingFromServer 44 | }; 45 | } 46 | ]; 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-ionic-gulp", 3 | "version": "1.5.2", 4 | "description": "A Yeoman generator for Ionic projects with gulp", 5 | "license": "MIT", 6 | "main": "app/index.js", 7 | "repository": "tmaximini/generator-ionic-gulp", 8 | "author": { 9 | "name": "Thomas Maximini", 10 | "email": "tmaximini@gmail.com", 11 | "url": "https://github.com/tmaximini" 12 | }, 13 | "engines": { 14 | "node": ">=0.10.0" 15 | }, 16 | "scripts": { 17 | "test": "mocha" 18 | }, 19 | "files": [ 20 | "app" 21 | ], 22 | "keywords": [ 23 | "yeoman-generator", 24 | "ionic", 25 | "gulp", 26 | "ionic framework" 27 | ], 28 | "dependencies": { 29 | "yeoman-generator": "^0.18.0", 30 | "chalk": "^0.5.0", 31 | "yosay": "^0.3.0" 32 | }, 33 | "devDependencies": { 34 | "mocha": "*" 35 | }, 36 | "peerDependencies": { 37 | "yo": ">=1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/test-app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assert = require('yeoman-generator').assert; 5 | var helpers = require('yeoman-generator').test; 6 | var os = require('os'); 7 | 8 | describe('ionic-gulp:app', function () { 9 | before(function (done) { 10 | helpers.run(path.join(__dirname, '../app')) 11 | .inDir(path.join(os.tmpdir(), './temp-test')) 12 | .withOptions({ 'skip-install': true }) 13 | .withPrompt({ 14 | someOption: true 15 | }) 16 | .on('end', done); 17 | }); 18 | 19 | it('creates files', function () { 20 | assert.file([ 21 | 'bower.json', 22 | 'package.json', 23 | '.editorconfig', 24 | '.jshintrc' 25 | ]); 26 | }); 27 | }); 28 | --------------------------------------------------------------------------------