├── .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 | [![Node Dependencies](https://david-dm.org/erkobridee/angularjs-github-info.png)](https://david-dm.org/erkobridee/angularjs-github-info) [![Node devDependencies](https://david-dm.org/erkobridee/angularjs-github-info/dev-status.png)](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 |
2 | 3 | 40 | 41 |
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 | 26 |
27 | 28 | 29 | 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 | 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 |
6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /src/app/github/templates/user-gists.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | 7 | 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 |
2 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 |
16 | 27 |
28 | 29 | 30 | 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 | 88 | 89 | 90 | 91 |
92 | 93 | -------------------------------------------------------------------------------- /src/app/github/templates/user-repos.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | 7 | 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 |
5 |

 

6 |

This application is based on: AngularJS GitHub Contributors (App | GitHub)

7 |
8 |

Application (Code on GitHub | MIT License)

9 | 27 |
28 |
29 | 30 |
31 | 32 | 34 | 35 | 37 | 38 | 40 | 41 |
42 | -------------------------------------------------------------------------------- /src/app/main/templates/search.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

GitHub user:

4 |
5 | 6 |
7 | 10 | 11 | 14 | 15 |
16 | 17 |
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 |
46 |
47 |
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 | --------------------------------------------------------------------------------