
-
7 |
-
8 | 9 |10 | 404Page Not Found 11 |12 | 13 |
14 |
├── .bowerrc
├── .editorconfig
├── .gitignore
├── .jscsrc
├── .jshintrc
├── .travis.yml
├── README.md
├── bower.json
├── gulp.config.js
├── gulp.png
├── gulpfile.js
├── jsconfig.json
├── karma.conf.js
├── package.json
├── src
├── client
│ ├── app
│ │ ├── app.module.js
│ │ ├── blocks
│ │ │ ├── diagnostics
│ │ │ │ ├── diagnostics.decorator.js
│ │ │ │ └── diagnostics.module.js
│ │ │ ├── exception
│ │ │ │ ├── exception-handler.provider.js
│ │ │ │ ├── exception-handler.provider.spec.js
│ │ │ │ ├── exception.js
│ │ │ │ └── exception.module.js
│ │ │ ├── logger
│ │ │ │ ├── logger.js
│ │ │ │ └── logger.module.js
│ │ │ └── router
│ │ │ │ ├── router-helper.provider.js
│ │ │ │ └── router.module.js
│ │ ├── core
│ │ │ ├── 404.html
│ │ │ ├── config.js
│ │ │ ├── constants.js
│ │ │ ├── core.module.js
│ │ │ ├── core.route.js
│ │ │ ├── core.route.spec.js
│ │ │ ├── dataservice.js
│ │ │ └── dataservice.spec.js
│ │ ├── customers
│ │ │ ├── customer-detail.controller.js
│ │ │ ├── customer-detail.controller.spec.js
│ │ │ ├── customer-detail.html
│ │ │ ├── customers.controller.js
│ │ │ ├── customers.controller.spec.js
│ │ │ ├── customers.html
│ │ │ ├── customers.module.js
│ │ │ ├── customers.route.js
│ │ │ └── customers.route.spec.js
│ │ ├── dashboard
│ │ │ ├── dashboard.controller.js
│ │ │ ├── dashboard.controller.spec.js
│ │ │ ├── dashboard.html
│ │ │ ├── dashboard.module.js
│ │ │ ├── dashboard.route.js
│ │ │ └── dashboard.route.spec.js
│ │ ├── layout
│ │ │ ├── ht-sidebar.directive.js
│ │ │ ├── ht-sidebar.directive.spec.js
│ │ │ ├── ht-top-nav.directive.js
│ │ │ ├── ht-top-nav.html
│ │ │ ├── layout.module.js
│ │ │ ├── shell.controller.js
│ │ │ ├── shell.controller.spec.js
│ │ │ ├── shell.html
│ │ │ ├── sidebar.controller.js
│ │ │ ├── sidebar.controller.spec.js
│ │ │ └── sidebar.html
│ │ └── widgets
│ │ │ ├── ht-img-person.directive.js
│ │ │ ├── ht-widget-header.directive.js
│ │ │ ├── widget-header.html
│ │ │ └── widgets.module.js
│ ├── images
│ │ ├── AngularJS-small.png
│ │ ├── busy.gif
│ │ ├── gulp-tiny.png
│ │ └── photos
│ │ │ ├── aaron_skonnard.jpg
│ │ │ ├── anant-narayanan.png
│ │ │ ├── ari-lerner.png
│ │ │ ├── ben-clinkinbeard.png
│ │ │ ├── ben-teese.png
│ │ │ ├── brad_green.jpg
│ │ │ ├── brian-ford.png
│ │ │ ├── burke-holland.png
│ │ │ ├── cat.jpg
│ │ │ ├── christian-lilley.png
│ │ │ ├── colleen_papa.jpg
│ │ │ ├── craig_shoemaker.jpg
│ │ │ ├── dan_wahlin.jpg
│ │ │ ├── dave-smith.png
│ │ │ ├── dave_ward.jpg
│ │ │ ├── elijah_manor.jpg
│ │ │ ├── eric_barnard.jpg
│ │ │ ├── esteban_garcia.jpg
│ │ │ ├── felix_fanboi.jpg
│ │ │ ├── fritz_onion.jpg
│ │ │ ├── glenn_block.jpg
│ │ │ ├── hans_fjallemark.jpg
│ │ │ ├── howard_dierking.jpg
│ │ │ ├── igor_minar.jpg
│ │ │ ├── james-deboer.png
│ │ │ ├── jason-aden.png
│ │ │ ├── jason_salmond.jpg
│ │ │ ├── jeff-cross.png
│ │ │ ├── jesse_liberty.jpg
│ │ │ ├── jim_cowart.jpg
│ │ │ ├── john-lindquist.png
│ │ │ ├── john_papa.jpg
│ │ │ ├── john_smith.jpg
│ │ │ ├── john_sonmez.jpg
│ │ │ ├── julie-ralph.png
│ │ │ ├── julie_lerman.jpg
│ │ │ ├── keith_sparkjoy.jpg
│ │ │ ├── lukas-ruebbelke.png
│ │ │ ├── mads_kristensen.jpg
│ │ │ ├── matias-niemela.png
│ │ │ ├── max-lynch.png
│ │ │ ├── megan_russell.jpg
│ │ │ ├── mike_callaghan.jpg
│ │ │ ├── mike_woodring.jpg
│ │ │ ├── misko-hevery.png
│ │ │ ├── pete_brown.jpg
│ │ │ ├── rey_bango.jpg
│ │ │ ├── rob_eisenberg.jpg
│ │ │ ├── ron-evans.png
│ │ │ ├── ryan_niemeyer.jpg
│ │ │ ├── scott_guthrie.jpg
│ │ │ ├── scott_hanselman.jpg
│ │ │ ├── scott_hunter.jpg
│ │ │ ├── sean-hess.png
│ │ │ ├── sharon-diorio.png
│ │ │ ├── shawn_wildermuth.jpg
│ │ │ ├── silvano-luciani.png
│ │ │ ├── steve_sanderson.jpg
│ │ │ ├── sue_menot.jpg
│ │ │ ├── thomas-burleson.png
│ │ │ ├── tim_heuer.jpg
│ │ │ ├── unknown_person.jpg
│ │ │ ├── vojta-jina.png
│ │ │ ├── ward-bell.png
│ │ │ └── ward_bell.jpg
│ ├── index.html
│ ├── specs.html
│ ├── stubs
│ │ ├── pass-throughs.js
│ │ ├── stubs.config.js
│ │ └── stubs.js
│ ├── styles
│ │ └── styles.less
│ ├── test-helpers
│ │ ├── bind-polyfill.js
│ │ └── mock-data.js
│ └── tests
│ │ └── server-integration
│ │ └── dataservice.spec.js
└── server
│ ├── app.js
│ ├── data
│ └── customers.json
│ ├── favicon.ico
│ ├── routes
│ └── index.js
│ └── utils
│ ├── 404.js
│ ├── errorHandler.js
│ └── jsonfileservice.js
├── tsd.json
└── typings
├── angular-ui-router
└── angular-ui-router.d.ts
├── angularjs
├── angular-animate.d.ts
├── angular-mocks.d.ts
├── angular-sanitize.d.ts
└── angular.d.ts
├── bardjs
└── bardjs.d.ts
├── bootstrap
└── bootstrap.d.ts
├── chai-shim.d.ts
├── chai
└── chai.d.ts
├── jquery
└── jquery.d.ts
├── mocha
└── mocha.d.ts
├── moment
├── moment-node.d.ts
└── moment.d.ts
├── sinon
└── sinon.d.ts
├── toastr
└── toastr.d.ts
└── tsd.d.ts
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "scripts": {
4 | "postinstall": "gulp wiredep"
5 | }
6 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 |
13 | [*.md]
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Visual Studio Project #
2 | ###################
3 | *.user
4 | *.gpState
5 | *.suo
6 | bin
7 | obj
8 | /packages
9 |
10 | # Ignore Node, Bower & TSD
11 | ##########################
12 | node_modules
13 | bower_components
14 | #typings
15 | build
16 | .tmp
17 |
18 | # Ignore Test reporters
19 | ###################
20 | **/test/coverage
21 | report
22 |
23 |
24 | # mongo db
25 | ###################
26 | #Don't commit Mongo Database files
27 | *.lock
28 | *.0
29 | *.1
30 | *.ns
31 | journal
32 |
33 | # Ignore Web Storm #
34 | .idea
35 |
36 | # Compiled source #
37 | ###################
38 | *.com
39 | *.class
40 | *.dll
41 | *.exe
42 | *.o
43 | *.so
44 |
45 | # Packages #
46 | ############
47 | # it's better to unpack these files and commit the raw source
48 | # git has its own built in compression methods
49 | *.7z
50 | *.dmg
51 | *.gz
52 | *.iso
53 | *.jar
54 | *.rar
55 | *.tar
56 | *.xap
57 | *.zip
58 |
59 | # Logs and databases #
60 | ######################
61 | *.log
62 | *.sql
63 | *.sqlite
64 | # *.sdf
65 | *.mdf
66 | *.ldf
67 |
68 | # OS generated files #
69 | ######################
70 | .DS_Store*
71 | ehthumbs.db
72 | Icon?
73 | Thumbs.db
74 |
75 |
--------------------------------------------------------------------------------
/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "excludeFiles": ["node_modules/**", "bower_components/**"],
3 |
4 | "requireCurlyBraces": [
5 | "if",
6 | "else",
7 | "for",
8 | "while",
9 | "do",
10 | "try",
11 | "catch"
12 | ],
13 | "requireOperatorBeforeLineBreak": true,
14 | "requireCamelCaseOrUpperCaseIdentifiers": true,
15 | "maximumLineLength": {
16 | "value": 100,
17 | "allowComments": true,
18 | "allowRegex": true
19 | },
20 | "validateIndentation": 4,
21 | "validateQuoteMarks": "'",
22 |
23 | "disallowMultipleLineStrings": true,
24 | "disallowMixedSpacesAndTabs": true,
25 | "disallowTrailingWhitespace": true,
26 | "disallowSpaceAfterPrefixUnaryOperators": true,
27 | "disallowMultipleVarDecl": null,
28 |
29 | "requireSpaceAfterKeywords": [
30 | "if",
31 | "else",
32 | "for",
33 | "while",
34 | "do",
35 | "switch",
36 | "return",
37 | "try",
38 | "catch"
39 | ],
40 | "requireSpaceBeforeBinaryOperators": [
41 | "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
42 | "&=", "|=", "^=", "+=",
43 |
44 | "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
45 | "|", "^", "&&", "||", "===", "==", ">=",
46 | "<=", "<", ">", "!=", "!=="
47 | ],
48 | "requireSpaceAfterBinaryOperators": true,
49 | "requireSpacesInConditionalExpression": true,
50 | "requireSpaceBeforeBlockStatements": true,
51 | "requireLineFeedAtFileEnd": true,
52 | "disallowSpacesInsideObjectBrackets": "all",
53 | "disallowSpacesInsideArrayBrackets": "all",
54 | "disallowSpacesInsideParentheses": true,
55 |
56 | "jsDoc": {
57 | "checkAnnotations": true,
58 | "checkParamNames": true,
59 | "requireParamTypes": true,
60 | "checkReturnTypes": true,
61 | "checkTypes": true
62 | },
63 |
64 | "disallowMultipleLineBreaks": true,
65 |
66 | "disallowCommaBeforeLineBreak": null,
67 | "disallowDanglingUnderscores": null,
68 | "disallowEmptyBlocks": null,
69 | "disallowMultipleLineStrings": null,
70 | "disallowTrailingComma": null,
71 | "requireCommaBeforeLineBreak": null,
72 | "requireDotNotation": null,
73 | "requireMultipleVarDecl": null,
74 | "requireParenthesesAroundIIFE": true
75 | }
76 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "camelcase": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "es3": false,
7 | "forin": true,
8 | "freeze": true,
9 | "immed": true,
10 | "indent": 4,
11 | "latedef": "nofunc",
12 | "newcap": true,
13 | "noarg": true,
14 | "noempty": true,
15 | "nonbsp": true,
16 | "nonew": true,
17 | "plusplus": false,
18 | "quotmark": "single",
19 | "undef": true,
20 | "unused": false,
21 | "strict": false,
22 | "maxparams": 10,
23 | "maxdepth": 5,
24 | "maxstatements": 40,
25 | "maxcomplexity": 8,
26 | "maxlen": 120,
27 |
28 | "asi": false,
29 | "boss": false,
30 | "debug": false,
31 | "eqnull": true,
32 | "esnext": false,
33 | "evil": false,
34 | "expr": false,
35 | "funcscope": false,
36 | "globalstrict": false,
37 | "iterator": false,
38 | "lastsemic": false,
39 | "laxbreak": false,
40 | "laxcomma": false,
41 | "loopfunc": true,
42 | "maxerr": 50,
43 | "moz": false,
44 | "multistr": false,
45 | "notypeof": false,
46 | "proto": false,
47 | "scripturl": false,
48 | "shadow": false,
49 | "sub": true,
50 | "supernew": false,
51 | "validthis": false,
52 | "noyield": false,
53 |
54 | "browser": true,
55 | "node": true,
56 |
57 | "globals": {
58 | "angular": false
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.10"
4 |
5 | branches:
6 | only:
7 | - master
8 |
9 | before_install:
10 | - npm install bower -g
11 | - npm install gulp -g
12 |
13 | script:
14 | - npm install
15 | - bower install
16 | - gulp test --verbose
17 |
18 | cache:
19 | directories:
20 | - bower_components
21 | - node_modules
22 |
23 | notifications:
24 | email:
25 | - wardbell@hotmail.com
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gulp-patterns
2 | You've built your JavaScript application but how do you automate testing, code analysis, running it locally or deploying it? These redundant tasks can consume valuable time and resources. Stop working so hard and take advantage of JavaScript task automation using Gulp to streamline these tasks and give you back more time in the day. Studying this repo can help clarify how Gulp works, jump-start task automation with Gulp, find and resolve issues faster, and be a more productive.
3 |
4 | [](https://travis-ci.org/johnpapa/gulp-patterns)
5 |
6 | [](https://codeship.io/projects/54583)
7 |
8 | ## Requirements
9 |
10 | - Install Node
11 | - on OSX install [home brew](http://brew.sh/) and type `brew install node`
12 | - on Windows install [chocolatey](https://chocolatey.org/)
13 | - More tips on [Windows with node](http://jpapa.me/winnode)
14 | - open command prompt as administrator
15 | - type `choco install nodejs`
16 | - type `choco install nodejs.install`
17 | - On OSX you can alleviate the need to run as sudo by [following these instructions](http://jpapa.me/nomoresudo). I highly recommend this step on OSX
18 | - Open terminal
19 | - Type `npm install -g node-inspector bower gulp tsd`
20 |
21 | ## Quick Start
22 | Clone this repo and run the content locally
23 | ```bash
24 | $ npm install
25 | $ bower install
26 | $ tsd install -r -o --save
27 | $ gulp serve-dev
28 | ```
29 |
30 | ## Tasks
31 |
32 | ### Task Listing
33 |
34 | - `gulp help`
35 |
36 | Displays all of the available gulp tasks.
37 |
38 | ### Code Analysis
39 |
40 | - `gulp vet`
41 |
42 | Performs static code analysis on all javascript files. Runs jshint and jscs.
43 |
44 | - `gulp vet --verbose`
45 |
46 | Displays all files affected and extended information about the code analysis.
47 |
48 | - `gulp plato`
49 |
50 | Performs code analysis using plato on all javascript files. Plato generates a report in the reports folder.
51 |
52 | ### Testing
53 |
54 | - `gulp serve-specs`
55 |
56 | Serves and browses to the spec runner html page and runs the unit tests in it. Injects any changes on the fly and re runs the tests. Quick and easy view of tests as an alternative to terminal via `gulp test`.
57 |
58 | - `gulp test`
59 |
60 | Runs all unit tests using karma runner, mocha, chai and sinon with phantomjs. Depends on vet task, for code analysis.
61 |
62 | - `gulp test --startServers`
63 |
64 | Runs all unit tests and midway tests. Cranks up a second node process to run a server for the midway tests to hit a web api.
65 |
66 | - `gulp autotest`
67 |
68 | Runs a watch to run all unit tests.
69 |
70 | - `gulp autotest --startServers`
71 |
72 | Runs a watch to run all unit tests and midway tests. Cranks up a second node process to run a server for the midway tests to hit a web api.
73 |
74 | ### Cleaning Up
75 |
76 | - `gulp clean`
77 |
78 | Remove all files from the build and temp folders
79 |
80 | - `gulp clean-images`
81 |
82 | Remove all images from the build folder
83 |
84 | - `gulp clean-code`
85 |
86 | Remove all javascript and html from the build folder
87 |
88 | - `gulp clean-fonts`
89 |
90 | Remove all fonts from the build folder
91 |
92 | - `gulp clean-styles`
93 |
94 | Remove all styles from the build folder
95 |
96 | ### Fonts and Images
97 |
98 | - `gulp fonts`
99 |
100 | Copy all fonts from source to the build folder
101 |
102 | - `gulp images`
103 |
104 | Copy all images from source to the build folder
105 |
106 | ### Styles
107 |
108 | - `gulp styles`
109 |
110 | Compile less files to CSS, add vendor prefixes, and copy to the build folder
111 |
112 | ### Bower Files
113 |
114 | - `gulp wiredep`
115 |
116 | Looks up all bower components' main files and JavaScript source code, then adds them to the `index.html`.
117 |
118 | The `.bowerrc` file also runs this as a postinstall task whenever `bower install` is run.
119 |
120 | ### Angular HTML Templates
121 |
122 | - `gulp templatecache`
123 |
124 | Create an Angular module that adds all HTML templates to Angular's $templateCache. This pre-fetches all HTML templates saving XHR calls for the HTML.
125 |
126 | - `gulp templatecache --verbose`
127 |
128 | Displays all files affected by the task.
129 |
130 | ### Serving Development Code
131 |
132 | - `gulp serve-dev`
133 |
134 | Serves the development code and launches it in a browser. The goal of building for development is to do it as fast as possible, to keep development moving efficiently. This task serves all code from the source folders and compiles less to css in a temp folder.
135 |
136 | - `gulp serve-dev --nosync`
137 |
138 | Serves the development code without launching the browser.
139 |
140 | - `gulp serve-dev --debug`
141 |
142 | Launch debugger with node-inspector.
143 |
144 | - `gulp serve-dev --debug-brk`
145 |
146 | Launch debugger and break on 1st line with node-inspector.
147 |
148 | - `gulp serve-dev --stubs`
149 |
150 | Serves the development code with the stubs to avoid hitting a real backend
151 |
152 | ### Building Production Code
153 |
154 | - `gulp optimize`
155 |
156 | Optimize all javascript and styles, move to a build folder, and inject them into the new index.html
157 |
158 | - `gulp build`
159 |
160 | Copies all fonts, copies images and runs `gulp optimize` to build the production code to the build folder.
161 |
162 | ### Serving Production Code
163 |
164 | - `gulp serve-build`
165 |
166 | Serve the optimized code from the build folder and launch it in a browser.
167 |
168 | - `gulp serve-build --nosync`
169 |
170 | Serve the optimized code from the build folder and manually launch the browser.
171 |
172 | - `gulp serve-build --debug`
173 |
174 | Launch debugger with node-inspector.
175 |
176 | - `gulp serve-build --debug-brk`
177 |
178 | Launch debugger and break on 1st line with node-inspector.
179 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Gulp-Patterns-Demo",
3 | "version": "0.1.1",
4 | "description": "Gulp Patterns Demo",
5 | "authors": [
6 | "John Papa"
7 | ],
8 | "license": "MIT",
9 | "homepage": "https://github.com/johnpapa/gulp-patterns",
10 | "ignore": [
11 | "**/.*",
12 | "node_modules",
13 | "bower_components",
14 | "test",
15 | "tests"
16 | ],
17 | "devDependencies": {
18 | "angular-mocks": "~1.3.8",
19 | "sinon": "http://sinonjs.org/releases/sinon-1.12.1.js",
20 | "bardjs": "~0.0.8"
21 | },
22 | "dependencies": {
23 | "jquery": "~2.1.1",
24 | "angular": "~1.3.8",
25 | "angular-sanitize": "~1.3.8",
26 | "bootstrap": "~3.3.1",
27 | "extras.angular.plus": "~0.9.2",
28 | "font-awesome": "~4.2.0",
29 | "moment": "~2.8.4",
30 | "angular-ui-router": "~0.2.13",
31 | "toastr": "~2.1.0",
32 | "angular-animate": "~1.3.8"
33 | },
34 | "overrides": {
35 | "bootstrap": {
36 | "main": "dist/css/bootstrap.css",
37 | "dist": "dist/js/bootstrap.js"
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/gulp.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | var client = './src/client/';
3 | var server = './src/server/';
4 | var clientApp = client + 'app/';
5 | var report = './report/';
6 | var root = './';
7 | var specRunnerFile = 'specs.html';
8 | var temp = './.tmp/';
9 | var wiredep = require('wiredep');
10 | var bowerFiles = wiredep({devDependencies: true})['js'];
11 | var bower = {
12 | json: require('./bower.json'),
13 | directory: './bower_components/',
14 | ignorePath: '../..'
15 | };
16 | var nodeModules = 'node_modules';
17 |
18 | var config = {
19 | /**
20 | * File paths
21 | */
22 | // all javascript that we want to vet
23 | alljs: [
24 | './src/**/*.js',
25 | './*.js'
26 | ],
27 | build: './build/',
28 | client: client,
29 | css: temp + 'styles.css',
30 | fonts: bower.directory + 'font-awesome/fonts/**/*.*',
31 | html: client + '**/*.html',
32 | htmltemplates: clientApp + '**/*.html',
33 | images: client + 'images/**/*.*',
34 | index: client + 'index.html',
35 | // app js, with no specs
36 | js: [
37 | clientApp + '**/*.module.js',
38 | clientApp + '**/*.js',
39 | '!' + clientApp + '**/*.spec.js'
40 | ],
41 | jsOrder: [
42 | '**/app.module.js',
43 | '**/*.module.js',
44 | '**/*.js'
45 | ],
46 | less: client + 'styles/styles.less',
47 | report: report,
48 | root: root,
49 | server: server,
50 | source: 'src/',
51 | stubsjs: [
52 | bower.directory + 'angular-mocks/angular-mocks.js',
53 | client + 'stubs/**/*.js'
54 | ],
55 | temp: temp,
56 |
57 | /**
58 | * optimized files
59 | */
60 | optimized: {
61 | app: 'app.js',
62 | lib: 'lib.js'
63 | },
64 |
65 | /**
66 | * plato
67 | */
68 | plato: {js: clientApp + '**/*.js'},
69 |
70 | /**
71 | * browser sync
72 | */
73 | browserReloadDelay: 1000,
74 |
75 | /**
76 | * template cache
77 | */
78 | templateCache: {
79 | file: 'templates.js',
80 | options: {
81 | module: 'app.core',
82 | root: 'app/',
83 | standAlone: false
84 | }
85 | },
86 |
87 | /**
88 | * Bower and NPM files
89 | */
90 | bower: bower,
91 | packages: [
92 | './package.json',
93 | './bower.json'
94 | ],
95 |
96 | /**
97 | * specs.html, our HTML spec runner
98 | */
99 | specRunner: client + specRunnerFile,
100 | specRunnerFile: specRunnerFile,
101 |
102 | /**
103 | * The sequence of the injections into specs.html:
104 | * 1 testlibraries
105 | * mocha setup
106 | * 2 bower
107 | * 3 js
108 | * 4 spechelpers
109 | * 5 specs
110 | * 6 templates
111 | */
112 | testlibraries: [
113 | nodeModules + '/mocha/mocha.js',
114 | nodeModules + '/chai/chai.js',
115 | nodeModules + '/sinon-chai/lib/sinon-chai.js'
116 | ],
117 | specHelpers: [client + 'test-helpers/*.js'],
118 | specs: [clientApp + '**/*.spec.js'],
119 | serverIntegrationSpecs: [client + '/tests/server-integration/**/*.spec.js'],
120 |
121 | /**
122 | * Node settings
123 | */
124 | nodeServer: './src/server/app.js',
125 | defaultPort: '7203'
126 | };
127 |
128 | /**
129 | * wiredep and bower settings
130 | */
131 | config.getWiredepDefaultOptions = function() {
132 | var options = {
133 | bowerJson: config.bower.json,
134 | directory: config.bower.directory,
135 | ignorePath: config.bower.ignorePath
136 | };
137 | return options;
138 | };
139 |
140 | /**
141 | * karma settings
142 | */
143 | config.karma = getKarmaOptions();
144 |
145 | return config;
146 |
147 | ////////////////
148 |
149 | function getKarmaOptions() {
150 | var options = {
151 | files: [].concat(
152 | bowerFiles,
153 | config.specHelpers,
154 | clientApp + '**/*.module.js',
155 | clientApp + '**/*.js',
156 | temp + config.templateCache.file,
157 | config.serverIntegrationSpecs
158 | ),
159 | exclude: [],
160 | coverage: {
161 | dir: report + 'coverage',
162 | reporters: [
163 | // reporters not supporting the `file` property
164 | {type: 'html', subdir: 'report-html'},
165 | {type: 'lcov', subdir: 'report-lcov'},
166 | // reporters supporting the `file` property, use `subdir` to directly
167 | // output them in the `dir` directory.
168 | // omit `file` to output to the console.
169 | // {type: 'cobertura', subdir: '.', file: 'cobertura.txt'},
170 | // {type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt'},
171 | // {type: 'teamcity', subdir: '.', file: 'teamcity.txt'},
172 | //{type: 'text'}, //, subdir: '.', file: 'text.txt'},
173 | {type: 'text-summary'} //, subdir: '.', file: 'text-summary.txt'}
174 | ]
175 | },
176 | preprocessors: {}
177 | };
178 | options.preprocessors[clientApp + '**/!(*.spec)+(.js)'] = ['coverage'];
179 | return options;
180 | }
181 | };
182 |
--------------------------------------------------------------------------------
/gulp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/gulp.png
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | var gulpConfig = require('./gulp.config')();
3 |
4 | config.set({
5 | // base path that will be used to resolve all patterns (eg. files, exclude)
6 | basePath: './',
7 |
8 | // frameworks to use
9 | // some available frameworks: https://npmjs.org/browse/keyword/karma-adapter
10 | frameworks: ['mocha', 'chai', 'sinon', 'chai-sinon'],
11 |
12 | // list of files / patterns to load in the browser
13 | files: gulpConfig.karma.files,
14 |
15 | // list of files to exclude
16 | exclude: gulpConfig.karma.exclude,
17 |
18 | proxies: {
19 | '/': 'http://localhost:8888/'
20 | },
21 |
22 | // preprocess matching files before serving them to the browser
23 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
24 | preprocessors: gulpConfig.karma.preprocessors,
25 |
26 | // test results reporter to use
27 | // possible values: 'dots', 'progress', 'coverage'
28 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
29 | reporters: ['progress', 'coverage'],
30 |
31 | coverageReporter: {
32 | dir: gulpConfig.karma.coverage.dir,
33 | reporters: gulpConfig.karma.coverage.reporters
34 | },
35 |
36 | // web server port
37 | port: 9876,
38 |
39 | // enable / disable colors in the output (reporters and logs)
40 | colors: true,
41 |
42 | // level of logging
43 | // possible values: config.LOG_DISABLE || config.LOG_ERROR ||
44 | // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
45 | logLevel: config.LOG_INFO,
46 |
47 | // enable / disable watching file and executing tests whenever any file changes
48 | autoWatch: true,
49 |
50 | // start these browsers
51 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
52 | // browsers: ['Chrome', 'ChromeCanary', 'FirefoxAurora', 'Safari', 'PhantomJS'],
53 | browsers: ['PhantomJS'],
54 |
55 | // Continuous Integration mode
56 | // if true, Karma captures browsers, runs the tests and exits
57 | singleRun: false
58 | });
59 | };
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Gulp-Patterns",
3 | "version": "0.2.0",
4 | "description": "Gulp Patterns",
5 | "authors": [
6 | "John Papa"
7 | ],
8 | "license": "MIT",
9 | "homepage": "https://github.com/johnpapa/gulp-patterns",
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/johnpapa/gulp-patterns.git"
13 | },
14 | "scripts": {
15 | "init": "npm install",
16 | "install": "bower install && tsd install -r -o --save-dev",
17 | "start": "node src/server/app.js",
18 | "test": "gulp test"
19 | },
20 | "dependencies": {
21 | "body-parser": "^1.8.2",
22 | "compression": "^1.1.0",
23 | "cors": "^2.2.0",
24 | "express": "^4.9.3",
25 | "morgan": "^1.1.1",
26 | "serve-favicon": "^2.0.1"
27 | },
28 | "devDependencies": {
29 | "browser-sync": "^2.5.0",
30 | "chai": "^2.2.0",
31 | "chai-as-promised": "^4.3.0",
32 | "chalk": "^1.0.0",
33 | "dateformat": "^1.0.8-1.2.3",
34 | "debug": "^2.1.3",
35 | "del": "^1.1.1",
36 | "glob": "^5.0.3",
37 | "gulp": "^3.8.11",
38 | "gulp-angular-templatecache": "^1.6.0",
39 | "gulp-autoprefixer": "^2.1.0",
40 | "gulp-bump": "^0.3.0",
41 | "gulp-bytediff": "^0.2.1",
42 | "gulp-concat": "^2.5.2",
43 | "gulp-csso": "^1.0.0",
44 | "gulp-filter": "^2.0.2",
45 | "gulp-header": "^1.2.2",
46 | "gulp-if": "^1.2.5",
47 | "gulp-imagemin": "^2.2.1",
48 | "gulp-inject": "^1.2.0",
49 | "gulp-jscs": "^2.0.0",
50 | "gulp-jshint": "^1.7.1",
51 | "gulp-less": "^3.0.2",
52 | "gulp-load-plugins": "^0.9.0",
53 | "gulp-minify-html": "^1.0.1",
54 | "gulp-ng-annotate": "^0.5.2",
55 | "gulp-nodemon": "^2.0.2",
56 | "gulp-order": "^1.1.1",
57 | "gulp-plumber": "^1.0.0",
58 | "gulp-print": "^1.1.0",
59 | "gulp-rev": "^3.0.1",
60 | "gulp-rev-replace": "^0.4.0",
61 | "gulp-sourcemaps": "^1.5.1",
62 | "gulp-task-listing": "^1.0.0",
63 | "gulp-uglify": "^1.0.1",
64 | "gulp-useref": "^1.0.2",
65 | "gulp-util": "^3.0.4",
66 | "jshint-stylish": "^1.0.1",
67 | "karma": "^0.12.32",
68 | "karma-chai": "^0.1.0",
69 | "karma-chai-sinon": "^0.1.3",
70 | "karma-chrome-launcher": "^0.1.4",
71 | "karma-coverage": "^0.2.4",
72 | "karma-firefox-launcher": "^0.1.4",
73 | "karma-growl-reporter": "^0.1.1",
74 | "karma-mocha": "^0.1.4",
75 | "karma-phantomjs-launcher": "^0.1.4",
76 | "karma-safari-launcher": "^0.1.1",
77 | "karma-sinon": "^1.0.3",
78 | "lodash": "^3.6.0",
79 | "method-override": "^2.3.2",
80 | "minimist": "^1.1.1",
81 | "mocha": "^2.2.1",
82 | "node-notifier": "^4.1.2",
83 | "phantomjs": "^1.9.16",
84 | "plato": "^1.4.0",
85 | "q": "^1.2.0",
86 | "sinon": "^1.14.1",
87 | "sinon-chai": "^2.7.0",
88 | "wiredep": "^2.2.2",
89 | "yargs": "^3.6.0"
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/client/app/app.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | 'use strict';
4 |
5 | angular.module('app', [
6 | /* Shared modules */
7 | 'app.core',
8 | 'app.widgets',
9 |
10 | /* Feature areas */
11 | 'app.customers',
12 | 'app.dashboard',
13 | 'app.layout'
14 | ]);
15 |
16 | })();
17 |
--------------------------------------------------------------------------------
/src/client/app/blocks/diagnostics/diagnostics.decorator.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | var diagnostics = {
5 | enable: true // default
6 | };
7 |
8 | angular
9 | .module('blocks.diagnostics')
10 | .constant('diagnostics', diagnostics)
11 | .config(bindingDecorator);
12 |
13 | /**
14 | * Add binding diaganostics to the console
15 | * @param {Object} $provide
16 | */
17 | /* @ngInject */
18 | bindingDecorator.$inject = ['$provide'];
19 |
20 | function bindingDecorator($provide) {
21 | $provide.decorator('$interpolate', extendInterpolater);
22 | }
23 |
24 | /* @ngInject */
25 | extendInterpolater.$inject = ['$delegate', '$log', 'diagnostics'];
26 |
27 | function extendInterpolater($delegate, $log, diagnostics) {
28 | if (diagnostics.enable) {
29 | angular.extend(interpolatorWrapper, $delegate);
30 | return interpolatorWrapper;
31 | }
32 | return $delegate;
33 |
34 | ////////////////
35 |
36 | function interpolatorWrapper() {
37 | /* jshint validthis:true */
38 | var bindingFunction = $delegate.apply(this, arguments);
39 | var bindingExpression = arguments[0];
40 | if (angular.isFunction(bindingFunction) && bindingExpression) {
41 | return bindingWrapper(bindingFunction, bindingExpression.trim());
42 | }
43 | return bindingFunction;
44 |
45 | function bindingWrapper(bindingFunction, bindingExpression) {
46 | return bindingInspector;
47 |
48 | function bindingInspector() {
49 | var result = bindingFunction.apply(this, arguments);
50 | var trimmedResult = result.trim();
51 | var log = trimmedResult ? $log.info : $log.warn;
52 | var msg = 'Binding: ' +
53 | bindingExpression + ' = ' + trimmedResult;
54 | log.call($log, msg);
55 | return result;
56 | }
57 | }
58 | }
59 |
60 | }
61 | })();
62 |
--------------------------------------------------------------------------------
/src/client/app/blocks/diagnostics/diagnostics.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('blocks.diagnostics', []);
5 | })();
6 |
--------------------------------------------------------------------------------
/src/client/app/blocks/exception/exception-handler.provider.js:
--------------------------------------------------------------------------------
1 | // Include in index.html so that app level exceptions are handled.
2 | // Exclude from testRunner.html which should run exactly what it wants to run
3 | (function() {
4 | 'use strict';
5 |
6 | angular
7 | .module('blocks.exception')
8 | .provider('exceptionHandler', exceptionHandlerProvider)
9 | .config(config);
10 |
11 | /**
12 | * Must configure the exception handling
13 | */
14 | function exceptionHandlerProvider() {
15 | /* jshint validthis:true */
16 | this.config = {
17 | appErrorPrefix: undefined
18 | };
19 |
20 | this.configure = function (appErrorPrefix) {
21 | this.config.appErrorPrefix = appErrorPrefix;
22 | };
23 |
24 | this.$get = function() {
25 | return {config: this.config};
26 | };
27 | }
28 |
29 | /**
30 | * Configure by setting an optional string value for appErrorPrefix.
31 | * Accessible via config.appErrorPrefix (via config value).
32 | * @param {Object} $provide
33 | */
34 | /* @ngInject */
35 | function config($provide) {
36 | $provide.decorator('$exceptionHandler', extendExceptionHandler);
37 | }
38 |
39 | /**
40 | * Extend the $exceptionHandler service to also display a toast.
41 | * @param {Object} $delegate
42 | * @param {Object} exceptionHandler
43 | * @param {Object} logger
44 | * @return {Function} the decorated $exceptionHandler service
45 | */
46 | function extendExceptionHandler($delegate, exceptionHandler, logger) {
47 | return function(exception, cause) {
48 | var appErrorPrefix = exceptionHandler.config.appErrorPrefix || '';
49 | var errorData = {exception: exception, cause: cause};
50 | exception.message = appErrorPrefix + exception.message;
51 | $delegate(exception, cause);
52 | /**
53 | * Could add the error to a service's collection,
54 | * add errors to $rootScope, log errors to remote web server,
55 | * or log locally. Or throw hard. It is entirely up to you.
56 | * throw exception;
57 | *
58 | * @example
59 | * throw { message: 'error message we added' };
60 | */
61 | logger.error(exception.message, errorData);
62 | };
63 | }
64 | })();
65 |
--------------------------------------------------------------------------------
/src/client/app/blocks/exception/exception-handler.provider.spec.js:
--------------------------------------------------------------------------------
1 | /* jshint -W117, -W030 */
2 | describe('blocks.exception', function() {
3 | var exceptionHandlerProvider;
4 | var mocks = {
5 | errorMessage: 'fake error',
6 | prefix: '[TEST]: '
7 | };
8 |
9 | beforeEach(function() {
10 | bard.appModule('blocks.exception', function(_exceptionHandlerProvider_) {
11 | exceptionHandlerProvider = _exceptionHandlerProvider_;
12 | });
13 | bard.inject(this, '$rootScope');
14 | });
15 |
16 | bard.verifyNoOutstandingHttpRequests();
17 |
18 | describe('$exceptionHandler', function() {
19 | it('should have a dummy test', inject(function() {
20 | expect(true).to.equal(true);
21 | }));
22 |
23 | it('should be defined', inject(function($exceptionHandler) {
24 | expect($exceptionHandler).to.be.defined;
25 | }));
26 |
27 | it('should have configuration', inject(function($exceptionHandler) {
28 | expect($exceptionHandler.config).to.be.defined;
29 | }));
30 |
31 | describe('with appErrorPrefix', function() {
32 | beforeEach(function() {
33 | exceptionHandlerProvider.configure(mocks.prefix);
34 | });
35 |
36 | it('should have exceptionHandlerProvider defined', inject(function() {
37 | expect(exceptionHandlerProvider).to.be.defined;
38 | }));
39 |
40 | it('should have appErrorPrefix defined', inject(function() {
41 | expect(exceptionHandlerProvider.$get().config.appErrorPrefix).to.be.defined;
42 | }));
43 |
44 | it('should have appErrorPrefix set properly', inject(function() {
45 | expect(exceptionHandlerProvider.$get().config.appErrorPrefix)
46 | .to.equal(mocks.prefix);
47 | }));
48 |
49 | it('should throw an error when forced', inject(function() {
50 | expect(functionThatWillThrow).to.throw();
51 | }));
52 |
53 | it('manual error is handled by decorator', function() {
54 | var exception;
55 | exceptionHandlerProvider.configure(mocks.prefix);
56 | try {
57 | $rootScope.$apply(functionThatWillThrow);
58 | }
59 | catch (ex) {
60 | exception = ex;
61 | expect(ex.message).to.equal(mocks.prefix + mocks.errorMessage);
62 | }
63 | });
64 | });
65 | });
66 |
67 | function functionThatWillThrow() {
68 | throw new Error(mocks.errorMessage);
69 | }
70 | });
71 |
--------------------------------------------------------------------------------
/src/client/app/blocks/exception/exception.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('blocks.exception')
6 | .factory('exception', exception);
7 |
8 | /* @ngInject */
9 | function exception($q, logger) {
10 | var service = {
11 | catcher: catcher
12 | };
13 | return service;
14 |
15 | function catcher(message) {
16 | return function(e) {
17 | var thrownDescription;
18 | var newMessage;
19 | if (e.data && e.data.description) {
20 | thrownDescription = '\n' + e.data.description;
21 | newMessage = message + thrownDescription;
22 | }
23 | e.data.description = newMessage;
24 | logger.error(newMessage);
25 | return $q.reject(e);
26 | };
27 | }
28 | }
29 | })();
30 |
--------------------------------------------------------------------------------
/src/client/app/blocks/exception/exception.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('blocks.exception', ['blocks.logger']);
5 | })();
6 |
--------------------------------------------------------------------------------
/src/client/app/blocks/logger/logger.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('blocks.logger')
6 | .factory('logger', logger);
7 |
8 | logger.$inject = ['$log', 'toastr'];
9 |
10 | function logger($log, toastr) {
11 | var service = {
12 | showToasts: true,
13 |
14 | error : error,
15 | info : info,
16 | success : success,
17 | warning : warning,
18 |
19 | // straight to console; bypass toastr
20 | log : $log.log
21 | };
22 |
23 | return service;
24 | /////////////////////
25 |
26 | function error(message, data, title) {
27 | toastr.error(message, title);
28 | $log.error('Error: ' + message, data);
29 | }
30 |
31 | function info(message, data, title) {
32 | toastr.info(message, title);
33 | $log.info('Info: ' + message, data);
34 | }
35 |
36 | function success(message, data, title) {
37 | toastr.success(message, title);
38 | $log.info('Success: ' + message, data);
39 | }
40 |
41 | function warning(message, data, title) {
42 | toastr.warning(message, title);
43 | $log.warn('Warning: ' + message, data);
44 | }
45 | }
46 | }());
47 |
--------------------------------------------------------------------------------
/src/client/app/blocks/logger/logger.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('blocks.logger', []);
5 | })();
6 |
--------------------------------------------------------------------------------
/src/client/app/blocks/router/router-helper.provider.js:
--------------------------------------------------------------------------------
1 | /* Help configure the state-base ui.router */
2 | (function() {
3 | 'use strict';
4 |
5 | angular
6 | .module('blocks.router')
7 | .provider('routerHelper', routerHelperProvider);
8 |
9 | routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider'];
10 | /* @ngInject */
11 | function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) {
12 | /* jshint validthis:true */
13 | var config = {
14 | docTitle: undefined,
15 | resolveAlways: {}
16 | };
17 |
18 | $locationProvider.html5Mode(true);
19 |
20 | this.configure = function(cfg) {
21 | angular.extend(config, cfg);
22 | };
23 |
24 | this.$get = RouterHelper;
25 | RouterHelper.$inject = ['$location', '$rootScope', '$state', 'logger'];
26 | /* @ngInject */
27 | function RouterHelper($location, $rootScope, $state, logger) {
28 | var handlingStateChangeError = false;
29 | var hasOtherwise = false;
30 | var stateCounts = {
31 | errors: 0,
32 | changes: 0
33 | };
34 |
35 | var service = {
36 | configureStates: configureStates,
37 | getStates: getStates,
38 | stateCounts: stateCounts
39 | };
40 |
41 | init();
42 |
43 | return service;
44 |
45 | ///////////////
46 |
47 | function configureStates(states, otherwisePath) {
48 | states.forEach(function(state) {
49 | state.config.resolve =
50 | angular.extend(state.config.resolve || {}, config.resolveAlways);
51 | $stateProvider.state(state.state, state.config);
52 | });
53 | if (otherwisePath && !hasOtherwise) {
54 | hasOtherwise = true;
55 | $urlRouterProvider.otherwise(otherwisePath);
56 | }
57 | }
58 |
59 | function handleRoutingErrors() {
60 | // Route cancellation:
61 | // On routing error, go to the dashboard.
62 | // Provide an exit clause if it tries to do it twice.
63 | $rootScope.$on('$stateChangeError',
64 | function(event, toState, toParams, fromState, fromParams, error) {
65 | if (handlingStateChangeError) {
66 | return;
67 | }
68 | stateCounts.errors++;
69 | handlingStateChangeError = true;
70 | var destination = (toState &&
71 | (toState.title || toState.name || toState.loadedTemplateUrl)) ||
72 | 'unknown target';
73 | var msg = 'Error routing to ' + destination + '. ' +
74 | (error.data || '') + '.
' + (error.statusText || '') +
75 | ': ' + (error.status || '');
76 | logger.warning(msg, [toState]);
77 | $location.path('/');
78 | }
79 | );
80 | }
81 |
82 | function init() {
83 | handleRoutingErrors();
84 | updateDocTitle();
85 | }
86 |
87 | function getStates() { return $state.get(); }
88 |
89 | function updateDocTitle() {
90 | $rootScope.$on('$stateChangeSuccess',
91 | function(event, toState, toParams, fromState, fromParams) {
92 | stateCounts.changes++;
93 | handlingStateChangeError = false;
94 | var title = config.docTitle + ' ' + (toState.title || '');
95 | $rootScope.title = title; // data bind to