├── .bowerrc
├── .editorconfig
├── .gitignore
├── .npmrc
├── README.md
├── bower.json
├── gulpfile.js
├── package.json
├── src
├── app
│ ├── commons
│ │ ├── cacheManagement
│ │ │ ├── module.js
│ │ │ ├── package.js
│ │ │ └── service.js
│ │ ├── components
│ │ │ ├── directives
│ │ │ │ ├── navbar.js
│ │ │ │ ├── pane.js
│ │ │ │ └── tabs.js
│ │ │ ├── module.js
│ │ │ ├── package.js
│ │ │ └── templates
│ │ │ │ ├── navbar.html
│ │ │ │ ├── pane.html
│ │ │ │ └── tabs.html
│ │ ├── persistence
│ │ │ ├── module.js
│ │ │ ├── package.js
│ │ │ ├── run.js
│ │ │ ├── service.js
│ │ │ └── values.js
│ │ └── shorthash
│ │ │ ├── module.js
│ │ │ ├── package.js
│ │ │ └── service.js
│ ├── github
│ │ ├── controllers
│ │ │ ├── repository.js
│ │ │ └── user.js
│ │ ├── module.js
│ │ ├── package.js
│ │ ├── resource.js
│ │ ├── routes.js
│ │ ├── services
│ │ │ ├── data.js
│ │ │ ├── repository
│ │ │ │ ├── contributors.js
│ │ │ │ └── info.js
│ │ │ └── user
│ │ │ │ ├── gists.js
│ │ │ │ ├── info.js
│ │ │ │ └── repositories.js
│ │ ├── styles
│ │ │ ├── _avatar.scss
│ │ │ ├── _contributor.scss
│ │ │ ├── _main.scss
│ │ │ ├── _repo.scss
│ │ │ ├── _techs.scss
│ │ │ └── _user.scss
│ │ └── templates
│ │ │ ├── repo-contributors.html
│ │ │ ├── repo-info.html
│ │ │ ├── repo.html
│ │ │ ├── user-gists.html
│ │ │ ├── user-info.html
│ │ │ ├── user-repos.html
│ │ │ └── user.html
│ └── main
│ │ ├── controllers
│ │ ├── about.js
│ │ └── search.js
│ │ ├── module.js
│ │ ├── package.js
│ │ ├── routes.js
│ │ ├── services
│ │ ├── navbar.js
│ │ └── pluralize.js
│ │ └── templates
│ │ ├── about.html
│ │ └── search.html
├── img
│ ├── loading.gif
│ └── user.png
├── index.html
├── ng.app.js
├── require.config.js
└── scss
│ ├── _CommonFunctions.scss
│ ├── _TopScreen.scss
│ └── app.scss
└── tools
├── config.js
├── gulp
├── helpers
│ ├── $.js
│ ├── loadTasks.js
│ └── sharedStreams.js
├── index.js
└── tasks
│ ├── bower.js
│ ├── build.js
│ ├── bump.js
│ ├── clean.js
│ ├── copy.js
│ ├── default.js
│ ├── help.js
│ ├── html2js.js
│ ├── init.js
│ ├── jshint.js
│ ├── lintspaces.js
│ ├── publish.js
│ ├── require.js
│ ├── shell.js
│ ├── styles.js
│ ├── validate.js
│ ├── watch.js
│ └── webserver.js
├── lib
├── localip.js
├── oscheck.js
├── requirejs
│ ├── builder.js
│ ├── index.js
│ └── js-ast-js
│ │ ├── gulp-rewrite-require-config.js
│ │ └── rewrite-require-config.js
└── testModuleThenExecute.js
└── scripts
├── localip.js
├── setup.js
└── testos.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": ".local/bower/vendor"
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | charset = utf-8
7 | end_of_line = lf
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [{**.js,**.html,**.css,**.less,**.json,**.coffee}]
12 | indent_style = space
13 | indent_size = 2
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | node_modules
15 | npm-debug.log
16 |
17 | .local
18 | .temp
19 | cache
20 | build
21 | dist
22 |
23 | #-----------
24 | # Windows
25 |
26 | **/.db
27 |
28 | #-----------
29 | # Mac OS X
30 |
31 | **/.DS_Store
32 |
33 | # Thumbnails
34 | **/._*
35 |
36 | # Files that might appear on external disk
37 | **/.Spotlight-V100
38 | **/.Trashes
39 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | loglevel = "error"
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AngularJS GitHub Info
2 |
3 | [](https://david-dm.org/erkobridee/angularjs-github-info) [](https://david-dm.org/erkobridee/angularjs-github-info#info=devDependencies)
4 |
5 | This application is based on: AngularJS GitHub Contributors [App](http://daha.github.com/angularJS-github-contributors/) | [GitHub](https://github.com/daha/angularJS-github-contributors/)
6 |
7 | *By [@ErkoBridee](https://twitter.com/erkobridee)*
8 |
9 |
10 | ## Demo
11 |
12 | View the app [AngularJS GitHub Info](http://erkobridee.github.io/angularjs-github-info/).
13 |
14 |
15 | ## Application
16 |
17 | * **Interface:** [Twitter Bootstrap](http://twitter.github.com/bootstrap/) v3.3.7
18 |
19 | * **Engine:** [AngularJS](http://angularjs.org/) v1.6.1 ( [Guide](http://docs.angularjs.org/guide/) )
20 |
21 | * **Features:** List all public repositories, public gists and contributors repository from some GitHub user
22 |
23 | * **Data Access:** [GitHub API](http://developer.github.com/)
24 |
25 |
26 | ## Install AngularJS GitHub Info
27 |
28 | Enter the following commands in the terminal.
29 |
30 | ```bash
31 | $ git clone https://github.com/erkobridee/angularjs-github-info.git
32 | $ cd angularjs-github-info/
33 | $ npm install
34 | ```
35 | > pre install will execute `tools/scripts/setup.js`, that will check and install node global packages [`gulp`, `bower`]
36 | > if you are running on unix/mac machine, please run `sudo npm install`
37 |
38 | ### Prerequisites
39 |
40 | * Must have [Git](http://git-scm.com/) installed
41 |
42 | * Must have [node.js (at least v0.12)](http://nodejs.org/) installed with npm (Node Package Manager)
43 |
44 | * Must have [gulp](https://github.com/gulpjs/gulp) node package installed globally. `[sudo] npm install -g gulp`
45 |
46 | * Must have [Bower](https://github.com/bower/bower) node package installed globally. `[sudo] npm install -g bower`
47 |
48 |
49 | ### Gulp commands
50 |
51 | > If you want to know more about Gulp usage in this project, check [[GitHub] soudev / gulp-steps](https://github.com/soudev/gulp-steps). This project is based on step [04](https://github.com/soudev/gulp-steps/tree/master/04).
52 |
53 | * `gulp` - development mode, prepare files, watch changes and start server on port 1337
54 |
55 | * `gulp --preview` - generate deploy version (`gulp --release`) on `dist` directory and start server on port 1337 looking to this directory
56 |
57 | * `gulp --publish` - publish deploy version files on `gh-pages` branch
58 |
59 | * `gulp --init` - create local directory with github repository on gh-pages branch
60 |
61 |
62 | ## Licenses
63 |
64 | * All my code is licensed under the [MIT License].
65 |
66 |
67 | [AngularJS GitHub Info]: http://erkobridee.github.com/angularjs-github-info
68 | [MIT License]: http://erkobridee.mit-license.org/
69 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angularjs-github-info",
3 | "version": "2.3.3",
4 | "ignore": [
5 | "**/.*",
6 | ".local",
7 | "helpers",
8 | "node_modules",
9 | "test",
10 | "tests"
11 | ],
12 | "dependencies": {
13 | "jquery": "3.1.1",
14 | "requirejs": "2.3.2",
15 | "bootstrap": "3.3.7",
16 | "angular": "~1.6.1",
17 | "angular-resource": "~1.6.1",
18 | "angular-route": "~1.6.1",
19 | "hashids": "~1.1.1",
20 | "moment": "~2.17.1"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | // agi - angular github info
2 | process.title = 'agi-dev-tools';
3 |
4 | require('./tools/gulp')
5 | .loadTasks('tools/gulp/tasks'); // load tasks config per file
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "angularjs-github-info",
4 | "version": "2.3.3",
5 | "description": "prove of concept using angularjs accessing github api",
6 | "author": "Erko Bridee",
7 | "license": "MIT",
8 | "readmeFilename": "README.md",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/erkobridee/angularjs-github-info.git"
12 | },
13 | "scripts": {
14 | "outdated": "npm outdated --depth=0",
15 | "localip": "node tools/scripts/localip",
16 | "testos": "node tools/scripts/testos",
17 | "setup": "node tools/scripts/setup",
18 | "preinstall": "npm run setup",
19 | "postinstall": "gulp --init && bower install",
20 | "test": "echo \"Error: no test specified\" && exit 1",
21 | "start": "gulp",
22 | "preview": "gulp --preview",
23 | "publish": "gulp --publish"
24 | },
25 | "keywords": [
26 | "angularjs",
27 | "prove",
28 | "concept",
29 | "github",
30 | "api"
31 | ],
32 | "engines": {
33 | "node": ">=0.12.0"
34 | },
35 | "devDependencies": {
36 | "browser-sync": "^2.17.5",
37 | "del": "^2.2.2",
38 | "escodegen": "^1.8.1",
39 | "esprima": "^3.1.1",
40 | "gulp": "^3.9.1",
41 | "gulp-angular-templatecache": "^1.7.0",
42 | "gulp-autoprefixer": "^3.0.1",
43 | "gulp-bump": "^2.5.0",
44 | "gulp-cached": "^1.1.0",
45 | "gulp-concat": "^2.6.0",
46 | "gulp-connect": "^5.0.0",
47 | "gulp-debug": "^2.1.0",
48 | "gulp-filter": "^4.0.0",
49 | "gulp-htmlmin": "^3.0.0",
50 | "gulp-if": "^2.0.2",
51 | "gulp-imagemin": "^2.3.0",
52 | "gulp-inject-string": "^1.1.0",
53 | "gulp-jshint": "^2.0.2",
54 | "gulp-less": "^3.2.0",
55 | "gulp-lintspaces": "^0.5.0",
56 | "gulp-load-plugins": "^1.4.0",
57 | "gulp-minify-css": "^1.2.4",
58 | "gulp-print": "^2.0.1",
59 | "gulp-rename": "^1.2.2",
60 | "gulp-sass": "^2.3.2",
61 | "gulp-shell": "^0.5.2",
62 | "gulp-task-listing": "^1.0.1",
63 | "gulp-uglify": "^2.0.0",
64 | "gulp-util": "^3.0.7",
65 | "http-proxy-middleware": "^0.17.2",
66 | "jshint": "^2.9.4",
67 | "jshint-stylish": "^2.2.1",
68 | "lazypipe": "^1.0.1",
69 | "open": "0.0.5",
70 | "requirejs": "^2.3.2",
71 | "run-sequence": "^1.2.2",
72 | "through2": "^2.0.1",
73 | "yargs": "^6.3.0"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/commons/cacheManagement/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 |
6 | // angular module definition
7 | return angular.module(
8 | // module name
9 | 'cache.management',
10 |
11 | // module dependencies
12 | [
13 | require('app/commons/persistence/package').name,
14 | require('app/commons/shorthash/package').name
15 | ]
16 | );
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/src/app/commons/cacheManagement/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./service');
6 |
7 | return module;
8 |
9 | });
10 |
--------------------------------------------------------------------------------
/src/app/commons/cacheManagement/service.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | /*
5 | http://momentjs.com/docs/#/parsing/unix-timestamp/
6 |
7 | https://developer.github.com/v3/#rate-limiting
8 |
9 | https://developer.github.com/v3/#json-p-callbacks
10 | */
11 |
12 | var moment = require('moment');
13 |
14 | //---
15 |
16 | var module = require('./module');
17 |
18 | module.factory('CacheService', CacheService);
19 |
20 | //---
21 |
22 | CacheService.$inject = [
23 | '$q', 'PersistenceService', 'ShortHashService'
24 | ];
25 |
26 | function CacheService($q, persistence, shorthash) {
27 |
28 | return function(persistenceKey, loadRemoteData) {
29 | if(!loadRemoteData) {
30 | loadRemoteData = function(options) {
31 | return $q.when({
32 | data: {},
33 | meta: {
34 | 'X-RateLimit-Reset':0
35 | }
36 | });
37 | };
38 | }
39 |
40 | var CacheManager = (function() {
41 |
42 | function getCacheKey(value) {
43 | return shorthash.make(value);
44 | }
45 |
46 | function checkCache(cache, cacheKey) {
47 | var cacheObj = cache[cacheKey];
48 |
49 | if(angular.isObject(cacheObj)) {
50 | if(
51 | moment()
52 | .isAfter(
53 | moment.unix( cacheObj.ttl )
54 | )
55 | ) {
56 | removeCacheObject(cache, cacheKey);
57 | cacheObj = null;
58 | }
59 | } else {
60 | cacheObj = null;
61 | }
62 |
63 | return cacheObj;
64 | }
65 |
66 | function removeCacheObject(cache, cacheKey) {
67 | delete( cache[cacheKey] );
68 | }
69 |
70 | function makeCacheObject(value, ttl) {
71 | return {
72 | data: angular.copy( value ),
73 | ttl: ttl
74 | };
75 | }
76 |
77 | function addCacheObject(cache, cacheKey, cacheObject) {
78 | cache[cacheKey] = cacheObject;
79 | }
80 |
81 | //--- public
82 |
83 | function CacheManager(persistenceKey, loadRemoteData, cache) {
84 | var self = this;
85 | self.persistenceKey = persistenceKey;
86 | self.loadRemoteData = loadRemoteData;
87 | self.cache = cache;
88 |
89 | persistence.onBeforePersist(function() {
90 | persistence.setItem( self.persistenceKey, self.cache );
91 | });
92 |
93 | self.get = function(options) {
94 | var cacheKey = getCacheKey(options),
95 | cacheObj = checkCache(self.cache, cacheKey);
96 |
97 | if(cacheObj) {
98 | return $q.when( angular.copy( cacheObj.data ) );
99 | } else {
100 | return self.loadRemoteData(options)
101 | .then(function(result) {
102 | addCacheObject(self.cache, cacheKey, makeCacheObject(
103 | result.data,
104 | result.meta['X-RateLimit-Reset']
105 | ));
106 | return result.data;
107 | });
108 | }
109 | };
110 | }
111 |
112 | return CacheManager;
113 | })();
114 |
115 | return new CacheManager(
116 | persistenceKey,
117 | loadRemoteData,
118 | ( persistence.extractItem( persistenceKey ) || {} )
119 | );
120 |
121 | };
122 | }
123 |
124 | });
125 |
--------------------------------------------------------------------------------
/src/app/commons/components/directives/navbar.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.directive('navbar', navbar);
7 |
8 | //---
9 |
10 | // https://docs.angularjs.org/guide/directive
11 | // https://docs.angularjs.org/api/ng/service/$compile
12 |
13 | function navbar() {
14 |
15 | var scope = {
16 | title: '@'
17 | };
18 |
19 | var directive = {
20 | restrict: 'E',
21 | scope: scope,
22 |
23 | controller: ControllerFn,
24 | controllerAs: 'vm',
25 | // So our isolated scope will be stored
26 | // on the `this` context of our controller
27 | // instead of
28 | bindToController: true,
29 |
30 | templateUrl: templateUrlFn
31 | };
32 |
33 | //---
34 |
35 | ControllerFn.$inject = ['NavBarService'];
36 |
37 | function ControllerFn(NavBarService) {
38 | var vm = this;
39 |
40 | vm.nav = NavBarService.getNav();
41 | }
42 |
43 | //---
44 |
45 | function templateUrlFn(tElement, tAttrs) {
46 | return 'app/commons/components/templates/navbar.html';
47 | }
48 |
49 | //---
50 |
51 | return directive;
52 |
53 | }
54 |
55 | });
56 |
--------------------------------------------------------------------------------
/src/app/commons/components/directives/pane.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.directive('pane', pane);
7 |
8 | //---
9 |
10 | // https://docs.angularjs.org/guide/directive
11 |
12 | function pane() {
13 |
14 | var scope = {
15 | title: '@'
16 | };
17 |
18 | var directive = {
19 | require: '^tabs',
20 | restrict: 'E',
21 | scope: scope,
22 |
23 | link: linkingFn,
24 |
25 | transclude: true,
26 | templateUrl: templateUrlFn
27 | };
28 |
29 | //---
30 |
31 | function linkingFn(scope, element, attrs, controller) {
32 |
33 | controller.addPane(scope);
34 |
35 | }
36 |
37 | //---
38 |
39 | function templateUrlFn(tElement, tAttrs) {
40 | return 'app/commons/components/templates/pane.html';
41 | }
42 |
43 | //---
44 |
45 | return directive;
46 |
47 | }
48 |
49 | });
50 |
--------------------------------------------------------------------------------
/src/app/commons/components/directives/tabs.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.directive('tabs', tabs);
7 |
8 | //---
9 |
10 | // https://docs.angularjs.org/guide/directive
11 | // https://docs.angularjs.org/api/ng/service/$compile
12 |
13 | function tabs() {
14 |
15 | var scope = {
16 | };
17 |
18 | var directive = {
19 | restrict: 'E',
20 | scope: scope,
21 | transclude: true,
22 |
23 | controller: ControllerFn,
24 | controllerAs: 'tabs',
25 | // So our isolated scope will be stored
26 | // on the `this` context of our controller
27 | // instead of
28 | bindToController: true,
29 |
30 | templateUrl: templateUrlFn
31 | };
32 |
33 | //---
34 |
35 | ControllerFn.$inject = ['NavBarService'];
36 |
37 | function ControllerFn(NavBarService) {
38 | var vm = this;
39 |
40 | vm.panes = [];
41 |
42 | vm.select = select;
43 | vm.addPane = addPane;
44 |
45 | //---
46 |
47 | function select(pane) {
48 | angular.forEach(vm.panes, function(pane) {
49 | pane.selected = false;
50 | });
51 | pane.selected = true;
52 | }
53 |
54 | function addPane(pane) {
55 | if (vm.panes.length === 0) vm.select(pane);
56 | vm.panes.push(pane);
57 | }
58 |
59 | }
60 |
61 | //---
62 |
63 | function templateUrlFn(tElement, tAttrs) {
64 | return 'app/commons/components/templates/tabs.html';
65 | }
66 |
67 | //---
68 |
69 | return directive;
70 |
71 | }
72 |
73 | });
74 |
--------------------------------------------------------------------------------
/src/app/commons/components/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 |
6 | // angular module definition
7 | return angular.module(
8 | // module name
9 | 'components',
10 |
11 | // module dependencies
12 | [
13 | // TODO: review
14 | ]
15 | );
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/src/app/commons/components/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./directives/navbar');
6 | require('./directives/pane');
7 | require('./directives/tabs');
8 |
9 | return module;
10 |
11 | });
12 |
--------------------------------------------------------------------------------
/src/app/commons/components/templates/navbar.html:
--------------------------------------------------------------------------------
1 |
42 |
--------------------------------------------------------------------------------
/src/app/commons/components/templates/pane.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/app/commons/components/templates/tabs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/app/commons/persistence/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 |
6 | // angular module definition
7 | return angular.module(
8 | // module name
9 | 'persistence',
10 |
11 | // module dependencies
12 | [
13 | // TODO: review
14 | ]
15 | );
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/src/app/commons/persistence/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./values');
6 | require('./service');
7 | require('./run');
8 |
9 | return module;
10 |
11 | });
12 |
--------------------------------------------------------------------------------
/src/app/commons/persistence/run.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.run(onModuleRun);
7 |
8 | //---
9 |
10 | /*
11 | This is just here to make sure that the storage component is loaded when the
12 | app is bootstrapped. This will cause the localStorage I/O overhead to be front-
13 | loaded in the app rather than caused by a particular user interaction (which
14 | the user is more likely to notice).
15 | */
16 | onModuleRun.$inject = ['PersistenceService'];
17 |
18 | function onModuleRun(persistenceService) {}
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/src/app/commons/persistence/service.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.factory('PersistenceService', PersistenceService);
7 |
8 | //---
9 |
10 | PersistenceService.$inject = ['$exceptionHandler', '$window', 'PERSISTENCE_STORAGE_KEY'];
11 |
12 | /*
13 | Provide a storage API that uses an in-memory data cache that is persisted
14 | to the localStorage at the limits of the application life-cycle.
15 | */
16 | function PersistenceService($exceptionHandler, $window, storageKey) {
17 |
18 | /*
19 | Collection of callbacks that want to hook into the
20 | unload event of the in-memory cache. This will give the calling
21 | context a chance to update their relevant storage items before
22 | the data is persisted to localStorage.
23 | */
24 | var persistHooks = [];
25 |
26 | /*
27 | Determine if the cache should be persisted to localStorage when the
28 | application is unloaded.
29 | */
30 | var persistEnabled = true;
31 |
32 | //---
33 |
34 | /*
35 | Try to load the initial payload from localStorage.
36 |
37 | Attempt to load the cache from the localStorage interface.
38 | Once the data is loaded, it is deleted from localStorage.
39 | */
40 | var items = (function loadData() {
41 | /*
42 | There's a chance that the localStorage isn't available, even in
43 | modern browsers (looking at you, Safari, running in Private mode).
44 | */
45 | try {
46 | if( storageKey in $window.localStorage ) {
47 | var data = $window.localStorage.getItem( storageKey );
48 | $window.localStorage.removeItem( storageKey );
49 | /*
50 | NOTE: Using .extend() here as a safe-guard to ensure that
51 | the value we return is actually a hash, even if the data
52 | is corrupted.
53 | */
54 | return( angular.extend( {}, angular.fromJson( data ) ) );
55 | }
56 | } catch ( localStorageError ) {
57 | $exceptionHandler( localStorageError );
58 | }
59 | // If we made it this far, something went wrong.
60 | return( {} );
61 | })();
62 |
63 | //---
64 | // @begin: internal logic
65 |
66 | /*
67 | Normalize the given cache key so that we never collide with any
68 | native object keys when looking up items.
69 | */
70 | function normalizeKey( key ) {
71 | return( "sk_" + key );
72 | }
73 |
74 | // Attempt to persist the cache to the localStorage.
75 | function persistData() {
76 | /*
77 | Before we persist the data, invoke all of the before-persist hook
78 | operators so that consuming services have one last chance to
79 | synchronize their local data with the storage data.
80 | */
81 | for( var i = 0, length = persistHooks.length ; i < length ; i++ ) {
82 | try {
83 | persistHooks[ i ]();
84 | } catch ( persistHookError ) {
85 | $exceptionHandler( persistHookError );
86 | }
87 | }
88 | // If persistence is disabled, skip the localStorage access.
89 | if( ! persistEnabled ) {
90 | return;
91 | }
92 | /*
93 | There's a chance that localStorage isn't available, even in modern
94 | browsers. And, even if it does exist, we may be attempting to store
95 | more data that we can based on per-domain quotas.
96 | */
97 | try {
98 | $window.localStorage.setItem( storageKey, angular.toJson( items ) );
99 | } catch ( localStorageError ) {
100 | $exceptionHandler( localStorageError );
101 | }
102 | }
103 |
104 | //---
105 |
106 | // Clear the current item cache.
107 | function clear() {
108 | items = {};
109 | }
110 |
111 | // Disable the persisting of the cache to localStorage on unload.
112 | function disablePersist() {
113 | persistEnabled = false;
114 | }
115 |
116 | // Enable the persisting of the cache to localStorage on unload.
117 | function enablePersist() {
118 | persistEnabled = true;
119 | }
120 |
121 | /*
122 | Remove the given key from the cache and return the value that was
123 | cached at that key; returns null if the key didn't exist.
124 | */
125 | function extractItem( key ) {
126 | var value = getItem( key );
127 | removeItem( key );
128 | return ( value );
129 | }
130 |
131 | // Return the item at the given key; returns null if not available.
132 | function getItem( key ) {
133 | key = normalizeKey( key );
134 | /*
135 | NOTE: Using .copy() so that the internal cache can't be
136 | mutated through direct object references.
137 | */
138 | return ( ( key in items ) ? angular.copy( items[ key ] ) : null );
139 | }
140 |
141 | /*
142 | Add the given operator to persist hooks that will be invoked prior
143 | to unload-based persistence.
144 | */
145 | function onBeforePersist( operator ) {
146 | persistHooks.push( operator );
147 | }
148 |
149 | // Remove the given key from the cache.
150 | function removeItem( key ) {
151 | key = normalizeKey( key );
152 | delete( items[ key ] );
153 | }
154 |
155 | // I store the item at the given key.
156 | function setItem( key, value ) {
157 | key = normalizeKey( key );
158 | /*
159 | NOTE: Using .copy() so that the internal cache can't be
160 | mutated through direct object references.
161 | */
162 | items[ key ] = angular.copy( value );
163 | }
164 |
165 | // @end: internal logic
166 | //---
167 |
168 | /*
169 | During the application lifetime, we're going to be using in-memory
170 | data access (since localStorage I/O is relatively expensive and
171 | requires data to be serialized - two things we don't want during the
172 | user to "feel"). However, when the application unloads, we want to try
173 | to persist the in-memory cache to the localStorage.
174 | */
175 | $window.addEventListener( 'beforeunload', persistData );
176 |
177 | //---
178 |
179 | var service = {
180 | clear : clear,
181 | disablePersist : disablePersist,
182 | enablePersist : enablePersist,
183 | extractItem : extractItem,
184 | getItem : getItem,
185 | onBeforePersist : onBeforePersist,
186 | removeItem : removeItem,
187 | setItem : setItem
188 | };
189 |
190 | return service;
191 | }
192 |
193 | });
194 |
--------------------------------------------------------------------------------
/src/app/commons/persistence/values.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.value('PERSISTENCE_STORAGE_KEY', '_pks_'); // persistence keep saved
7 |
8 | });
9 |
--------------------------------------------------------------------------------
/src/app/commons/shorthash/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 |
6 | // angular module definition
7 | return angular.module(
8 | // module name
9 | 'shorthash',
10 |
11 | // module dependencies
12 | [
13 | // TODO: review
14 | ]
15 | );
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/src/app/commons/shorthash/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./service');
6 |
7 | return module;
8 |
9 | });
10 |
--------------------------------------------------------------------------------
/src/app/commons/shorthash/service.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var Hashids = require('hashids');
5 | var salt = 'shorthashservice';
6 | var hashids = new Hashids( salt );
7 | //---
8 |
9 | var module = require('./module');
10 |
11 | module.factory('ShortHashService', ShortHashService);
12 |
13 | //---
14 |
15 | ShortHashService.$inject = [];
16 |
17 | function ShortHashService() {
18 | //--- publish
19 |
20 | function hashFn(value) {
21 | if( !angular.isString( value ) ) value = JSON.stringify( value );
22 |
23 | var i,
24 | charArray = [];
25 |
26 | for( i = value.length - 1; i >= 0; i-- ) {
27 | charArray.push( value.charCodeAt(i) );
28 | }
29 |
30 | var hash = hashids.encode( charArray );
31 | charArray = [];
32 |
33 | var hashSum = hash.length;
34 | for( i = hash.length - 1; i >= 0; i-- ) {
35 | hashSum += hash.charCodeAt(i);
36 | }
37 |
38 | // return {
39 | // input: value,
40 | // hashSum: hashSum,
41 | // hash: hashids.encode( hashSum )
42 | // };
43 | return hashids.encode( hashSum );
44 | }
45 |
46 | //--- api
47 | var service = {
48 | make: hashFn
49 | };
50 | return service;
51 | }
52 |
53 | });
54 |
--------------------------------------------------------------------------------
/src/app/github/controllers/repository.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.controller('GitHubRepositoryCtrl', GitHubRepositoryCtrl);
7 |
8 | //---
9 |
10 | GitHubRepositoryCtrl.$inject = [
11 | '$routeParams', 'NavBarService', 'PluralizeService',
12 | 'GithubDataService'
13 | ];
14 |
15 | function GitHubRepositoryCtrl(
16 | $routeParams, NavBarService, PluralizeService,
17 | dataService
18 | ) {
19 |
20 | var userParam = $routeParams.user,
21 | repoParam = $routeParams.repo,
22 | urlPath = ['', 'github', userParam, repoParam, ''].join('/');
23 |
24 | //---
25 |
26 | var vm = this;
27 |
28 | vm.repoInfo = null;
29 | vm.contributors = null;
30 |
31 | vm.watchForms = PluralizeService.watchForms;
32 | vm.forkForms = PluralizeService.forkForms;
33 |
34 | vm.contributionsTitle = contributionsTitle;
35 |
36 | //---
37 |
38 | // update search menu option url
39 | NavBarService.updateSearchUrl(urlPath);
40 |
41 | loadData();
42 |
43 | //---
44 |
45 | function contributionsTitle(contributor) {
46 | var contributionStr = 'Contribution',
47 | titleMsg;
48 |
49 | if(contributor.contributions > 1) {
50 | contributionStr = contributionStr + 's';
51 | }
52 |
53 | titleMsg = contributor.login +
54 | ' has ' +
55 | contributor.contributions +
56 | ' ' +
57 | contributionStr;
58 |
59 | return titleMsg;
60 | }
61 |
62 | function loadData() {
63 | var options = {
64 | user: userParam,
65 | repo: repoParam
66 | };
67 |
68 | // RepositoryInfo
69 | dataService
70 | .repository
71 | .info
72 | .get(options)
73 | .then(function(data) {
74 | vm.repoInfo = data;
75 | });
76 |
77 | // RepositoryContributors
78 | dataService
79 | .repository
80 | .contributors
81 | .get(options)
82 | .then(function(data) {
83 | vm.contributors = data;
84 | });
85 |
86 | }
87 |
88 | }
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/src/app/github/controllers/user.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.controller('GitHubUserCtrl', GitHubUserCtrl);
7 |
8 | //---
9 |
10 | GitHubUserCtrl.$inject = [
11 | '$routeParams', 'NavBarService', 'PluralizeService',
12 | 'GithubDataService'
13 | ];
14 |
15 | function GitHubUserCtrl(
16 | $routeParams, NavBarService, PluralizeService,
17 | dataService
18 | ) {
19 |
20 | var userParam = $routeParams.user,
21 | urlPath = ['', 'github', userParam, ''].join('/');
22 |
23 | //---
24 |
25 | var vm = this;
26 |
27 | vm.user = null;
28 | vm.repos = null;
29 | vm.gists = null;
30 |
31 | vm.publicRepoForms = PluralizeService.publicRepoForms;
32 | vm.followerForms = PluralizeService.followerForms;
33 |
34 | vm.watchForms = PluralizeService.watchForms;
35 | vm.forkForms = PluralizeService.forkForms;
36 |
37 | vm.getFile = getFile;
38 | vm.checkLength = checkLength;
39 |
40 | //---
41 |
42 | // update search menu option url
43 | NavBarService.updateSearchUrl(urlPath);
44 |
45 | loadData();
46 |
47 | //---
48 |
49 | function getFile(files) {
50 | for(var key in files) {
51 | return files[key];
52 | }
53 | }
54 |
55 | function checkLength(value) {
56 | if(
57 | value &&
58 | typeof value !== 'undefined' &&
59 | value.hasOwnProperty('length')
60 | ) {
61 | return '(' + value.length + ')';
62 | } else {
63 | return '(0)';
64 | }
65 | }
66 |
67 | function loadData() {
68 | var options = {
69 | user: userParam
70 | };
71 |
72 | // UserInfo
73 | dataService
74 | .user
75 | .info
76 | .get(options)
77 | .then(function(data) {
78 | vm.user = data;
79 | });
80 |
81 | // UserRepositories
82 | dataService
83 | .user
84 | .repositories
85 | .get(options)
86 | .then(function(data) {
87 | vm.repos = data;
88 | });
89 |
90 | // UserGists
91 | dataService
92 | .user
93 | .gists
94 | .get(options)
95 | .then(function(data) {
96 | vm.gists = data;
97 | });
98 |
99 | }
100 |
101 | }
102 |
103 | });
104 |
--------------------------------------------------------------------------------
/src/app/github/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 | require('angularResource');
6 | require('angularRoute');
7 |
8 | // angular module definition
9 | return angular.module(
10 | // module name
11 | 'github',
12 |
13 | // module dependencies
14 | [
15 | 'ngResource',
16 | 'ngRoute',
17 |
18 | require('app/commons/cacheManagement/package').name
19 | ]
20 | );
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/src/app/github/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./resource');
6 | require('./services/user/info');
7 | require('./services/user/gists');
8 | require('./services/user/repositories');
9 | require('./services/repository/info');
10 | require('./services/repository/contributors');
11 | require('./services/data');
12 | require('./controllers/repository');
13 | require('./controllers/user');
14 | require('./routes');
15 |
16 | return module;
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/src/app/github/resource.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.factory('GithubResource', GithubResource);
7 |
8 | //--- https://docs.angularjs.org/api/ngResource/service/
9 |
10 | GithubResource.$inject = ['$resource'];
11 |
12 | function GithubResource($resource) {
13 |
14 | return $resource(
15 | 'https://api.github.com/:query/:user/:repo/:spec',
16 | {
17 | 'query': 'users',
18 | 'user': 'erkobridee',
19 | 'repo': 'repos',
20 | 'spec': '',
21 | // this works until angular.js v1.5.x
22 | // 'callback': 'JSON_CALLBACK',
23 | 'per_page': 100
24 | }, {
25 | 'get': {
26 | 'method': 'JSONP',
27 | 'params': {
28 | // needed since angular.js v1.6.x
29 | 'jsonpCallbackParam': 'cb'
30 | }
31 | }
32 | }
33 | );
34 |
35 | }
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/src/app/github/routes.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.config(configureRoutes);
7 |
8 | //--- https://docs.angularjs.org/api/ngRoute
9 |
10 | configureRoutes.$inject = ['$routeProvider'];
11 |
12 | function configureRoutes($routeProvider) {
13 |
14 | $routeProvider
15 | .when(
16 | '/github/:user',
17 | {
18 | templateUrl : 'app/github/templates/user.html',
19 | controller : 'GitHubUserCtrl',
20 | controllerAs : 'vm'
21 | }
22 | )
23 | .when(
24 | '/github/:user/:repo/',
25 | {
26 | templateUrl : 'app/github/templates/repo.html',
27 | controller : 'GitHubRepositoryCtrl',
28 | controllerAs : 'vm'
29 | }
30 | );
31 |
32 | }
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/src/app/github/services/data.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.factory('GithubDataService', GithubDataService);
7 |
8 | //---
9 |
10 | GithubDataService.$inject = [
11 | 'GithubUserInfoService',
12 | 'GithubUserRepositoriesService',
13 | 'GithubUserGistsService',
14 | 'GithubRepositoryInfoService',
15 | 'GithubRepositoryContributorsService'
16 | ];
17 |
18 | function GithubDataService(
19 | userInfo, userRepositories, userGists,
20 | repositoryInfo, repositoryContributors
21 | ) {
22 |
23 | //--- api
24 | return {
25 | user: {
26 | info: userInfo,
27 | repositories: userRepositories,
28 | gists: userGists
29 | },
30 | repository: {
31 | info: repositoryInfo,
32 | contributors: repositoryContributors
33 | }
34 | };
35 | }
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/src/app/github/services/repository/contributors.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../../module');
5 |
6 | module.factory('GithubRepositoryContributorsService', RepositoryContributorsService);
7 |
8 | //---
9 |
10 | RepositoryContributorsService.$inject = [
11 | 'GithubResource', 'CacheService'
12 | ];
13 |
14 | function RepositoryContributorsService(resource, cacheService) {
15 | //--- private
16 | var persistenceKey = 'RepositoryContributors';
17 |
18 | var cache = cacheService(persistenceKey, function loadRemoteData(options) {
19 | return resource.get({
20 | 'query': 'repos',
21 | 'user': options.user,
22 | 'repo': options.repo,
23 | 'spec': 'contributors'
24 | }).$promise;
25 | });
26 |
27 | //--- api
28 | return {
29 | get: cache.get
30 | };
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/src/app/github/services/repository/info.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../../module');
5 |
6 | module.factory('GithubRepositoryInfoService', RepositoryInfoService);
7 |
8 | //---
9 |
10 | RepositoryInfoService.$inject = [
11 | 'GithubResource', 'CacheService'
12 | ];
13 |
14 | function RepositoryInfoService(resource, cacheService) {
15 | //--- private
16 | var persistenceKey = 'RepositoryInfo';
17 |
18 | var cache = cacheService(persistenceKey, function loadRemoteData(options) {
19 | return resource.get({
20 | 'query': 'repos',
21 | 'user': options.user,
22 | 'repo': options.repo
23 | }).$promise;
24 | });
25 |
26 | //--- api
27 | return {
28 | get: cache.get
29 | };
30 | }
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/src/app/github/services/user/gists.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../../module');
5 |
6 | module.factory('GithubUserGistsService', UserGistsService);
7 |
8 | //---
9 |
10 | UserGistsService.$inject = [
11 | 'GithubResource', 'CacheService'
12 | ];
13 |
14 | function UserGistsService(resource, cacheService) {
15 | //--- private
16 | var persistenceKey = 'UserGists';
17 |
18 | var cache = cacheService(persistenceKey, function loadRemoteData(options) {
19 | return resource
20 | .get({
21 | 'user': options.user,
22 | 'repo': 'gists'
23 | })
24 | .$promise;
25 | });
26 |
27 | //--- api
28 | return {
29 | get: cache.get
30 | };
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/src/app/github/services/user/info.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | // var moment = require('moment');
5 |
6 | var module = require('../../module');
7 |
8 | module.factory('GithubUserInfoService', UserInfoService);
9 |
10 | //---
11 |
12 | UserInfoService.$inject = [
13 | 'GithubResource', 'CacheService'
14 | ];
15 |
16 | function UserInfoService(resource, cacheService) {
17 | //--- private
18 | var persistenceKey = 'UserInfo';
19 |
20 | var cache = cacheService(persistenceKey, function loadRemoteData(options) {
21 | return resource.get({
22 | 'user': options.user,
23 | 'repo': ''
24 | }).$promise;
25 | });
26 |
27 | //--- api
28 | return {
29 | get: cache.get
30 | };
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/src/app/github/services/user/repositories.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../../module');
5 |
6 | module.factory('GithubUserRepositoriesService', UserRepositoriesService);
7 |
8 | //---
9 |
10 | UserRepositoriesService.$inject = [
11 | 'GithubResource', 'CacheService'
12 | ];
13 |
14 | function UserRepositoriesService(resource, cacheService) {
15 | //--- private
16 | var persistenceKey = 'UserRepositories';
17 |
18 | var cache = cacheService(persistenceKey, function loadRemoteData(options) {
19 | return resource.get({
20 | 'user': options.user
21 | }).$promise;
22 | });
23 |
24 | //--- api
25 | return {
26 | get: cache.get
27 | };
28 | }
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/src/app/github/styles/_avatar.scss:
--------------------------------------------------------------------------------
1 | .avatar {
2 |
3 | display: inline-block;
4 | *display: inline; zoom: 1;
5 | height: 78px;
6 | padding: 2px;
7 |
8 | img {
9 | display: block;
10 | width: 75px;
11 | height: 75px;
12 | border: 0;
13 | @include border-radius(3px);
14 | }
15 |
16 | }
17 |
18 | .avatar:hover,
19 | .user-avatar {
20 | @include box-shadow(0, 0, 3px, rgba(0,0,0,0.5));
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/github/styles/_contributor.scss:
--------------------------------------------------------------------------------
1 | .contributor {
2 |
3 | margin: 5px;
4 | display: inline-block;
5 | *display: inline; zoom: 1;
6 |
7 | .avatar {
8 | position: relative;
9 | display: block;
10 |
11 | &:link,
12 | &:visited,
13 | &:hover,
14 | &:active {
15 | text-decoration: none;
16 | }
17 |
18 | }
19 |
20 | .name,
21 | .contributions {
22 | position: absolute;
23 | left: 0;
24 | margin: 2px;
25 | padding: 0 4px;
26 | width: 68px;
27 | font-size: 11px;
28 | color: #fff;
29 | background: #000;
30 | background: rgba(0,0,0, 0.4);
31 | text-shadow: 0 1px 0 rgba(0,0,0, 0.5);
32 | }
33 |
34 | // top
35 | .contributions {
36 | top: 0;
37 | -webkit-border-top-left-radius: 3px;
38 | -webkit-border-top-right-radius: 3px;
39 | -moz-border-radius-topleft: 3px;
40 | -moz-border-radius-topright: 3px;
41 | border-top-left-radius: 3px;
42 | border-top-right-radius: 3px;
43 | }
44 |
45 | // bottom
46 | .name {
47 | bottom: 0;
48 | white-space: nowrap;
49 | overflow: hidden;
50 | text-overflow: ellipsis;
51 | -webkit-border-bottom-right-radius: 3px;
52 | -webkit-border-bottom-left-radius: 3px;
53 | -moz-border-radius-bottomright: 3px;
54 | -moz-border-radius-bottomleft: 3px;
55 | border-bottom-right-radius: 3px;
56 | border-bottom-left-radius: 3px;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/app/github/styles/_main.scss:
--------------------------------------------------------------------------------
1 | #github-app {
2 |
3 | @import "avatar";
4 | @import "user";
5 | @import "repo";
6 | @import "contributor";
7 | @import "techs";
8 |
9 | //---
10 |
11 | $userNotFoundSize: 128px;
12 |
13 | .userNotFound {
14 |
15 | background-image: data-uri('image/png;base64', '../img/user.png');
16 | background-position: center top;
17 | background-repeat: no-repeat;
18 | min-width: $userNotFoundSize;
19 | min-height: $userNotFoundSize;
20 |
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/github/styles/_repo.scss:
--------------------------------------------------------------------------------
1 | .repo {
2 |
3 | margin: 1px 0;
4 | padding: 0 6px;
5 | color: #333;
6 | background: #F7F7F7;
7 | border-bottom: 1px solid #E5E6F1;
8 |
9 | &:hover {
10 | background: #E5E5E5;
11 | }
12 |
13 | .name {
14 |
15 | ul {
16 | list-style: none;
17 | padding-left: 0;
18 | height: 47px;
19 | line-height: 47px;
20 | }
21 |
22 | div, li {
23 | float: left;
24 | vertical-align: middle;
25 | display: table-cell;
26 | width: 65%;
27 | }
28 |
29 | }
30 |
31 | .stats {
32 |
33 | margin-top: 6px;
34 | display: table-cell;
35 | vertical-align: middle;
36 |
37 | ul {
38 | list-style: none;
39 | padding-left: 0;
40 | height: 47px;
41 | line-height: 47px;
42 | }
43 |
44 | div, li {
45 | padding: 10px;
46 | float: left;
47 | vertical-align: middle;
48 | display: table-cell;
49 | }
50 |
51 | b {
52 | display: block;
53 | }
54 |
55 | span {
56 | display: block;
57 | font-size: 11px;
58 | color: #767676;
59 | }
60 |
61 | .lang {
62 | text-align: center;
63 | line-height: 11px;
64 | margin-top: 15px;
65 | }
66 |
67 | .watchers,
68 | .forks {
69 | width: 50px;
70 | text-align: center;
71 | line-height: 11px;
72 | margin-top: 15px;
73 | }
74 |
75 | }
76 |
77 | .line-desc {
78 | margin: 10px 20px 0 0;
79 | overflow: hidden;
80 | text-overflow: ellipsis;
81 | color: #667;
82 | width: auto;
83 | }
84 |
85 | }
86 |
87 |
88 | //---
89 |
90 | .repo-desc {
91 | margin: 10px 20px 5px 5px;
92 | overflow: hidden;
93 | text-overflow: ellipsis;
94 | color: #767676;
95 | width: auto;
96 | }
97 |
98 | //---
99 |
--------------------------------------------------------------------------------
/src/app/github/styles/_techs.scss:
--------------------------------------------------------------------------------
1 | .techs {
2 |
3 | li {
4 | padding-left: 10px;
5 | padding-top: 3px;
6 | padding-bottom: 3px;
7 | vertical-align: middle;
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/github/styles/_user.scss:
--------------------------------------------------------------------------------
1 | @mixin common-li($paddin: 10px) {
2 | li {
3 | float: left;
4 | text-align: center;
5 | vertical-align: middle;
6 | display: table-cell;
7 | padding: $paddin;
8 | }
9 | }
10 |
11 | .user {
12 |
13 | .login {
14 |
15 | div {
16 | float: left;
17 | padding: 10px;
18 | vertical-align: middle;
19 | display: table-cell;
20 | }
21 |
22 | }
23 |
24 | .login-mobile {
25 |
26 | div {
27 | margin-left: 10%;
28 | float: left;
29 | padding: 10px;
30 | vertical-align: middle;
31 | display: table-cell;
32 | }
33 |
34 | }
35 |
36 | .info {
37 |
38 | ul {
39 | padding-left: 0;
40 | margin-left: 0;
41 | }
42 |
43 | @include common-li;
44 |
45 | }
46 |
47 | .info-mobile {
48 |
49 | ul {
50 | padding-left: 0;
51 | margin-left: 20%;
52 | }
53 |
54 | @include common-li;
55 |
56 | }
57 |
58 | .info-repo-mobile {
59 |
60 | ul {
61 | padding-left: 0;
62 | margin-left: 30%;
63 | }
64 |
65 | @include common-li;
66 |
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/app/github/templates/repo-contributors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Project Contributors ({{vm.contributors.length}})
5 |
6 |
18 |
19 |
--------------------------------------------------------------------------------
/src/app/github/templates/repo-info.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
{{vm.repoInfo.owner.login}}
23 | ({{vm.repoInfo.name}})
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
{{vm.repoInfo.owner.login}}
38 | ({{vm.repoInfo.name}})
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | -
52 |
{{vm.repoInfo.watchers}}
53 |
54 |
55 | -
56 |
{{vm.repoInfo.forks}}
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
View on GitHub
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | -
75 |
{{vm.repoInfo.watchers}}
76 |
77 |
78 | -
79 |
{{vm.repoInfo.forks}}
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | Description:
95 | {{vm.repoInfo.description}}
96 |
97 |
--------------------------------------------------------------------------------
/src/app/github/templates/repo.html:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/src/app/github/templates/user-gists.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | -
9 |
10 | {{gist.description}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | -
19 | {{vm.getFile(gist.files).language}}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/app/github/templates/user-info.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
{{vm.user.login}}
24 | ({{vm.user.name}})
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
{{vm.user.login}}
39 | ({{vm.user.name}})
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | -
53 |
{{vm.user.public_repos}}
54 |
55 |
56 | -
57 |
{{vm.user.followers}}
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
View on GitHub
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | -
77 |
{{vm.user.public_repos}}
78 |
79 |
80 | -
81 |
{{vm.user.followers}}
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/app/github/templates/user-repos.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | -
9 |
10 | {{repo.description}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | -
20 | {{repo.language}}
21 |
22 | -
23 | {{repo.watchers}}
24 |
25 |
26 |
27 |
28 | -
29 | {{repo.forks}}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/app/github/templates/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
{{vm.user.message}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/app/main/controllers/about.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.controller('AboutCtrl', AboutCtrl);
7 |
8 | //---
9 |
10 | AboutCtrl.$inject = ['NavBarService'];
11 |
12 | function AboutCtrl(NavBarService) { // custom parameter scope name if you want
13 | var vm = this;
14 |
15 | vm.pageName = 'About this application';
16 |
17 | //---
18 |
19 | NavBarService.aboutPageSelected();
20 |
21 | //---
22 |
23 | // TODO: define internal processing code
24 |
25 | }
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/src/app/main/controllers/search.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.controller('SearchCtrl', SearchCtrl);
7 |
8 | //---
9 |
10 | SearchCtrl.$inject = ['$location', 'NavBarService'];
11 |
12 | function SearchCtrl($location, NavBarService) {
13 | var vm = this;
14 |
15 | vm.searchField = '';
16 | vm.searchAction = searchAction;
17 |
18 | //---
19 |
20 | // update search menu option url
21 | NavBarService.updateSearchUrl('/');
22 |
23 | //---
24 |
25 | function searchAction() {
26 | var user = vm.searchField || 'erkobridee';
27 |
28 | $location.path(['', 'github', user, ''].join('/'));
29 | }
30 |
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/src/app/main/module.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 | require('angularResource');
6 | require('angularRoute');
7 |
8 | // angular module definition
9 | return angular.module(
10 | // module name
11 | 'main',
12 |
13 | // module dependencies
14 | [
15 | 'ngResource',
16 | 'ngRoute',
17 |
18 | require('app/commons/components/package').name,
19 | require('app/github/package').name,
20 | ]
21 | );
22 |
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/main/package.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 | require('./services/navbar');
6 | require('./services/pluralize');
7 | require('./controllers/about');
8 | require('./controllers/search');
9 | require('./routes');
10 |
11 | return module;
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/src/app/main/routes.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('./module');
5 |
6 | module.config(configureRoutes);
7 |
8 | //--- https://docs.angularjs.org/api/ngRoute
9 |
10 | configureRoutes.$inject = [
11 | '$routeProvider',
12 | '$locationProvider',
13 | '$sceDelegateProvider'
14 | ];
15 |
16 | function configureRoutes(
17 | $routeProvider,
18 | $locationProvider,
19 | $sceDelegateProvider
20 | ) {
21 |
22 | // remove the ! added by angular v1.6.1
23 | $locationProvider.hashPrefix('');
24 |
25 | // https://docs.angularjs.org/api/ng/service/$sce
26 | // https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider#resourceUrlWhitelist
27 | $sceDelegateProvider.resourceUrlWhitelist([
28 | // Allow same origin resource loads.
29 | 'self',
30 |
31 | // Allow github api domain
32 | 'https://api.github.com/**'
33 | ]);
34 |
35 | $routeProvider
36 | .when(
37 | '/',
38 | {
39 | templateUrl : 'app/main/templates/search.html',
40 | controller : 'SearchCtrl',
41 | controllerAs : 'vm'
42 | }
43 | )
44 | .when(
45 | '/about',
46 | {
47 | templateUrl : 'app/main/templates/about.html',
48 | controller : 'AboutCtrl',
49 | controllerAs : 'vm'
50 | }
51 | )
52 | .otherwise({redirectTo:'/'});
53 |
54 | }
55 |
56 | });
57 |
--------------------------------------------------------------------------------
/src/app/main/services/navbar.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.factory('NavBarService', NavBarService);
7 |
8 | //---
9 |
10 | // NavBarService.$inject = [ ];
11 |
12 | function NavBarService() {
13 |
14 | var nav = {
15 | showForkBelt: 'yes',
16 | searchUrlPath: '/',
17 | searchNotActive: '',
18 | aboutNotActive: 'x'
19 | };
20 |
21 | //---
22 |
23 | var service = {
24 | getNav: getNav,
25 | searchPageSelected: searchPageSelected,
26 | aboutPageSelected: aboutPageSelected,
27 | updateSearchUrl: updateSearchUrl
28 | };
29 |
30 | return service;
31 |
32 | //---
33 |
34 | function getNav() {
35 | return nav;
36 | }
37 |
38 | function searchPageSelected() {
39 | nav.searchNotActive = '';
40 | nav.aboutNotActive = 'x';
41 | }
42 |
43 | function aboutPageSelected() {
44 | nav.showForkBelt = 'yes';
45 |
46 | nav.searchNotActive = 'x';
47 | nav.aboutNotActive = '';
48 | }
49 |
50 | function updateSearchUrl(urlPath) {
51 | if('/' === urlPath) {
52 | nav.showForkBelt = 'yes';
53 | } else {
54 | nav.showForkBelt = undefined;
55 | }
56 |
57 | nav.searchUrlPath = urlPath;
58 | searchPageSelected();
59 | }
60 |
61 | }
62 |
63 | });
64 |
--------------------------------------------------------------------------------
/src/app/main/services/pluralize.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var module = require('../module');
5 |
6 | module.factory('PluralizeService', PluralizeService);
7 |
8 | //---
9 |
10 | // PluralizeService.$inject = [ ];
11 |
12 | function PluralizeService() {
13 |
14 | var service = {
15 |
16 | publicRepoForms: {
17 | '1': 'Public Repo',
18 | 'other': 'Public Repos'
19 | },
20 |
21 | followerForms: {
22 | '1': 'Follower',
23 | 'other': 'Followers'
24 | },
25 |
26 | watchForms: {
27 | '1': 'Watcher',
28 | 'other': 'Watchers'
29 | },
30 |
31 | forkForms: {
32 | '1': 'Fork',
33 | 'other': 'Forks'
34 | }
35 |
36 | };
37 |
38 | return service;
39 |
40 | }
41 |
42 | });
43 |
--------------------------------------------------------------------------------
/src/app/main/templates/about.html:
--------------------------------------------------------------------------------
1 |
2 |
{{vm.pageName}}
3 |
4 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
37 |
38 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/app/main/templates/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
GitHub user:
4 |
18 |
Public Repositories and Gists
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erkobridee/angularjs-github-info/1eeb4219eb4bf661f7c47ccfb9d9329a80f6d865/src/img/loading.gif
--------------------------------------------------------------------------------
/src/img/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erkobridee/angularjs-github-info/1eeb4219eb4bf661f7c47ccfb9d9329a80f6d865/src/img/user.png
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | AngularJS - GitHub Info
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/ng.app.js:
--------------------------------------------------------------------------------
1 | define(function(require) {
2 | 'use strict';
3 |
4 | var angular = require('angular');
5 |
6 | angular.element(document).ready(startAngularApp);
7 |
8 | //---
9 |
10 | function startAngularApp() {
11 |
12 | console.log('start angular application');
13 |
14 | // define angular module to bootstrap application
15 | var module = angular.module(
16 | // module name
17 | 'run',
18 |
19 | // module dependencies
20 | [
21 | require('app/main/package').name
22 | ]
23 | );
24 |
25 | // start angular app
26 | angular.bootstrap(document, [module.name]);
27 |
28 | }
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/src/require.config.js:
--------------------------------------------------------------------------------
1 | require({
2 |
3 | // libraries dependencies (fallback support)
4 | paths: {
5 |
6 | jquery: [
7 | 'libs/jquery/jquery.min'
8 | ],
9 | bootstrap: [
10 | 'libs/bootstrap/js/bootstrap.min'
11 | ],
12 | angular: [
13 | 'libs/angular/angular.min'
14 | ],
15 | angularResource: [
16 | 'libs/angular-resource/angular-resource.min'
17 | ],
18 | angularRoute: [
19 | 'libs/angular-route/angular-route.min'
20 | ],
21 | moment: [
22 | 'libs/moment/moment.min'
23 | ],
24 | hashids: [
25 | 'libs/hashids/hashids.min'
26 | ]
27 |
28 | },
29 |
30 | // define js scripts dependencies
31 | shim: {
32 |
33 | 'bootstrap': {
34 | deps: ['jquery']
35 | },
36 |
37 | 'angular': {
38 | deps: ['bootstrap'],
39 | exports: 'angular'
40 | },
41 |
42 | 'angularResource': {
43 | deps: ['angular']
44 | },
45 |
46 | 'angularRoute': {
47 | deps: ['angular']
48 | },
49 |
50 | 'hashids': {
51 | exports: 'hashids'
52 | }
53 |
54 | },
55 |
56 | priority: [
57 | 'angular'
58 | ],
59 |
60 | deps: ['./ng.app']
61 |
62 | });
63 |
--------------------------------------------------------------------------------
/src/scss/_CommonFunctions.scss:
--------------------------------------------------------------------------------
1 | @mixin border-radius($radius: 5px) {
2 | -webkit-border-radius: $radius;
3 | -moz-border-radius: $radius;
4 | -ms-border-radius: $radius;
5 | -o-border-radius: $radius;
6 | border-radius: $radius;
7 | }
8 |
9 | @mixin box-shadow($x: 0, $y: 0, $blur: 1px, $color: #000) {
10 | -webkit-box-shadow: $x $y $blur $color;
11 | -moz-box-shadow: $x $y $blur $color;
12 | -ms-box-shadow: $x $y $blur $color;
13 | -o-box-shadow: $x $y $blur $color;
14 | box-shadow: $x $y $blur $color;
15 | }
16 |
--------------------------------------------------------------------------------
/src/scss/_TopScreen.scss:
--------------------------------------------------------------------------------
1 | body { padding-top: 60px; padding-bottom: 40px; }
2 |
--------------------------------------------------------------------------------
/src/scss/app.scss:
--------------------------------------------------------------------------------
1 | @import "CommonFunctions";
2 |
3 | @import "TopScreen";
4 |
5 | @import "../app/github/styles/main";
6 |
--------------------------------------------------------------------------------
/tools/config.js:
--------------------------------------------------------------------------------
1 | module.exports = (function() {
2 |
3 | var path = require('path');
4 | var pkg = require('../package');
5 |
6 | //---
7 |
8 | var config = {};
9 |
10 | //--
11 |
12 | config.root = './';
13 |
14 | //--
15 |
16 | config.packages = [
17 | './package.json',
18 | './bower.json'
19 | ];
20 |
21 | //---
22 |
23 | var bannerTitle = pkg.title || pkg.name;
24 |
25 | config.banner =
26 | '/*!\n' +
27 | ' * ' + bannerTitle + '\n' +
28 | ' * ' + pkg.description + '\n' +
29 | ' * @license ' + pkg.license + '\n' +
30 | ' * v' + pkg.version + '\n' +
31 | ' */\n';
32 |
33 | //---
34 |
35 | config.git = {
36 | branch: 'gh-pages',
37 | commitMessage: '<%= branch %> automated commit <%= time %>'
38 | };
39 |
40 | //---
41 |
42 | config.vendorsDirName = 'libs';
43 |
44 | config.paths = {
45 | src : 'src',
46 | bower : '.local/bower',
47 | repoDir : '.local/' + config.git.branch,
48 | build : '.temp',
49 | vendor : '.temp/libs',
50 | dist : 'dist'
51 | };
52 |
53 | //---
54 |
55 | config.js = {
56 |
57 | project: {
58 | lint : [
59 | config.paths.src + '/**/*.js'
60 | ],
61 | watch : [
62 | config.paths.src + '/**/*.js'
63 | ],
64 | copy2build : [
65 | config.paths.src + '/**/*.js'
66 | ]
67 | },
68 |
69 | tools: [
70 | 'gulpfile.js',
71 | 'tools/**/*.js',
72 | '!tools/lib/generate/templates/**/*'
73 | ]
74 |
75 | };
76 |
77 | //---
78 |
79 | var stylefilename = 'app';
80 |
81 | config.styles = {
82 | sass: {
83 | main : config.paths.src + '/scss/' + stylefilename + '.scss',
84 | project : config.paths.src + '/{app,scss}/**/*.scss'
85 | }
86 | };
87 |
88 | //---
89 |
90 | config.autoprefixer = {
91 | browsers: [
92 | 'last 2 versions', 'last 4 Android versions'
93 | ]
94 | };
95 |
96 | //---
97 |
98 | config.html = {
99 | index: config.paths.src + '/index.html',
100 | files: config.paths.src + '/**/*.html'
101 | };
102 |
103 | // TODO: review - needed?
104 | config.htmlmin = {
105 | collapseBooleanAttributes: true,
106 | collapseWhitespace: true,
107 | removeAttributeQuotes: true,
108 | removeComments: true,
109 | removeEmptyAttributes: true,
110 | removeRedundantAttributes: true,
111 | removeScriptTypeAttributes: true,
112 | removeStyleLinkTypeAttributes: true
113 | };
114 |
115 | config.html2js = {
116 | filename: 'templatesCache.js',
117 | moduleName: 'templatesCache',
118 | src: [
119 | config.paths.src + '/app/**/*.html',
120 | config.paths.src + '/shared/**/*.html'
121 | ],
122 | dest: path.join( config.paths.build, 'app', 'main' )
123 | };
124 |
125 | //---
126 |
127 | config.require = {
128 | name: 'ng.app',
129 | config: path.join(config.paths.src, 'require.config.js'),
130 | build: path.join(config.paths.build, 'require.config.js')
131 | };
132 |
133 | //---
134 |
135 | config.webserver = {
136 | port: 1337,
137 |
138 | // https://github.com/nodejitsu/node-http-proxy#options
139 | // https://github.com/chimurai/http-proxy-middleware#http-proxy-options
140 | proxies: [
141 | {
142 | host: 'localhost',
143 | port: 9000,
144 | context: 'rest'
145 | }
146 | ]
147 | };
148 |
149 | //---
150 |
151 | return config;
152 |
153 | })();
154 |
--------------------------------------------------------------------------------
/tools/gulp/helpers/$.js:
--------------------------------------------------------------------------------
1 | // Expose all Gulp plugins found
2 | var $ = module.exports = require('gulp-load-plugins')();
3 |
4 | //---
5 |
6 | // Expose some other modules
7 | $.path = require('path');
8 |
9 | $.rootPath = $.path.resolve( './' );
10 |
11 | // [Gist] Better local require() paths for Node.js
12 | // https://gist.github.com/branneman/8048520
13 | $.rootRequire = function( name ) {
14 | return require( $.path.join( $.rootPath, name ) );
15 | };
16 |
17 | //---
18 |
19 | $.del = require('del');
20 | $.lazypipe = require('lazypipe');
21 | $.runSequence = require('run-sequence');
22 |
23 | $.browserSync = require('browser-sync').create();
24 | $.reload = $.browserSync.reload;
25 |
26 | $.open = require('open');
27 |
28 | //--- local modules
29 |
30 | $.pkg = $.rootRequire('package.json');
31 |
32 | $.config = $.rootRequire('tools/config');
33 |
34 | $.localip = $.rootRequire('tools/lib/localip');
35 |
36 | $.requirejs = $.rootRequire('tools/lib/requirejs');
37 |
38 | //---
39 |
40 | $.args = require('yargs').argv;
41 |
42 | //---
43 |
44 | $.is = {
45 | debug : !!$.args.debug,
46 | release : !!$.args.release,
47 | preview : !!$.args.preview,
48 | proxy : !!$.args.proxy,
49 | publish : !!$.args.publish,
50 | init : !!$.args.init
51 | };
52 |
53 | //---
54 | // @begin: define output dir
55 |
56 | (function() {
57 |
58 | $.config.paths.outputDir = (
59 | ($.is.release || $.is.preview) ?
60 | $.config.paths.dist :
61 | $.config.paths.build
62 | );
63 |
64 | })();
65 |
66 | // @end: define output dir
67 | //---
68 | // @begin: check webserver configs
69 |
70 | (function() {
71 |
72 | $.config
73 | .webserver = $.config.webserver || {};
74 |
75 | $.config
76 | .webserver
77 | .port = parseInt($.args.port, 10) || $.config.webserver.port || 3000;
78 |
79 | // do not configure proxy if proxy flag isn't present
80 | if(!$.is.proxy) return;
81 |
82 | // middlewares array
83 | $.config
84 | .webserver
85 | .middlewares = [];
86 |
87 | //---
88 | // @begin: config proxies
89 | var proxyMiddleware = require('http-proxy-middleware'),
90 | hasGulpTaskName = !!$.args._[0];
91 |
92 | if( $.config.webserver.proxies ) {
93 | $.config
94 | .webserver
95 | .proxies.forEach(function(proxy) {
96 | if( !$.config.webserver.proxy ) $.config.webserver.proxy = proxy;
97 | configProxy( mountProxyOptions( proxy ) );
98 | });
99 | } else if( $.config.webserver.proxy ) {
100 | configProxy( mountProxyOptions( $.config.webserver.proxy ) );
101 | }
102 |
103 | function mountProxyOptions( proxy ) {
104 | return {
105 | host : proxy.host || 'localhost',
106 | port : proxy.port || 80,
107 | context : checkContext(proxy.context),
108 | https : proxy.https || false,
109 | xforward : proxy.xforward || false
110 | };
111 | }
112 |
113 | function configProxy( proxyOptions ) {
114 | $.config
115 | .webserver
116 | .middlewares
117 | .push(
118 | proxyMiddleware(
119 | proxyOptions.context,
120 | {
121 | target : mountTarget( proxyOptions ),
122 | secure : proxyOptions.https,
123 | xfwd : proxyOptions.xforward
124 | }
125 | )
126 | );
127 | }
128 |
129 | function checkContext( context ) {
130 | if( !context ) return '/api';
131 | if( !/^\//.test(context) ) context = '/' + context;
132 | return context;
133 | }
134 |
135 | function mountTarget( proxyOptions ) {
136 | return (
137 | ( proxyOptions.https ? 'https://' : 'http://' ) +
138 | proxyOptions.host + ':' + proxyOptions.port
139 | );
140 | }
141 | // @end: config proxies
142 | //---
143 |
144 | })();
145 |
146 | // @end: check webserver configs
147 | //---
148 |
149 | /**
150 | * Log a message or series of messages using chalk's blue color.
151 | * Can pass in a string, object or array.
152 | */
153 | $.log = function(msg) {
154 | if (typeof(msg) === 'object') {
155 | for (var item in msg) {
156 | if (msg.hasOwnProperty(item)) {
157 | $.util.log($.util.colors.blue(msg[item]));
158 | }
159 | }
160 | } else {
161 | $.util.log($.util.colors.blue(msg));
162 | }
163 | };
164 |
165 | $.onError = function(err) {
166 | $.log(err);
167 | };
168 |
169 | //---
170 |
171 | $.projectInfoMsg = function() {
172 | $.log('');
173 | $.log('project: ' + $.pkg.name + ' v' + $.pkg.version);
174 | $.log('description: ' + $.pkg.description);
175 | $.log('');
176 |
177 | var msg = '';
178 |
179 | if( $.is.release ) {
180 | msg += ' release';
181 |
182 | $.log('>> ' + msg);
183 | $.log('');
184 | } else if( $.is.proxy ) {
185 | $.log('>> running with proxy');
186 | }
187 | };
188 |
--------------------------------------------------------------------------------
/tools/gulp/helpers/loadTasks.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var fs = require('fs');
3 | var gulp = require('gulp');
4 | var $ = require('./$');
5 |
6 |
7 | function loadTask(filepath) {
8 | var filename = path.basename(filepath);
9 | var msg = 'Loading "' + filename + '" tasks...';
10 | var fn;
11 |
12 | try {
13 | // Load taskfile.
14 | fn = require(path.resolve(filepath));
15 | if(typeof fn === 'function') {
16 | fn.call({}, gulp, $);
17 | }
18 | } catch(e) {
19 | console.log(msg);
20 | // Something went wrong.
21 | console.error(e);
22 | }
23 | fn = null;
24 | }
25 |
26 | function loadTasks(tasksDir) {
27 | var files = fs
28 | .readdirSync(tasksDir)
29 | .filter(function isValid(file) {
30 | return (file !== '.DS_store' && file.indexOf('.') !== 0 && /\.js$/.test(file));
31 | });
32 |
33 | // load tasks from files
34 | files.forEach(function(filename) {
35 | loadTask(path.join(tasksDir, filename));
36 | });
37 | }
38 |
39 | module.exports = function(tasksDir) {
40 | if(fs.existsSync(tasksDir)) {
41 | loadTasks(tasksDir);
42 | } else {
43 | console.error('Tasks directory "' + tasksDir + '" not found.');
44 | }
45 | };
46 |
--------------------------------------------------------------------------------
/tools/gulp/helpers/sharedStreams.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var $ = require('./$');
3 |
4 | // shared streams to gulp tasks
5 | var streams = $.streams = {};
6 |
7 | //--
8 |
9 | var outputCssDir = $.path.join( $.config.paths.outputDir, 'styles' );
10 |
11 | //---
12 |
13 | streams.autoprefix = function() {
14 | return $.autoprefixer( $.config.autoprefixer );
15 | };
16 |
17 | //---
18 |
19 | streams.sass = function() {
20 |
21 | return gulp
22 | .src( $.config.styles.sass.main )
23 | .pipe( $.if( $.is.debug, $.debug() ) )
24 | .pipe( $.sass().on('error', $.sass.logError) )
25 | .pipe( streams.autoprefix() )
26 | .pipe( $.injectString.prepend( $.config.banner ) )
27 | .pipe( $.if( ($.is.release || $.is.preview), $.minifyCss() ) )
28 | .pipe( gulp.dest( outputCssDir ) )
29 | .pipe( $.filter( '**.css' ) )
30 | .pipe( $.if( $.browserSync.active, $.reload({stream: true}) ) )
31 | .on( 'error', $.onError );
32 |
33 | };
34 |
--------------------------------------------------------------------------------
/tools/gulp/index.js:
--------------------------------------------------------------------------------
1 | require('./helpers/sharedStreams');
2 |
3 | module.exports.loadTasks = require('./helpers/loadTasks');
4 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/bower.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('bower:clean', $.del.bind(null, [
4 | $.config.paths.vendor
5 | ]));
6 |
7 | gulp.task('bower:angular', function() {
8 | return gulp.src([
9 | $.config.paths.bower + '/vendor/angular*/angular*.{js,map,css}'
10 | ])
11 | .pipe(gulp.dest( $.config.paths.vendor ));
12 | });
13 |
14 | gulp.task('bower:bootstrap', function() {
15 | return gulp.src([
16 | $.config.paths.bower + '/vendor/bootstrap/dist/**/*'
17 | ])
18 | .pipe(gulp.dest( $.config.paths.vendor + '/bootstrap' ));
19 | });
20 |
21 | gulp.task('bower:jquery', function() {
22 | return gulp.src([
23 | $.config.paths.bower + '/vendor/jquery/dist/**/*'
24 | ])
25 | .pipe(gulp.dest( $.config.paths.vendor + '/jquery' ));
26 | });
27 |
28 | gulp.task('bower:requirejs', function() {
29 | return gulp.src([
30 | $.config.paths.bower + '/vendor/requirejs/require.js'
31 | ])
32 | .pipe(gulp.dest( $.config.paths.vendor + '/requirejs' ))
33 | .pipe( $.uglify() )
34 | .pipe( $.rename({ suffix: '.min' }) )
35 | .pipe(gulp.dest( $.config.paths.vendor + '/requirejs' ));
36 | });
37 |
38 | gulp.task('bower:hashids', function() {
39 | return gulp.src([
40 | $.config.paths.bower + '/vendor/hashids/dist/*.min.js'
41 | ])
42 | .pipe(gulp.dest( $.config.paths.vendor + '/hashids' ));
43 | });
44 |
45 | gulp.task('bower:momentjs', function() {
46 | return gulp.src([
47 | $.config.paths.bower + '/vendor/moment/min/*.min.js'
48 | ])
49 | .pipe(gulp.dest( $.config.paths.vendor + '/moment' ));
50 | });
51 |
52 | gulp.task('bower', ['bower:clean'], function(done) {
53 | $.runSequence([
54 | 'bower:angular',
55 | 'bower:bootstrap',
56 | 'bower:jquery',
57 | 'bower:requirejs',
58 | 'bower:hashids',
59 | 'bower:momentjs'
60 | ], done);
61 | });
62 |
63 | };
64 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/build.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('build', function( done ) {
4 |
5 | $.runSequence(
6 | 'copy:vendor2dist',
7 | [
8 | 'copy:js2build',
9 | 'styles',
10 | 'build:min:index.html',
11 | 'build:min:images'
12 | ],
13 | 'html2js',
14 | 'update:main:package.js',
15 | 'requirejs',
16 | 'build:concat:js',
17 | 'clean:build',
18 | done
19 | );
20 |
21 | });
22 |
23 | gulp.task('build:min:index.html', function() {
24 | return gulp.src( $.config.html.index )
25 | .pipe( $.htmlmin( $.config.htmlmin ) )
26 | .pipe( gulp.dest( $.config.paths.dist ) );
27 | });
28 |
29 | gulp.task('build:min:images', function() {
30 | return gulp.src( $.config.paths.src + '/img/**/*' )
31 | .pipe( $.imagemin({
32 | progressive: true,
33 | interlaced: true
34 | }) )
35 | .pipe( gulp.dest( $.config.paths.dist + '/img' ) );
36 | });
37 |
38 | gulp.task('build:concat:js', function() {
39 | var filter = $.filter([
40 | 'require.config.js'
41 | ], {restore: true});
42 |
43 | return gulp.src([
44 | $.config.paths.build + '/' + $.config.require.name + '.js',
45 | $.config.require.config
46 | ])
47 | .pipe( filter )
48 | .pipe( $.uglify() )
49 | .pipe( filter.restore )
50 | .pipe( $.concat( 'require.config.js' ) )
51 | .pipe( $.uglify() )
52 | .pipe( gulp.dest( $.config.paths.dist ) );
53 | });
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/bump.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | /**
4 | * Bump the version
5 | * --type=pre will bump the prerelease version *.*.*-x
6 | * --type=patch or no flag will bump the patch version *.*.x
7 | * --type=minor will bump the minor version *.x.*
8 | * --type=major will bump the major version x.*.*
9 | * --version=1.2.3 will bump to a specific version and ignore other flags
10 | */
11 | gulp.task('bump', function() {
12 |
13 | var msg = 'Bumping versions';
14 | var type = $.args.type;
15 | var version = $.args.version;
16 | var options = {};
17 | if (version) {
18 | options.version = version;
19 | msg += ' to ' + version;
20 | } else {
21 | options.type = type;
22 | msg += ' for a ' + type;
23 | }
24 | $.log( msg );
25 |
26 | return gulp
27 | .src( $.config.packages )
28 | .pipe( $.print() )
29 | .pipe( $.bump( options ) )
30 | .pipe( gulp.dest( $.config.root ) );
31 |
32 | });
33 |
34 | };
35 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/clean.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('clean:repo-dir', $.del.bind(null, [
4 | $.config.paths.repoDir
5 | ]));
6 |
7 | gulp.task('clean:repo-dir:content', $.del.bind(null, [
8 | $.config.paths.repoDir + '/' + '/**/*',
9 | '!' + $.config.paths.repoDir + '/{.git,.gitignore}'
10 | ]));
11 |
12 | gulp.task('clean:build', $.del.bind(null, [
13 | $.config.paths.build
14 | ]));
15 |
16 | gulp.task('clean:dist', $.del.bind(null, [
17 | $.config.paths.dist
18 | ]));
19 |
20 | gulp.task('clean', ['clean:dist', 'clean:build']);
21 |
22 | };
23 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/copy.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('copy:js2build', function() {
4 | return gulp.src( $.config.js.project.copy2build )
5 | .pipe( gulp.dest( $.config.paths.build ) );
6 | });
7 |
8 | gulp.task('copy:vendor2dist', function() {
9 | return gulp.src([
10 | $.config.paths.vendor + '/**/*'
11 | ])
12 | .pipe( gulp.dest( $.config.paths.dist + '/' + $.config.vendorsDirName ) );
13 | });
14 |
15 | gulp.task('copy:dist2repo-dir', function() {
16 | return gulp.src( $.config.paths.dist + '/**/*' )
17 | .pipe( gulp.dest( $.config.paths.repoDir ) );
18 | });
19 |
20 | };
21 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/default.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('run:flow', function(done) {
4 |
5 | var runTasks = [
6 | 'clean',
7 | 'validate',
8 | 'bower'
9 | ];
10 |
11 | if( $.is.init ) {
12 |
13 | runTasks = ['init'];
14 |
15 | } else if( $.is.publish ) {
16 |
17 | runTasks = runTasks.concat([ 'publish' ]);
18 |
19 | } else if( $.is.release ) {
20 |
21 | runTasks = runTasks.concat([ 'build' ]);
22 |
23 | } else if( $.is.preview ) {
24 |
25 | runTasks = runTasks.concat([
26 | 'build',
27 | 'webserver:preview'
28 | ]);
29 |
30 | } else {
31 |
32 | // dev flow
33 | runTasks = runTasks.concat([ 'watch' ]);
34 |
35 | }
36 |
37 | runTasks = runTasks.concat([ done ]);
38 | $.runSequence.apply(null, runTasks);
39 |
40 | });
41 |
42 | //---
43 |
44 | gulp.task('default', ['run:flow'], function() {
45 |
46 | $.projectInfoMsg();
47 |
48 | });
49 |
50 | };
51 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/help.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('help', $.taskListing);
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/html2js.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | var TEMPLATE_HEADER = [
4 | 'define(function(require) {',
5 | ' \'use strict\';',
6 | '',
7 | ' var module = require(\'./module\');',
8 | '',
9 | ' module.run(runner);',
10 | '',
11 | ' //---',
12 | '',
13 | ' runner.$inject = [\'$templateCache\'];',
14 | '',
15 | ' function runner($templateCache) {',
16 | ''
17 | ].join('\n');
18 |
19 | var TEMPLATE_FOOTER = [
20 | '',
21 | ' }',
22 | '});'
23 | ].join('\n');
24 |
25 | var html2jsOpts = {
26 | templateHeader : TEMPLATE_HEADER,
27 | templateFooter : TEMPLATE_FOOTER,
28 | base : function(file) {
29 | return file.path.replace( $.path.resolve($.config.paths.src) + $.path.sep , '' );
30 | }
31 | };
32 |
33 | //----------------------------------------------------------------------------
34 |
35 | gulp.task('html2js', function() {
36 | return gulp.src( $.config.html2js.src )
37 | .pipe( $.htmlmin( $.config.htmlmin ) )
38 | .pipe(
39 | $.angularTemplatecache(
40 | $.config.html2js.filename,
41 | html2jsOpts
42 | )
43 | )
44 | .pipe( gulp.dest( $.config.html2js.dest ) );
45 | });
46 |
47 | gulp.task('update:main:package.js', function() {
48 | return gulp.src( $.config.html2js.dest + '/package.js' )
49 | .pipe( $.injectString.before(
50 | 'return ', 'require(\'./' + $.config.html2js.filename + '\');\n '
51 | ) )
52 | .pipe( gulp.dest( $.config.html2js.dest ) );
53 | });
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/init.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('init', function( done ) {
4 |
5 | $.runSequence(
6 | 'clean:repo-dir',
7 | 'shell:git:clone',
8 | 'shell:git:checkout',
9 | done
10 | );
11 |
12 | });
13 |
14 | };
15 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/jshint.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | var jshintStream = $.lazypipe()
4 | .pipe( $.cached, 'jshint' )
5 | .pipe( $.jshint )
6 | .pipe( $.jshint.reporter, 'jshint-stylish' )
7 | .pipe( $.jshint.reporter, 'fail' );
8 |
9 | //---
10 |
11 | gulp.task('jshint:tools', function() {
12 | return gulp.src( $.config.js.tools )
13 | .pipe( jshintStream() );
14 | });
15 |
16 | gulp.task('jshint:project', function() {
17 | return gulp.src( $.config.js.project.lint )
18 | .pipe( jshintStream() );
19 | });
20 |
21 | gulp.task('jshint', ['jshint:tools', 'jshint:project']);
22 |
23 | };
24 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/lintspaces.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | // https://github.com/ck86/gulp-lintspaces
4 |
5 | var lintspacesStream = $.lazypipe()
6 | .pipe( $.cached, 'lintspaces' )
7 | .pipe( $.lintspaces, { editorconfig: '.editorconfig' } )
8 | .pipe( $.lintspaces.reporter );
9 |
10 | //---
11 |
12 | gulp.task('lintspaces:html', function() {
13 |
14 | return gulp.src( $.config.html.files )
15 | .pipe( lintspacesStream() );
16 |
17 | });
18 |
19 | gulp.task('lintspaces:js', function() {
20 |
21 | return gulp.src( $.config.js.project.lint )
22 | .pipe( lintspacesStream() );
23 |
24 | });
25 |
26 | gulp.task('lintspaces:tools', function() {
27 |
28 | return gulp.src( $.config.js.tools )
29 | .pipe( lintspacesStream() );
30 |
31 | });
32 |
33 | gulp.task('lintspaces:styles', function() {
34 |
35 | return gulp.src( $.config.styles.sass.project )
36 | .pipe( lintspacesStream() );
37 |
38 | });
39 |
40 | //---
41 |
42 | gulp.task('lintspaces', [
43 | 'lintspaces:html',
44 | 'lintspaces:styles',
45 | 'lintspaces:js',
46 | 'lintspaces:tools'
47 | ]);
48 |
49 | };
50 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/publish.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('publish', function( done ) {
4 |
5 | $.runSequence(
6 | [
7 | 'clean:repo-dir:content',
8 | 'shell:tools-build'
9 | ],
10 | 'copy:dist2repo-dir',
11 | 'shell:git:add',
12 | 'shell:git:commit',
13 | [
14 | 'clean',
15 | 'shell:git:push'
16 | ],
17 | done
18 | );
19 |
20 | });
21 |
22 | };
23 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/require.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | //----------------------------------------------------------------------------
4 |
5 | /*
6 | http://tech.pro/blog/1639/using-rjs-to-optimize-your-requirejs-project
7 |
8 | http://requirejs.org/docs/optimization.html
9 |
10 | https://github.com/jrburke/r.js/blob/master/build/example.build.js
11 |
12 | https://github.com/CaryLandholt/AngularFun/blob/master/Gruntfile.coffee
13 | */
14 |
15 | // https://github.com/kvindasAB/angular-enterprise-kickstart/blob/master/Gruntfile.js#L303
16 | var requireBuildConfig = {
17 | baseUrl: $.config.paths.build,
18 |
19 | mainConfigFile: $.config.require.build,
20 |
21 | name: $.config.require.name,
22 | out: $.path.join( $.config.paths.build, $.config.require.name + '.js' ),
23 |
24 | useStrict: true,
25 | wrap: {
26 | start: '(function() {\'use strict\';',
27 | end: '})();'
28 | },
29 | optimize: "uglify2",
30 | uglify2: {
31 | mangle: true,
32 | compress: {
33 | 'drop_console': true,
34 | 'drop_debugger': true,
35 | 'dead_code': true,
36 | 'join_vars': true,
37 | 'if_return': true,
38 | 'negate_iife': true,
39 | booleans: true,
40 | loops: true,
41 | unused: true
42 | }
43 | }
44 | };
45 |
46 | //----------------------------------------------------------------------------
47 |
48 | gulp.task('requirejs', ['requirejs:rewrite-config'], function( done ) {
49 | $.requirejs.builder( requireBuildConfig, done, $.is.debug, $.log );
50 | });
51 |
52 | //----------------------------------------------------------------------------
53 |
54 | gulp.task('requirejs:rewrite-config', function() {
55 | return gulp.src( $.config.require.config )
56 | .pipe( $.requirejs.rewriteConfig() )
57 | .pipe( gulp.dest( $.config.paths.build ) );
58 | });
59 |
60 | };
61 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/shell.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | //---
4 | // @begin: tools
5 |
6 | gulp.task('shell:tools-build', $.shell.task([
7 | 'gulp --release'
8 | ]));
9 |
10 | // @end: tools
11 | //---
12 | // @begin: git
13 |
14 | // init, checkout
15 |
16 | gulp.task('shell:git:clone', $.shell.task([
17 | 'git clone ' + $.pkg.repository.url + ' ' + $.config.paths.repoDir
18 | ]));
19 |
20 |
21 | gulp.task('shell:git:checkout', $.shell.task([
22 | 'git checkout ' + $.config.git.branch
23 | ], {
24 | cwd: $.config.paths.repoDir
25 | }));
26 |
27 | // add, commit, push
28 |
29 | gulp.task('shell:git:add', $.shell.task([
30 | 'git add . '
31 | ], {
32 | cwd: $.config.paths.repoDir
33 | }));
34 |
35 | gulp.task('shell:git:commit', $.shell.task([
36 | 'git commit -m "' +
37 | $.util.template(
38 | $.config.git.commitMessage,
39 | {
40 | branch: $.config.git.branch,
41 | time: new Date().toISOString(),
42 | file: $.util.noop()
43 | }
44 | ) +
45 | '"'
46 | ], {
47 | cwd: $.config.paths.repoDir,
48 | ignoreErrors: true
49 | }));
50 |
51 | gulp.task('shell:git:push', $.shell.task([
52 | 'git push origin ' + $.config.git.branch
53 | ], {
54 | cwd: $.config.paths.repoDir
55 | }));
56 |
57 | // @end: git
58 |
59 | };
60 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/styles.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('styles', function() {
4 | $.log("Building sass...");
5 | return $.streams.sass();
6 | });
7 |
8 | };
9 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/validate.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | // TODO: review
4 | gulp.task('validate', ['jshint', 'lintspaces']); // , 'karma'
5 |
6 | };
7 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/watch.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('watch', ['webserver:dev'], function() {
4 |
5 | // javascript project
6 | gulp.watch( $.config.js.project.watch, ['wf:js'] );
7 |
8 | //---
9 |
10 | // html project
11 | gulp.watch([
12 | $.config.html.files,
13 | // '!' + $.config.paths.src + '/vendor/**/*'
14 | ], ['wf:html']);
15 |
16 | //---
17 |
18 | // (less) stypes project
19 | gulp.watch([
20 | $.config.styles.sass.project
21 | ], ['wf:styles']);
22 |
23 | });
24 |
25 | //---
26 |
27 | gulp.task('wf:bs:reload', function() {
28 | $.reload();
29 | });
30 |
31 | gulp.task('wf:js', function( done ) {
32 |
33 | $.runSequence(
34 | ['jshint:project', 'lintspaces:js'],
35 | 'wf:bs:reload',
36 | done
37 | );
38 |
39 | });
40 |
41 | gulp.task('wf:html', function( done ) {
42 |
43 | $.runSequence(
44 | 'lintspaces:html',
45 | 'wf:bs:reload',
46 | done
47 | );
48 |
49 | });
50 |
51 | gulp.task('wf:styles', function( done ) {
52 |
53 | $.runSequence(
54 | 'lintspaces:styles',
55 | 'styles',
56 | done
57 | );
58 |
59 | });
60 |
61 | };
62 |
--------------------------------------------------------------------------------
/tools/gulp/tasks/webserver.js:
--------------------------------------------------------------------------------
1 | module.exports = function(gulp, $) {
2 |
3 | gulp.task('webserver:dev', ['styles'], function() {
4 |
5 | var serverConfig = {
6 | port: $.config.webserver.port,
7 | server:{
8 | baseDir: [
9 | $.config.paths.src,
10 | $.config.paths.build
11 | ]
12 | }
13 | };
14 |
15 | if( $.is.proxy ) {
16 | serverConfig.server.middleware = $.config.webserver.middlewares;
17 | }
18 |
19 | $.browserSync.init( serverConfig );
20 |
21 | });
22 |
23 | gulp.task('webserver:preview', function() {
24 |
25 | var serverConfig = {
26 | port: $.config.webserver.port,
27 | root: [
28 | $.config.paths.outputDir
29 | ]
30 | };
31 |
32 | if( $.is.proxy ) {
33 | serverConfig.middleware = function( connect, opts ) {
34 | return $.config.webserver.middlewares;
35 | };
36 | }
37 |
38 | // https://www.npmjs.com/package/gulp-connect
39 | $.connect.server( serverConfig );
40 | $.open('http://' + $.localip + ':' + $.config.webserver.port);
41 |
42 | });
43 |
44 | };
45 |
--------------------------------------------------------------------------------
/tools/lib/localip.js:
--------------------------------------------------------------------------------
1 | // http://txt.fliglio.com/2014/01/concurrent-protractor-testing/
2 | module.exports = (function() {
3 |
4 | var os = require('os');
5 |
6 | function getIpAddress() {
7 | var ipAddress = null;
8 | var ifaces = os.networkInterfaces();
9 |
10 | function processDetails(details) {
11 | if (details.family === 'IPv4' && details.address !== '127.0.0.1' && !ipAddress) {
12 | ipAddress = details.address;
13 | }
14 | }
15 |
16 | for (var dev in ifaces) {
17 | ifaces[dev].forEach(processDetails);
18 | }
19 | return ipAddress;
20 | }
21 |
22 | return getIpAddress();
23 |
24 | })();
25 |
--------------------------------------------------------------------------------
/tools/lib/oscheck.js:
--------------------------------------------------------------------------------
1 |
2 | var os = require('os');
3 |
4 | module.exports = {
5 | name : os.platform(),
6 | isWin : /^win32/.test(os.platform()),
7 | isLinux : /^linux/.test(os.platform()),
8 | isMac : /^darwin/.test(os.platform()) || /^freebsd/.test(os.platform())
9 | };
10 |
--------------------------------------------------------------------------------
/tools/lib/requirejs/builder.js:
--------------------------------------------------------------------------------
1 | var requirejs = require('requirejs');
2 |
3 | function builder( config, done, debug, logger ) {
4 | debug = debug || false;
5 | log = logger || console.log;
6 |
7 | requirejs.optimize( config, buildResponse, buildError );
8 |
9 | function buildResponse( response ) {
10 | if( debug ) {
11 | log( 'requirejs build done' );
12 | log( response );
13 | }
14 | done();
15 | }
16 |
17 | function buildError( error ) {
18 | log( 'requirejs build error' );
19 | log( error );
20 | done();
21 | }
22 | }
23 |
24 | //---
25 |
26 | module.exports = builder;
27 |
--------------------------------------------------------------------------------
/tools/lib/requirejs/index.js:
--------------------------------------------------------------------------------
1 | module.exports = (function() {
2 |
3 | return {
4 | builder: require('./builder'),
5 | rewriteConfig: require('./js-ast-js/gulp-rewrite-require-config')
6 | };
7 |
8 | })();
9 |
--------------------------------------------------------------------------------
/tools/lib/requirejs/js-ast-js/gulp-rewrite-require-config.js:
--------------------------------------------------------------------------------
1 | // through2 is a thin wrapper around node transform streams
2 | var through = require('through2'),
3 | gutil = require('gulp-util'),
4 | transform = require('./rewrite-require-config'),
5 | PluginError = gutil.PluginError;
6 |
7 | // Consts
8 | var PLUGIN_NAME = 'gulp-rewrite-require-config';
9 |
10 |
11 | // Plugin level function(dealing with files)
12 | function gulpRewriteRequireConfig() {
13 |
14 | // Creating a stream through which each file will pass
15 | return through.obj(function(file, enc, cb) {
16 | if (file.isNull()) {
17 | // return empty file
18 | return cb(null, file);
19 | }
20 |
21 | if (file.isStream()) {
22 | return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
23 | }
24 |
25 | if ( file.isBuffer() ) {
26 | file.contents = new Buffer(
27 | transform( String( file.contents ) )
28 | );
29 | }
30 |
31 | return cb(null, file);
32 |
33 | });
34 |
35 | }
36 |
37 | // Exporting the plugin main function
38 | module.exports = gulpRewriteRequireConfig;
39 |
--------------------------------------------------------------------------------
/tools/lib/requirejs/js-ast-js/rewrite-require-config.js:
--------------------------------------------------------------------------------
1 |
2 | //---
3 |
4 | var esprima = require('esprima'),
5 | escodegen = require('escodegen');
6 |
7 | //---
8 |
9 | function checkTargetNode(node) {
10 | var flag = false;
11 |
12 | if(
13 | node.type === 'Property' &&
14 | node.key.type === 'Identifier' &&
15 | (
16 | node.key.name === 'paths' ||
17 | node.key.name === 'deps'
18 | )
19 | ) {
20 | flag = true;
21 | }
22 |
23 | return flag;
24 | }
25 |
26 | function newNodeValue() {
27 | return {
28 | type: 'Literal',
29 | value: 'empty:'
30 | };
31 | }
32 |
33 | //---
34 |
35 | function generateAST(codeStr) {
36 |
37 | return esprima.parse(codeStr);
38 |
39 | }
40 |
41 | function editAST(ast) {
42 |
43 | // get require config object : require( {} )
44 | var configAST = ast.body[0].expression.arguments[0];
45 |
46 | var oldProperties = configAST.properties,
47 | newProperties = [],
48 | paths;
49 |
50 | // get only what is needed
51 | oldProperties.forEach(function(node) {
52 |
53 | if(checkTargetNode(node)) {
54 | newProperties.push(node);
55 | if(node.key.name === 'paths') paths = node;
56 | }
57 |
58 | });
59 |
60 | // define new value
61 | paths.value.properties.forEach(function(node) {
62 | node.value = newNodeValue();
63 | });
64 |
65 | // update
66 | configAST.properties = newProperties;
67 |
68 | //---
69 |
70 | // code style options
71 | var escodegenOptions = {
72 | format: {
73 | indent: {
74 | style: ' '
75 | }
76 | }
77 | };
78 |
79 | // generate new source code
80 | return escodegen.generate(ast, escodegenOptions);
81 |
82 | }
83 |
84 | //---
85 |
86 | module.exports = function(inputSrc) {
87 |
88 | return editAST(
89 | generateAST( inputSrc )
90 | );
91 |
92 | };
93 |
--------------------------------------------------------------------------------
/tools/lib/testModuleThenExecute.js:
--------------------------------------------------------------------------------
1 | function testModuleThenExecute(testModule, installModule, executeLaterFn) {
2 | if(testModule && installModule && !executeLaterFn){
3 | executeLaterFn = installModule;
4 | installModule = testModule;
5 | }
6 | try {
7 | require.resolve(testModule);
8 | executeLaterFn();
9 | } catch(e) {
10 | var async_exec = require('child_process').exec;
11 |
12 | console.error('Module ' + testModule + ' not found. Installing... \n');
13 |
14 | async_exec('npm install ' + installModule, function(err, stdout, stderr) {
15 | executeLaterFn();
16 | });
17 | }
18 | }
19 |
20 | module.exports = testModuleThenExecute;
21 |
--------------------------------------------------------------------------------
/tools/scripts/localip.js:
--------------------------------------------------------------------------------
1 | console.log( require('../lib/localip'), '\n' );
2 |
--------------------------------------------------------------------------------
/tools/scripts/setup.js:
--------------------------------------------------------------------------------
1 | var testModuleThenExecute = require('../lib/testModuleThenExecute');
2 |
3 | testModuleThenExecute('shelljs', function executeLater() {
4 |
5 | require('shelljs/global');
6 |
7 | var oscheck = require('../lib/oscheck');
8 |
9 | var sudoStr = (oscheck.isLinux || oscheck.isMac) ? 'sudo ' : '';
10 | var cmd = '';
11 |
12 | echo('About to setup environment');
13 | echo('It works if it finishes with OK\n');
14 |
15 | echo('----------------------------------------\n');
16 |
17 | if(!which('bower')) {
18 | echo('Bower is missing...taking care of that now.');
19 | cmd = sudoStr + 'npm install --global bower';
20 | echo(cmd); exec(cmd);
21 | }
22 | echo('bower --version ');
23 | echo(exec('bower --version', {silent:true}).output);
24 |
25 | if(!which('gulp')) {
26 | echo('gulp is missing...taking care of that now.');
27 | cmd = sudoStr + 'npm install --global gulp';
28 | echo(cmd); exec(cmd);
29 | }
30 | echo('gulp --version ');
31 | echo(exec('gulp --version', {silent:true}).output);
32 |
33 | echo('----------------------------------------');
34 |
35 | echo('\nOK!');
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/tools/scripts/testos.js:
--------------------------------------------------------------------------------
1 | var testModuleThenExecute = require('../lib/testModuleThenExecute');
2 |
3 | testModuleThenExecute('shelljs', function executeLater() {
4 |
5 | // http://documentup.com/arturadib/shelljs
6 | require('shelljs/global');
7 |
8 | echo('Testing OS environment');
9 |
10 | var os = require('../lib/oscheck');
11 |
12 | /*
13 | What platform you're running on: 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'
14 | win32 (for 32 or 64 bit)
15 | */
16 | echo('OS detected is: '+os.name);
17 | echo ('isWin = '+os.isWin);
18 | echo ('isLinux = '+os.isLinux);
19 | echo ('isMac = '+os.isMac);
20 |
21 | });
22 |
--------------------------------------------------------------------------------