├── .editorconfig ├── .gitignore ├── .jscsrc ├── .sass-lint.yml ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── app.critical.scss ├── app.js ├── app.scss ├── assets │ └── README.md ├── components │ └── slider │ │ ├── _slider.scss │ │ ├── slider.fixture.html │ │ ├── slider.html │ │ ├── slider.js │ │ └── slider.test.js ├── controllers │ ├── cv │ │ ├── _cv.scss │ │ ├── cv.html │ │ └── cv.js │ └── rome │ │ ├── _rome.scss │ │ ├── rome.html │ │ ├── rome.js │ │ └── rome.test.js ├── filters │ └── romanize │ │ ├── romanize.js │ │ └── romanize.test.js ├── images │ ├── augustus.jpg │ ├── commodus.jpg │ ├── constantine.jpg │ ├── favicon.ico │ ├── gaius-marius.jpg │ ├── julius-caesar.jpg │ ├── marcus-cicero.jpg │ ├── nero.jpg │ ├── spartacus.jpg │ ├── tiberius-gracchus.jpg │ └── trajan.jpg ├── index.html ├── sass │ ├── _variables.scss │ ├── core │ │ ├── _defaults.scss │ │ ├── _inputs.scss │ │ └── _layout.scss │ └── mixins │ │ └── _breakpoint.scss └── services │ └── romans │ ├── romans.fixture.json │ ├── romans.js │ └── romans.test.js ├── example.aws-conf.js ├── example.aws-keys.js ├── gulp ├── _config.js ├── cdn-s3.js ├── copy.js ├── libs.js ├── revReplace.js ├── sass.js └── scripts.js ├── gulpfile.js ├── karma-conf.js ├── package.json ├── prototype-builder.sublime-project ├── scaffolding ├── _config.js ├── index.js └── templates │ ├── component │ ├── _component.scss │ ├── component.fixture.html │ ├── component.html │ ├── component.js │ └── component.test.js │ ├── constant │ └── constant.js │ ├── controller │ ├── _controller.scss │ ├── controller.html │ ├── controller.js │ └── controller.test.js │ ├── factory │ ├── factory.js │ └── factory.test.js │ ├── filter │ ├── filter.js │ └── filter.test.js │ └── service │ ├── service.fixture.json │ ├── service.js │ └── service.test.js └── server.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | # Due to when using install it auto indents 2 spaces 16 | [*.json] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.scss] 21 | indent_style = space 22 | indent_size = 2 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Log files 2 | ._* 3 | .DS* 4 | .idea/ 5 | *.log 6 | .DS_Store 7 | .aws-keys.js 8 | .aws-conf.js 9 | .awspublish-* 10 | 11 | 12 | # Sublime specific files 13 | *.sublime-workspace 14 | #*.sublime-project 15 | 16 | 17 | # Folders 18 | node_modules/**/* 19 | dist/**/* 20 | app/vendor/**/* 21 | docs/**/* 22 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": ["vendor/**"], 3 | 4 | "requireCommaBeforeLineBreak": null, 5 | "requireDotNotation": null, 6 | "requireLineFeedAtFileEnd": true, 7 | "requireMultipleVarDecl": null, 8 | "requireParenthesesAroundIIFE": true, 9 | "requireSpaceAfterBinaryOperators": true, 10 | "requireSpaceBeforeBlockStatements": true, 11 | "requireSpacesInConditionalExpression": true, 12 | "requireOperatorBeforeLineBreak": true, 13 | "requireCamelCaseOrUpperCaseIdentifiers": false, 14 | 15 | "requireCurlyBraces": [ 16 | "if", 17 | "else", 18 | "for", 19 | "while", 20 | "do", 21 | "try", 22 | "catch" 23 | ], 24 | 25 | "requireSpaceBeforeBinaryOperators": [ 26 | "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", 27 | "&=", "|=", "^=", "+=", 28 | 29 | "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", 30 | "|", "^", "&&", "||", "===", "==", ">=", 31 | "<=", "<", ">", "!=", "!==" 32 | ], 33 | 34 | "requireSpaceAfterKeywords": [ 35 | "if", 36 | "else", 37 | "for", 38 | "while", 39 | "do", 40 | "switch", 41 | "return", 42 | "try", 43 | "catch" 44 | ], 45 | 46 | "validateIndentation": "\t", 47 | "validateQuoteMarks": "'", 48 | 49 | "disallowCommaBeforeLineBreak": null, 50 | "disallowDanglingUnderscores": null, 51 | "disallowEmptyBlocks": null, 52 | "disallowMixedSpacesAndTabs": true, 53 | "disallowMultipleLineBreaks": true, 54 | "disallowMultipleLineStrings": true, 55 | "disallowMultipleVarDecl": null, 56 | "disallowSpaceAfterPrefixUnaryOperators": true, 57 | "disallowSpacesInsideArrayBrackets": "all", 58 | "disallowSpacesInsideObjectBrackets": "all", 59 | "disallowSpacesInsideParentheses": true, 60 | "disallowTrailingComma": null, 61 | "disallowTrailingWhitespace": true, 62 | 63 | "jsDoc": { 64 | "checkAnnotations": { 65 | "preset": "jsdoc3", 66 | "extra": { 67 | "ngdoc": true 68 | } 69 | }, 70 | "checkParamNames": true, 71 | "requireParamTypes": true, 72 | "checkReturnTypes": true, 73 | "checkTypes": true 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /.sass-lint.yml: -------------------------------------------------------------------------------- 1 | options: 2 | formatter: stylish 3 | files: 4 | include: '**/*.scss' 5 | rules: 6 | # Extends 7 | extends-before-mixins: 1 8 | extends-before-declarations: 1 9 | placeholder-in-extend: 0 10 | 11 | # Mixins 12 | mixins-before-declarations: 1 13 | 14 | # Line Spacing 15 | one-declaration-per-line: 1 16 | empty-line-between-blocks: 1 17 | single-line-per-selector: 1 18 | 19 | # Disallows 20 | no-color-keywords: 1 21 | no-color-literals: 1 22 | no-css-comments: 0 23 | no-debug: 1 24 | no-duplicate-properties: 0 25 | no-empty-rulesets: 1 26 | no-extends: 0 27 | no-ids: 1 28 | no-important: 1 29 | no-invalid-hex: 1 30 | no-mergeable-selectors: 1 31 | no-misspelled-properties: 1 32 | no-qualifying-elements: 0 33 | no-trailing-whitespace: 1 34 | no-trailing-zero: 1 35 | no-transition-all: 1 36 | no-url-protocols: 1 37 | no-vendor-prefixes: 1 38 | no-warn: 1 39 | property-units: 0 40 | 41 | # Nesting 42 | force-attribute-nesting: 0 43 | force-element-nesting: 0 44 | force-pseudo-nesting: 0 45 | 46 | # Name Formats 47 | class-name-format: 0 48 | function-name-format: 1 49 | id-name-format: 0 50 | mixin-name-format: 0 51 | placeholder-name-format: 1 52 | variable-name-format: 1 53 | 54 | # Style Guide 55 | bem-depth: 1 56 | border-zero: 1 57 | brace-style: 1 58 | clean-import-paths: 1 59 | empty-args: 1 60 | hex-length: 1 61 | hex-notation: 1 62 | indentation: 1 63 | leading-zero: 1 64 | nesting-depth: 1 65 | property-sort-order: 0 66 | quotes: 1 67 | shorthand-values: 1 68 | url-quotes: 1 69 | variable-for-property: 1 70 | zero-unit: 1 71 | 72 | # Inner Spacing 73 | space-after-comma: 1 74 | space-before-colon: 1 75 | space-after-colon: 1 76 | space-before-brace: 1 77 | space-before-bang: 1 78 | space-after-bang: 1 79 | space-between-parens: 1 80 | space-around-operator: 1 81 | 82 | # Final Items 83 | trailing-semicolon: 1 84 | final-newline: 1 85 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Guide here: 2 | # https://github.com/KyleAMathews/docker-nginx 3 | 4 | # Build docker file 5 | # docker build -t prototype . 6 | 7 | FROM kyma/docker-nginx 8 | 9 | COPY dist /var/www 10 | 11 | CMD 'nginx' 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Simon Dragsbæk Petersen 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Join the chat at https://gitter.im/sp90/prototype-builder](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sp90/prototype-builder?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | 3 | # Prototype-builder v3.2.2 4 | 5 | Just updated to 3.0.0, this is due to breaking changes, done with reformatting the application structure - im now working on rewriting all this in ES6 aswell 6 | 7 | This is a prototype-boilerplate which is a good way to start small html prototypes for show. With build-in seamless workflow 8 | 9 | ## What 10 | 11 | This is build to develop small applications, so its a step between codepen.io, and an full blown app. This is a project you should clone and build and test out stuff. 12 | 13 | ### Getting start 14 | 15 | **Clone, and install** 16 | 17 | ``` 18 | // Development repo 19 | cd /your/dev/folder 20 | 21 | // Clone the project 22 | git clone https://github.com/sp90/prototype-builder.git 23 | 24 | // Go into the project 25 | cd prototype-builder 26 | 27 | // Install project files 28 | npm install 29 | ``` 30 | 31 | **Build, and watch** 32 | 33 | ``` 34 | // Start node server on port 3000 35 | npm start 36 | 37 | // Build files 38 | gulp 39 | 40 | // Watch for changes 41 | gulp watch 42 | ``` 43 | 44 | **Test your code** 45 | 46 | ``` 47 | // Run tests 48 | npm test 49 | 50 | // Run watch on tests 51 | npm run test:watch 52 | ``` 53 | 54 | ### Project CLI 55 | 56 | ``` 57 | // These are used to generate modules 58 | // Remember to add a name to the module 59 | npm run add:controller MODULENAME | npm run add:con MODULENAME 60 | npm run add:component MODULENAME | npm run add:com MODULENAME 61 | npm run add:service MODULENAME | npm run add:ser MODULENAME 62 | npm run add:factory MODULENAME | npm run add:fac MODULENAME 63 | npm run add:constant MODULENAME | npm run add:cons MODULENAME 64 | npm run add:filter MODULENAME | npm run add:fil MODULENAME 65 | ``` 66 | 67 | ### Deployment 68 | 69 | ``` 70 | // These will build based on the enviroment you wanna build to 71 | // Right now prod and staging is the same, you could change it for your project 72 | // You need to set it up for s3 or just build it and serve in your project folder 73 | npm run deploy:dev 74 | npm run deploy:stag 75 | npm run deploy:prod 76 | ``` 77 | 78 | 79 | ### What's included 80 | 81 | * Gulp 82 | * Livereload 83 | * Node to serve dist folder and docs 84 | * Dockerfile to containerize 85 | * Sass 86 | * Linting 87 | * Sourcemaps 88 | * Cssnano 89 | * Uncss 90 | * Cache busting 91 | * JS 92 | * Cache busting 93 | * Linting 94 | * Uglify 95 | * NgAnnotate 96 | * Sourcemaps 97 | * Documentation - ngdocs 98 | * Clean docs folder on build 99 | * Testing 100 | * Karma 101 | * Mocha 102 | * Chai 103 | * Angular 104 | * ui-router 105 | * File revision 106 | * If s3 assets is turned on add s3 bucket url as prefix 107 | * On following types 108 | * html 109 | * js 110 | * json 111 | * css 112 | * jpg 113 | * gif 114 | * ico 115 | * png 116 | * svg 117 | * map 118 | * Url replacement in following types 119 | * html 120 | * css 121 | * js 122 | * Critical css (Manually styleable) 123 | * Support move assets to s3 bucket 124 | * Clean dist on build 125 | * Image minification 126 | * Support for vendor css files 127 | * Dynamicly get libs for karma config 128 | * Enviroment based build processes available: (prod, stag, dev) - default "dev" 129 | * Component based structure 130 | * Project based CLI 131 | * Angular loaded from external CDN 132 | * RevReplace now also supported for json fixtures 133 | 134 | ### Next up Todo's 135 | 136 | * Rewrite starting app to be a simple hello world application with only nesseary content NG1 in ES6 137 | * Default seo support 138 | * Add a change log 139 | * Contribution guide 140 | * Move guides and more to wiki 141 | 142 | Best regards 143 | 144 | **Nomis** 145 | 146 | 147 | Follow me my blog nomis.dk 148 | -------------------------------------------------------------------------------- /app/app.critical.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Critical css 3 | */ 4 | 5 | // Settings 6 | @import 'sass/variables'; 7 | 8 | // Core 9 | @import 'sass/core/layout'; 10 | @import 'sass/core/defaults'; 11 | @import 'sass/core/inputs'; 12 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // No strict because of babel.js 3 | 4 | var modules = [ 5 | // Third party 6 | 'ui.router', 7 | 8 | // Controllers 9 | 'controller.rome', 10 | 'controller.cv' 11 | ]; 12 | 13 | angular 14 | .module('app', modules) 15 | .config(Config); 16 | 17 | // Config app 18 | function Config($locationProvider, $stateProvider, $urlRouterProvider, $sceDelegateProvider) { 19 | $locationProvider.html5Mode(true); 20 | 21 | $stateProvider 22 | .state('rome', { 23 | url: '/', 24 | templateUrl: '/controllers/rome/rome.html', 25 | controller: 'RomeController', 26 | controllerAs: 'rome' 27 | }) 28 | .state('cv', { 29 | url: '/cv', 30 | templateUrl: '/controllers/cv/cv.html', 31 | controller: 'CvController', 32 | controllerAs: 'cv' 33 | }); 34 | 35 | $urlRouterProvider 36 | .otherwise('/'); 37 | 38 | $sceDelegateProvider.resourceUrlWhitelist([ 39 | // Allow same origin resource loads. 40 | 'self', 41 | // Allow loading from our assets domain. Notice the difference between * and **. 42 | 'https://s3.eu-central-1.amazonaws.com/**' 43 | ]); 44 | } 45 | })(); 46 | -------------------------------------------------------------------------------- /app/app.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Main app scss 3 | */ 4 | 5 | // Settings 6 | @import 'sass/variables'; 7 | 8 | // Mixins 9 | @import 'sass/mixins/breakpoint'; 10 | 11 | // Components - controllers 12 | @import 'controllers/cv/cv'; 13 | @import 'controllers/rome/rome'; 14 | 15 | // Components - directives 16 | @import 'components/slider/slider'; 17 | -------------------------------------------------------------------------------- /app/assets/README.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | 3 | Here we locate all the fonts, pdfs and more -------------------------------------------------------------------------------- /app/components/slider/_slider.scss: -------------------------------------------------------------------------------- 1 | slider { 2 | width: 350px; 3 | height: 350px; 4 | display: block; 5 | position: relative; 6 | } 7 | 8 | .slider__item { 9 | width: 100%; 10 | height: 100%; 11 | background-size: cover; 12 | background-position: center center; 13 | position: absolute; 14 | left: 0; 15 | top: 0; 16 | opacity: 0; 17 | z-index: 0; 18 | transition: opacity 300ms ease; 19 | 20 | &.is-active { 21 | opacity: 1; 22 | } 23 | } 24 | 25 | .slider__prev, 26 | .slider__next { 27 | $color: #fff; 28 | $bg: rgba(0, 0, 0, .5); 29 | $bg--alt: rgba(0, 0, 0, .8); 30 | 31 | top: 50%; 32 | left: 0; 33 | z-index: 10; 34 | color: $color; 35 | padding: 5px; 36 | user-select: none; 37 | cursor: pointer; 38 | position: absolute; 39 | transform: translateY(-50%); 40 | background: $bg; 41 | transition: background 300ms ease; 42 | 43 | &:hover { 44 | background: $bg--alt; 45 | } 46 | } 47 | 48 | .slider__next { 49 | right: 0; 50 | left: auto; 51 | } 52 | -------------------------------------------------------------------------------- /app/components/slider/slider.fixture.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/components/slider/slider.html: -------------------------------------------------------------------------------- 1 |
6 |
7 | 8 |
11 | > 12 |
13 |
16 | < 17 |
18 | -------------------------------------------------------------------------------- /app/components/slider/slider.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('directive.slider', []) 6 | .directive('slider', slider); 7 | 8 | function slider() { 9 | return { 10 | restrict: 'E', // only activate on element attribute 11 | templateUrl: '/components/slider/slider.html', 12 | scope: { 13 | content: '=' 14 | }, 15 | link: link 16 | }; 17 | 18 | function link(scope, element, attrs) { 19 | angular.extend(scope, { 20 | sliderState: 0, 21 | next: next, 22 | prev: prev, 23 | goTo: goTo 24 | }); 25 | 26 | function prev() { 27 | if (scope.sliderState < 1) { 28 | angular.extend(scope, { 29 | sliderState: scope.content.length - 1 30 | }); 31 | } else { 32 | angular.extend(scope, { 33 | sliderState: scope.sliderState - 1 34 | }); 35 | } 36 | } 37 | 38 | function next() { 39 | if (scope.sliderState < scope.content.length - 1) { 40 | angular.extend(scope, { 41 | sliderState: scope.sliderState + 1 42 | }); 43 | } else { 44 | angular.extend(scope, { 45 | sliderState: 0 46 | }); 47 | } 48 | } 49 | 50 | function goTo($index) { 51 | if ($index < scope.content.length) { 52 | angular.extend(scope, { 53 | sliderState: $index 54 | }); 55 | } else { 56 | angular.extend(scope, { 57 | sliderState: 0 58 | }); 59 | } 60 | } 61 | } 62 | } 63 | })(); 64 | -------------------------------------------------------------------------------- /app/components/slider/slider.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('Slider component', function() { 5 | var $outerScope, $scope, element; 6 | 7 | beforeEach(module('directive.slider')); 8 | beforeEach(module('/components/slider/slider.html')); 9 | beforeEach(module('/components/slider/slider.fixture.html')); 10 | 11 | beforeEach(inject(function($compile, $rootScope, $templateCache) { 12 | // Get fixture 13 | var fixture = $templateCache.get('/components/slider/slider.fixture.html'); 14 | // Create scope 15 | $outerScope = $rootScope.$new(); 16 | // Compile scope & fixture into the compiled element 17 | element = $compile(angular.element(fixture))($outerScope); 18 | // Init digest, to test before it has been given any data 19 | $outerScope.$digest(); 20 | })); 21 | 22 | it('before content should not be eq to after slidercontent scope has been digested', function() { 23 | // Update outerScope 24 | $outerScope.sliderContent = [ 25 | '/images/commodus.jpg', 26 | '/images/tiberius-gracchus.jpg', 27 | '/images/julius-caesar.jpg', 28 | '/images/augustus.jpg' 29 | ]; 30 | 31 | var before = element.html(); 32 | 33 | $outerScope.$digest(); 34 | 35 | var after = element.html(); 36 | 37 | expect(before).not.to.eq(after); 38 | }); 39 | 40 | it('should have default values', function() { 41 | // Update outerScope 42 | $outerScope.sliderContent = [ 43 | '/images/commodus.jpg', 44 | '/images/tiberius-gracchus.jpg', 45 | '/images/julius-caesar.jpg', 46 | '/images/augustus.jpg' 47 | ]; 48 | 49 | $outerScope.$digest(); 50 | 51 | var $scope = element.isolateScope(); 52 | 53 | expect($scope.sliderState).to.exist; 54 | }); 55 | 56 | it('should trigger next click and validate the sliderstate is correct', function() { 57 | // Update outerScope 58 | $outerScope.sliderContent = [ 59 | '/images/commodus.jpg', 60 | '/images/tiberius-gracchus.jpg', 61 | '/images/julius-caesar.jpg', 62 | '/images/augustus.jpg' 63 | ]; 64 | 65 | $outerScope.$digest(); 66 | 67 | var $scope = element.isolateScope(); 68 | 69 | expect($scope.sliderState).to.be.eq(0); 70 | 71 | $scope.next(); 72 | 73 | expect($scope.sliderState).to.be.eq(1); 74 | 75 | $scope.next(); 76 | 77 | expect($scope.sliderState).to.be.eq(2); 78 | 79 | $scope.next(); 80 | 81 | expect($scope.sliderState).to.be.eq(3); 82 | 83 | $scope.next(); 84 | 85 | expect($scope.sliderState).to.be.eq(0); 86 | }); 87 | 88 | it('should trigger prev click and validate the sliderstate is correct', function() { 89 | // Update outerScope 90 | $outerScope.sliderContent = [ 91 | '/images/commodus.jpg', 92 | '/images/tiberius-gracchus.jpg', 93 | '/images/julius-caesar.jpg', 94 | '/images/augustus.jpg' 95 | ]; 96 | 97 | $outerScope.$digest(); 98 | 99 | var $scope = element.isolateScope(); 100 | 101 | expect($scope.sliderState).to.be.eq(0); 102 | 103 | $scope.prev(); 104 | 105 | expect($scope.sliderState).to.be.eq(3); 106 | 107 | $scope.prev(); 108 | 109 | expect($scope.sliderState).to.be.eq(2); 110 | 111 | $scope.prev(); 112 | 113 | expect($scope.sliderState).to.be.eq(1); 114 | 115 | $scope.prev(); 116 | 117 | expect($scope.sliderState).to.be.eq(0); 118 | }); 119 | 120 | it('should trigger goTo click and validate the sliderstate is correct', function() { 121 | // Update outerScope 122 | $outerScope.sliderContent = [ 123 | '/images/commodus.jpg', 124 | '/images/tiberius-gracchus.jpg', 125 | '/images/julius-caesar.jpg', 126 | '/images/augustus.jpg' 127 | ]; 128 | 129 | $outerScope.$digest(); 130 | 131 | var $scope = element.isolateScope(); 132 | 133 | expect($scope.sliderState).to.be.eq(0); 134 | 135 | $scope.goTo(2); 136 | 137 | expect($scope.sliderState).to.be.eq(2); 138 | 139 | // Not in the range so should reset to first slide 140 | $scope.goTo(5); 141 | 142 | expect($scope.sliderState).to.be.eq(0); 143 | }); 144 | }); 145 | })(); 146 | -------------------------------------------------------------------------------- /app/controllers/cv/_cv.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Cv styles 3 | */ 4 | 5 | // .cv { 6 | 7 | // } 8 | -------------------------------------------------------------------------------- /app/controllers/cv/cv.html: -------------------------------------------------------------------------------- 1 |

{{cv.title}}

2 | 3 | 4 | -------------------------------------------------------------------------------- /app/controllers/cv/cv.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // No strict because of babel.js 3 | 4 | var modules = [ 5 | 'directive.slider' 6 | ]; 7 | 8 | angular 9 | .module('controller.cv', modules) 10 | .controller('CvController', CvController); 11 | 12 | function CvController($scope) { 13 | var rome = this; 14 | 15 | angular.extend(rome, { 16 | title: 'Noget med CV' 17 | }); 18 | } 19 | })(); 20 | -------------------------------------------------------------------------------- /app/controllers/rome/_rome.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Rome styles 3 | */ 4 | 5 | // .rome { 6 | 7 | // } 8 | -------------------------------------------------------------------------------- /app/controllers/rome/rome.html: -------------------------------------------------------------------------------- 1 |
2 |

{{rome.title}}

3 | 4 |
5 | 6 |
7 | 11 | 12 |
13 |
16 |
17 |

{{roman.name}}

18 |

19 | Lived from 20 | {{ roman.birth | romanize }} 21 | {{ roman.birth }} 22 | to 23 | {{ roman.death | romanize }} 24 | {{ roman.death }} 25 |

26 |
27 | {{roman.bio}} 28 |
29 |
30 | 31 |
32 |

No romans to be found with that name, try again!

33 |
34 | 35 | 36 |
37 | -------------------------------------------------------------------------------- /app/controllers/rome/rome.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // No strict because of babel.js 3 | 4 | var modules = [ 5 | 'filter.romanize', 6 | 'service.romans', 7 | 'directive.slider' 8 | ]; 9 | 10 | angular 11 | .module('controller.rome', modules) 12 | .controller('RomeController', RomeController); 13 | 14 | function RomeController($scope, $filter, Romans) { 15 | var rome = this; 16 | 17 | angular.extend(rome, { 18 | title: '10 most famous people from acient rome', 19 | romans: [], 20 | sliderContent: [ 21 | '/images/commodus.jpg', 22 | '/images/tiberius-gracchus.jpg', 23 | '/images/julius-caesar.jpg', 24 | '/images/augustus.jpg' 25 | ] 26 | }); 27 | 28 | Romans.get() 29 | .then(function(romans) { 30 | angular.extend(rome, { 31 | romans: romans 32 | }) 33 | }); 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /app/controllers/rome/rome.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // Some test here 5 | describe('RomeController function', function() { 6 | var $scope; 7 | 8 | beforeEach(module('controller.rome')); 9 | beforeEach(module('/controllers/rome/rome.html')); 10 | 11 | beforeEach(inject(function($rootScope, $controller, $httpBackend) { 12 | $scope = $rootScope.$new(); 13 | 14 | $controller('RomeController', { 15 | $scope: $scope 16 | }); 17 | 18 | // Get fixture 19 | var fixture = window.__fixtures__['/services/romans/romans.fixture']; 20 | $httpBackend.whenGET('/services/romans/romans.fixture.json').respond(fixture); 21 | $httpBackend.flush(); 22 | })); 23 | 24 | it('should create something', function() { 25 | // Expect something 26 | $scope.$digest(); 27 | }); 28 | }); 29 | })(); 30 | -------------------------------------------------------------------------------- /app/filters/romanize/romanize.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('filter.romanize', []) 6 | .filter('romanize', romanize) 7 | .filter('deromanize', deromanize); 8 | 9 | var pairs = [ 10 | [1000, 'M'], [900, 'CM'], [800, 'DCCC'], [700, 'DCC'], [600, 'DC'], 11 | [500, 'D'], [400, 'CD'], [300, 'CCC'], [200, 'CC'], 12 | [100, 'C'], [90, 'XC'], [80, 'LXXX'], [70, 'LXX'], [60, 'LX'], 13 | [50, 'L'], [40, 'XL'], [30, 'XXX'], [20, 'XX'], 14 | [10, 'X'], [9, 'IX'], [8, 'VIII'], [7, 'VII'], [6, 'VI'], 15 | [5, 'V'], [4, 'IV'], [3, 'III'], [2, 'II'], [1, 'I'], 16 | ]; 17 | 18 | var reversePairs = { 19 | I: 1, 20 | V: 5, 21 | X: 10, 22 | L: 50, 23 | C: 100, 24 | D: 500, 25 | M: 1000 26 | }; 27 | 28 | function romanize() { 29 | return function(number) { 30 | // Verify type 31 | if (typeof number !== 'number') { return false; } 32 | 33 | // Prep zero value 34 | var roman = ''; 35 | 36 | // Create map and loop over it 37 | new Map(pairs).forEach(function(mapRoman, mapNumber) { 38 | // While our original number is still 39 | // higher or equal to the map number keep going 40 | while (number >= mapNumber) { 41 | // Add our roman number to our final value 42 | roman += mapRoman; 43 | // Subtract mapNumber from our input value 44 | number -= mapNumber; 45 | } 46 | }); 47 | 48 | // Output roman number 49 | return roman; 50 | }; 51 | } 52 | 53 | function deromanize() { 54 | return function(roman) { 55 | // Verify type 56 | if (typeof roman !== 'string') { return false; } 57 | 58 | // Send to uppercase and make into an array 59 | roman = roman.toUpperCase().split(''); 60 | 61 | // Prep zero values 62 | var number = 0; 63 | var value = 0; 64 | 65 | // As long as we still have elements in the roman array keep going 66 | while (roman.length) { 67 | // Find roman if add the value and remove it from the array we made 68 | value = reversePairs[roman.shift()]; 69 | // Define if it's a plus or a minus 70 | number += value * (value < reversePairs[roman[0]] ? -1 : 1); 71 | } 72 | 73 | // Output number as interger 74 | return number; 75 | }; 76 | } 77 | })(); 78 | -------------------------------------------------------------------------------- /app/filters/romanize/romanize.test.js: -------------------------------------------------------------------------------- 1 | // jscs:disable validateQuoteMarks 2 | // This is disabled in order to replicate JSON objects 3 | 4 | describe('Roman filter', function() { 5 | var $filter; 6 | 7 | beforeEach(module('filter.romanize')); 8 | beforeEach(inject(function(_$filter_) { 9 | $filter = _$filter_; 10 | })); 11 | 12 | /** 13 | * Romanize 14 | */ 15 | describe('Romanize', function() { 16 | it('should filter 1 into I', function() { 17 | var result = $filter('romanize')(1); 18 | 19 | expect(result).to.equal('I'); 20 | }); 21 | 22 | it('should filter 4 into IV', function() { 23 | var result = $filter('romanize')(4); 24 | 25 | expect(result).to.equal('IV'); 26 | }); 27 | 28 | it('should filter 6 into IV', function() { 29 | var result = $filter('romanize')(6); 30 | 31 | expect(result).to.equal('VI'); 32 | }); 33 | 34 | it('should filter 90 into IV', function() { 35 | var result = $filter('romanize')(90); 36 | 37 | expect(result).to.equal('XC'); 38 | }); 39 | 40 | it('should filter 1999 into IV', function() { 41 | var result = $filter('romanize')(1999); 42 | 43 | expect(result).to.equal('MCMXCIX'); 44 | }); 45 | 46 | it('should filter 2444 into IV', function() { 47 | var result = $filter('romanize')(2444); 48 | 49 | expect(result).to.equal('MMCDXLIV'); 50 | }); 51 | }); 52 | 53 | /** 54 | * Deromanize 55 | */ 56 | describe('Deromanize', function() { 57 | it('should filter I into 1', function() { 58 | var result = $filter('deromanize')('I'); 59 | 60 | expect(result).to.equal(1); 61 | }); 62 | 63 | it('should filter IV into 4', function() { 64 | var result = $filter('deromanize')('IV'); 65 | 66 | expect(result).to.equal(4); 67 | }); 68 | 69 | it('should filter VI into 6', function() { 70 | var result = $filter('deromanize')('VI'); 71 | 72 | expect(result).to.equal(6); 73 | }); 74 | 75 | it('should filter 90 into IV', function() { 76 | var result = $filter('deromanize')('XC'); 77 | 78 | expect(result).to.equal(90); 79 | }); 80 | 81 | it('should filter 1999 into IV', function() { 82 | var result = $filter('deromanize')('MCMXCIX'); 83 | 84 | expect(result).to.equal(1999); 85 | }); 86 | 87 | it('should filter 2444 into IV', function() { 88 | var result = $filter('deromanize')('MMCDXLIV'); 89 | 90 | expect(result).to.equal(2444); 91 | }); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /app/images/augustus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/augustus.jpg -------------------------------------------------------------------------------- /app/images/commodus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/commodus.jpg -------------------------------------------------------------------------------- /app/images/constantine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/constantine.jpg -------------------------------------------------------------------------------- /app/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/favicon.ico -------------------------------------------------------------------------------- /app/images/gaius-marius.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/gaius-marius.jpg -------------------------------------------------------------------------------- /app/images/julius-caesar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/julius-caesar.jpg -------------------------------------------------------------------------------- /app/images/marcus-cicero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/marcus-cicero.jpg -------------------------------------------------------------------------------- /app/images/nero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/nero.jpg -------------------------------------------------------------------------------- /app/images/spartacus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/spartacus.jpg -------------------------------------------------------------------------------- /app/images/tiberius-gracchus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/tiberius-gracchus.jpg -------------------------------------------------------------------------------- /app/images/trajan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sp90/prototype-builder/1417f1de7e0027d3935261e47d7d9e19b67fef69/app/images/trajan.jpg -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Roman info 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Fonts 3 | */ 4 | 5 | $font--size-base: 18px; 6 | $font--line-base: 26px; 7 | 8 | $font-family--header: 'Open Sans', sans-serif; 9 | $font-family--base: 'Lora', sans; 10 | 11 | 12 | /** 13 | * Colors 14 | */ 15 | 16 | $color--primary: #bd0716; 17 | $color--header-bg: #2b2b2b; 18 | 19 | 20 | /** 21 | * Spacing 22 | */ 23 | 24 | $spacing--base: 12px; 25 | 26 | 27 | /** 28 | * Breakpoints 29 | */ 30 | 31 | $bp-giga: 2500px; 32 | $bp-mega: 1900px; 33 | $bp-kilo: 1360px; 34 | $bp-centi: 1024px; 35 | $bp-milli: 768px; 36 | $bp-nano: 480px; 37 | -------------------------------------------------------------------------------- /app/sass/core/_defaults.scss: -------------------------------------------------------------------------------- 1 | h1, 2 | .h1, 3 | h2, 4 | .h2, 5 | h3, 6 | .h3, 7 | h4, 8 | .h4 { 9 | font-family: $font-family--header; 10 | margin: $spacing--base 0 ($spacing--base / 2); 11 | line-height: 1.2em; 12 | } 13 | 14 | h1, 15 | .h1 { 16 | font-weight: 200; 17 | font-size: 32px; 18 | @media (max-width: 768px) { 19 | font-size: 24px; 20 | } 21 | } 22 | 23 | h2, 24 | .h2 { 25 | font-weight: 600; 26 | font-size: 28px; 27 | @media (max-width: 768px) { 28 | font-size: 20px; 29 | } 30 | } 31 | 32 | h3, 33 | .h3 { 34 | font-weight: 600; 35 | } 36 | 37 | h4, 38 | .h4 { 39 | font-weight: 600; 40 | } 41 | 42 | p { 43 | margin: 0 0 ($spacing--base * 2); 44 | @media (max-width: 768px) { 45 | margin: 0 0 $spacing--base; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/sass/core/_inputs.scss: -------------------------------------------------------------------------------- 1 | input { 2 | border: 0; 3 | font-family: $font-family--base; 4 | font-size: $font--size-base; 5 | margin: 0 0 $spacing--base; 6 | padding: 20px 0; 7 | width: 100%; 8 | 9 | &:focus { 10 | outline: none; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/sass/core/_layout.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | $bg: #fff; 7 | 8 | background: $bg; 9 | font-family: $font-family--base; 10 | font-size: $font--size-base; 11 | line-height: $font--line-base; 12 | margin: 0; 13 | 14 | @media (max-width: 768px) { 15 | font-size: 14px; 16 | line-height: 20px; 17 | } 18 | } 19 | 20 | header { 21 | $color: #fff; 22 | 23 | background: $color--header-bg; 24 | color: $color; 25 | padding: 20px; 26 | 27 | h1 { 28 | margin: 0; 29 | text-transform: uppercase; 30 | } 31 | } 32 | 33 | section { 34 | max-width: 980px; 35 | margin: $spacing--base auto; 36 | padding: 0 20px; 37 | } 38 | 39 | article { 40 | margin-bottom: ($spacing--base * 2); 41 | 42 | h2 { 43 | color: $color--primary; 44 | text-transform: capitalize; 45 | } 46 | 47 | .profile-image { 48 | background-position: center center; 49 | background-size: cover; 50 | float: left; 51 | height: 100%; 52 | margin: 0 20px 20px 0; 53 | max-height: 350px; 54 | max-width: 350px; 55 | width: 100%; 56 | 57 | @media (max-width: 768px) { 58 | float: none; 59 | } 60 | } 61 | } 62 | 63 | .article__fallback h3 { 64 | $color: #aaa; 65 | 66 | text-align: center; 67 | color: $color; 68 | font-weight: 400; 69 | } 70 | -------------------------------------------------------------------------------- /app/sass/mixins/_breakpoint.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * $bp-mega: 2500px; 3 | * $bp-mega: 1900px; 4 | * $bp-kilo: 1360px; 5 | * $bp-centi: 1024px; 6 | * $bp-milli: 768px; 7 | * $bp-nano: 480px; 8 | */ 9 | 10 | $breakpoint-map: ( 11 | giga: ( 12 | $bp-giga 13 | ), 14 | mega: ( 15 | $bp-mega 16 | ), 17 | kilo: ( 18 | $bp-kilo 19 | ), 20 | centi: ( 21 | $bp-centi 22 | ), 23 | milli: ( 24 | $bp-milli 25 | ), 26 | nano: ( 27 | $bp-nano 28 | ) 29 | ); 30 | 31 | @mixin breakpoint($point) { 32 | @if length($point) > 1 { 33 | @if type-of(nth($point, 1)) == 'number' and type-of(nth($point, 2)) == 'number' { 34 | @media only screen and (min-width: nth($point, 1)) and (max-width: nth($point, 2)) { 35 | @content; 36 | } 37 | } @else if type-of(nth($point, 1)) == 'number' { 38 | @media only screen and (min-width: nth($point, 1)) and (max-width: map-get($breakpoint-map, nth($point, 2))) { 39 | @content; 40 | } 41 | } @else if type-of(nth($point, 2)) == 'number' { 42 | @media only screen and (min-width: map-get($breakpoint-map, nth($point, 1))) and (max-width: nth($point, 2)) { 43 | @content; 44 | } 45 | } @else { 46 | @media only screen and (min-width: map-get($breakpoint-map, nth($point, 1))) and (max-width: map-get($breakpoint-map, nth($point, 2))) { 47 | @content; 48 | } 49 | } 50 | } @else { 51 | @if $point == giga { 52 | @media only screen and (min-width: $bp-giga) { @content; } 53 | } @else if $point == mega { 54 | @media only screen and (min-width: $bp-mega) { @content; } 55 | } @else if $point == kilo { 56 | @media only screen and (min-width: $bp-kilo) { @content; } 57 | } @else if $point == centi { 58 | @media only screen and (min-width: $bp-centi) { @content; } 59 | } @else if $point == milli { 60 | @media only screen and (min-width: $bp-milli) { @content; } 61 | } @else if $point == nano { 62 | @media only screen and (min-width: $bp-nano) { @content; } 63 | } @else if $point == print { 64 | @media print { @content; } 65 | } @else if type-of($point) == 'number' { 66 | @media only screen and (min-width: $point) { @content; } 67 | } @else if str-index($point, max) == 1 or str-index($point, min) == 1 { 68 | @media only screen and (#{$point}) { @content; } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/services/romans/romans.fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "name": "nero", 5 | "time": "AD", 6 | "birth": 37, 7 | "death": 68, 8 | "img": "/images/nero.jpg", 9 | "bio": "

He was Often known as the “Madman of Rome”. Nero was hands down the most notorious Roman of all times. This made the daily living of the-then Roman a grim affair, for he also happened to be their emperor – his reign lasting from 54 AD to 68 AD. So what is an infamous near dictator doing in this list? Well, when you make a of famous people, you put in the good, the bad and the ugly too! Nero was all bad and ugly part.

During his rule, two-third of entire Rome was burnt down, which led to massive loss of lives and properties. And even though he was helpless to stop the blitz, he did not even try to quell out fire. Instead he saw Rome burnt down into flames from his palace, singing through the entire catastrophe. Things get even uglier when evidence and motive point toward Nero being the one who started the fire because the Roman senate had refused to give him land to build a new palace. And what was the first thing he did once the blitz cleared out – built himself a brand new palace in the newly vacant space created by the fire.

" 10 | }, 11 | { 12 | "name": "commodus", 13 | "time": "AD", 14 | "birth": 161, 15 | "death": 192, 16 | "img": "/images/commodus.jpg", 17 | "bio": "

Most of us have seen this wanna-be gladiator but infact an emperor persona in, some of you might have guessed, the famous movie “Gladiator”. Emperor Lucius Aurelius Commodus was played by the gifted actor Joaquin Phoenix. Breaking the trend of accession to the throne based on merit, Commodus took the throne as a right by birth. His father, Marcus Aurelius was considered as one of the greatest Romans to have ascended the throne, and that Commodus could not live up to the absolutely draining standards set by Marcus would have been fairly understandable. But not only did he failed flat on his face, he turned out to be so terrible at kingship that his mere existence was a scream of revolt to what his father had toiled to build in his entire reign.

A cruel, power-hungry egomaniac, he saw himself as the one and only numero uno in the world. He saw himself as Hercules, and fancied himself as a gladiator – thus often neglecting all his political duties, and entering into battle arenas against rather weak and poor opponents. Needless to say, this guy as hated by most of the Romans, and his continues stints as a gladiator, who really sucked at fighting, eventually saw him assassinated by his own inner circle.

" 18 | }, 19 | { 20 | "name": "trajan", 21 | "time": "AD", 22 | "birth": 53, 23 | "death": 117, 24 | "img": "/images/trajan.jpg", 25 | "bio": "

Spanish by birth, Marcus Ulpius Trajan was the first Roman Emperor of a non-Italian origin. And he sure did went on to become one of the most outstanding emperors of ancient Rome. He delivered a rule that saw Rome reach to new heights of new developments, and new realms of boundaries. Unlike his many predecessors, he treated the Roman senate with respect, and always made sure the most competent and honest candidates were designated the rulers of different provinces.

Trajan had served as a soldier under his father in his hay days. But for an emperor with a military background, he was more known for his wisdom and dignity. His first priority always being the welfare of common people. He provided poor people with free grains, let many popular public changes, built new roads and harbours and even set-up funds for poor people and children. Needless to say, the reign of emperor Trajan was a glittering one.

" 26 | }, 27 | { 28 | "name": "tiberius gracchus", 29 | "time": "BC", 30 | "birth": 168, 31 | "death": 133, 32 | "img": "/images/tiberius-gracchus.jpg", 33 | "bio": "

Even though the origination of Tiberius Gracchus were from one of Rome’s elite families, he was known for his struggle for the poor people of Rome. The commendable effort he put in to bring some relief to the lives of have-nots along with his brother Gaius Gracchus. As a distinguished officer in the third Punic war, It was his negotiation skills that saved the lives of more than 3,000 Roman soldiers when they were stuck in dire straits in Numantia. Even though this move was particularly resented in the Roman senate – that the Roman army gave up without taking it to a fight, he had seen the latent weakness of Roman power.

But he is known more for his ideologies and practices that always hinted towards equality among the upper class elites and the lower class peasants. With the plight of peasant workers worsening with each passing day, the rise of slave labor had further degraded common peasants. And for obvious reasons, his ideas were not entertained by the senate and the elite Roman who owned much of land in Rome. Eventually, he was assassinated in a riot sparked his senatorial opponents.

" 34 | }, 35 | { 36 | "name": "constantine", 37 | "time": "AD", 38 | "birth": 272, 39 | "death": 337, 40 | "img": "/images/constantine.jpg", 41 | "bio": "

Constantine I was also known as Constantine the great, and he happens to be one of those emperors who did true justice to their names. The vast Roman empire had been divided between many rulers by the 3rd century AD. Constantine defeated all the would-be emperors, and unified all those divisions into the Roman kingdom. He then decided to relocate the capital from Rome to the-then known Byzantium. Not entirely satisfied, he went on to rename the new capital to a more familiar sounding Constantinopolis.

But moreover, Constantine is known in the history as the first Christian Roman Emperor. He not only initiated the evolution of the Roman Empire into a Christian state, but also opined the pathway for a culture with distinct cultural influences from Christianity, which eventually had a huge impact in the western medieval culture.

" 42 | }, 43 | { 44 | "name": "gaius marius", 45 | "time": "BC", 46 | "birth": 157, 47 | "death": 86, 48 | "img": "/images/gaius-marius.jpg", 49 | "bio": "

This legendary Roman general and statesman single handedly evolved the Roman army into one of the most effective and well-organized fighting body that made thumping statements in countless battles. A cunning tactician, Gaius Marius also held the office of Consul for an unprecedented seven times in a row. But he is more known for the transformations he brought about into the Roman military legions – the most dramatic and influential reforms that forever changed the rules of engagement in war.

At a time when attacks and invasions from Barbarian and German tribes was the biggest threat to the entire Roman republic, he saw the dire need to increase the recruitment power which lagged behind significantly because of the strict standards that had been set to for one to become a soldier. But once Marius took over, men from provinces could sign up for the army and in time become a Roman citizen. Then he went on to win many decisive battles with his new army, the famous ones being battle of Aquae Sextiae and Campi Raudii, where his victories saved the republic from a seemingly inevitable barbarian invasion.

" 50 | }, 51 | { 52 | "name": "marcus cicero", 53 | "time": "BC", 54 | "birth": 107, 55 | "death": 43, 56 | "img": "/images/marcus-cicero.jpg", 57 | "bio": "

“Gratitude is not only greatest of the virtues, but parent of all others.” This timeless quote, and many others that tell us about the essence of living our lives, and that we may have heard time and again – all of them came from the famous Roman philosopher Marcus Tullius Cicero. Widely considered as one of the greatest orators and prose stylist to have lived in the ancient Rome, he was also a philosopher, a respected politician, lawyer, political theorist, consul and constitutionalist, and what not!

As a writer, his influence in the latin language was so immense that the subsequent history of prose that were written then onward up to the late 19th century were either in reference to or a reaction against his style. A contemporary of Julius Caesar, Cicero also wrote a number of books of which six on rhetoric survive along with parts of eight other on philosophy.

" 58 | }, 59 | { 60 | "name": "julius caesar", 61 | "time": "BC", 62 | "birth": 100, 63 | "death": 44, 64 | "img": "/images/julius-caesar.jpg", 65 | "bio": "

He is arguably the most popular of the ancient Romans. Even though most of the people may not have slightest of ideas when it comes to the ancient Rome, chances are that they would still have heard about the prodigious Roman Emperor (and a self annotated dictator) Julius Caesar. The conflict in Gaul was proving to be the biggest thorn on the path of Roman glory, and that is when he pulled of a brilliant campaign to conquer Gaul, his strategies still being studied for training generals in this present age. His success added in one of the most important new territories into the Roman empire. He also led expeditions to Germany and Britain, both of them foreign territories to Rome at that time.

But with his ruthless success, he also gave rise to a number of political enemies, who kept on plotting against him time and again. His opposition took even uglier, albeit at-that-time-silent turn, when he famously crossed the Rubicon river and took power of Rome in his hands as a dictator. This eventually led to his assassination conspired by many Roman senators who repeatedly stabbed him to death.

" 66 | }, 67 | { 68 | "name": "spartacus", 69 | "time": "BC", 70 | "birth": 111, 71 | "death": 71, 72 | "img": "/images/spartacus.jpg", 73 | "bio": "

Without a doubt, the most famous gladiator in the entire Roman history, a Thracian by birth, Spartacus was a soldier caught in war and then sold in slavery to fight in the-then famous gladiator battles. But as history has proved time and again, even though you may take away a soldier’s freedom, a warrior’s fierce will for independence can never be easily given up. Before he was enslaved to fight in the Roman arenas, not much was known about him and it did not help much that the Romans never bothered to document the early lives of gladiators.

It was estimated that the number of slaves in Rome at its peak was around one and half million. However, despite after repeater slave uprisings, the roman legions did not pay particular concern since the senate and citizens took it as a mere whiff. They were counting too much on their stars. First Spartacus convinced some 70 fellow gladiators to revolt and escaped to the slopes of mount vesuvius. In a period of about two years, he freed a number of slaves and trained them to eventually make an army of 1,999 strong individuals by 71 BC. Now this had immediate attention from Roman senate, which sent a number of legions which eventually captured the slave force and killed Spartacus, but not before he made his mark in the Roman history.

" 74 | }, 75 | { 76 | "name": "augustus", 77 | "time": "BC-AD", 78 | "birth": 63, 79 | "death": 14, 80 | "img": "/images/augustus.jpg", 81 | "bio": "

Born as Gaius Octavius, he is known as the founder of Roman Empire, a walk away from the old Roman Republic and its first emperor. His rule reigning from 27 BC until his death in 14 AD. Such were his deeds that the senate changed his name to “Augustus” in the honor of his great achievements. Once the conspiracy behind the assassination of Julius Caesar came into light, Augustus went on to avenge his death along with Caesar’s closest ally Mark Antony. He later had a fallout with Antony amid differences, and showing the grit of his character, he went on to defeat the duo of Antony and Egyptian queen Cleopatra – thus securing his path to glory.

Despite repeated oppositions, he stood strong.Augustus’ reign laid the foundations of a regime that lasted for nearly fifteen hundred years through the ultimate decline of the Western Roman Empire. Together with the Roman senate, he scripted the new constitution for the great Roman empire in which he ruled wisely, building roads, aqueducts and famous buildings. He remains to this date the most famous and wise Roman emperor among them all.

Final Conclusion

The ancient Rome had a very rich history which saw the rise and fall of many famous people who are talked about to this day. From the craziest of the Emperors, to the bravest of the gladiators, to the biggest names in ancient philosophy – ancient Rome did give us a fair share of names that have always been worth mentioning. In fact, to put it rather blatantly, this list may not do an impeccable justice to the topic for there were many other famous Romans who could have easily made it into the list. But since we had to put in only ten of them, the aforementioned Romans indeed had been the outstanding figures that the Roman history created. And these people in turn created the Roman history.

" 82 | } 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /app/services/romans/romans.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('service.romans', []) 6 | .service('Romans', function($http, $q) { 7 | return { 8 | get: get 9 | }; 10 | 11 | function get() { 12 | return $q(function(resolve, reject) { 13 | $http({ 14 | method: 'GET', 15 | url: '/services/romans/romans.fixture.json', 16 | cache: true 17 | }) 18 | .success(function(res) { 19 | resolve(res.data); 20 | }) 21 | .error(function(err) { 22 | reject(err); 23 | }); 24 | }); 25 | } 26 | }); 27 | })(); 28 | -------------------------------------------------------------------------------- /app/services/romans/romans.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('Romans service', function () { 5 | var Romans, $httpBackend; 6 | 7 | beforeEach(module('service.romans')); 8 | beforeEach(inject(function (_Romans_, _$httpBackend_) { 9 | Romans = _Romans_; 10 | $httpBackend = _$httpBackend_; 11 | })); 12 | 13 | it('should do something', function () { 14 | // Get fixture 15 | var fixture = window.__fixtures__['/services/romans/romans.fixture']; 16 | $httpBackend.whenGET('/services/romans/romans.fixture.json').respond(fixture); 17 | 18 | Romans.get() 19 | .then(function(result) { 20 | expect(fixture.data).to.deep.equal(result); 21 | }); 22 | 23 | $httpBackend.flush(); 24 | }); 25 | }); 26 | })(); 27 | -------------------------------------------------------------------------------- /example.aws-conf.js: -------------------------------------------------------------------------------- 1 | // Just rename this file to .aws-conf.js 2 | // Typical url structure: 3 | // https://s3.REGION.amazonaws.com/BUCKET_NAME 4 | 5 | // REMEMBER NO ENDING SLASH 6 | module.exports = { 7 | 'url': 'SOME_URL' 8 | }; 9 | -------------------------------------------------------------------------------- /example.aws-keys.js: -------------------------------------------------------------------------------- 1 | // Just rename this file to .aws-keys.js 2 | // To enable it on deploy 3 | // Generate keys? 4 | // http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html 5 | module.exports = { 6 | 'accessKeyId': 'SOME_KEY', 7 | 'secretAccessKey': 'SOME_SECRET', 8 | 'region': 'YOUR_REGION', 9 | 'params': { 10 | 'Bucket': 'BUCKET_NAME' 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /gulp/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | output: 'dist/*', 3 | cssLibs: [], 4 | sass: [ 5 | 'app/**/*.scss' 6 | ], 7 | html: [ 8 | 'app/index.html', 9 | 'app/**/*.html' 10 | ], 11 | images: [ 12 | 'app/images/**/*.{jpg,gif,png,svg,ico}' 13 | ], 14 | assets: [ 15 | 'app/assets/**/*' 16 | ], 17 | fixtures: [ 18 | 'app/**/*.json' 19 | ], 20 | scripts: [ 21 | 'app/app.js', 22 | 'app/services/**/*.js', 23 | 'app/filters/**/*.js', 24 | 'app/components/**/*.js', 25 | 'app/factories/**/*.js', 26 | 'app/constants/**/*.js', 27 | 'app/controllers/**/*.js' 28 | ], 29 | scriptsSkip: [ 30 | '!app/**/*.test.js', 31 | '!app/**/*.mock.js' 32 | ], 33 | libs: [ 34 | 'node_modules/fg-loadcss/src/loadCSS.js', 35 | 'node_modules/fg-loadcss/src/cssrelpreload.js', 36 | 'node_modules/angular-ui-router/release/angular-ui-router.min.js' 37 | ], 38 | docLibs: [ 39 | 'node_modules/angular-animate/angular-animate.js', 40 | 'node_modules/marked/lib/marked.js' 41 | ], 42 | testLibs: [ 43 | 'node_modules/angular/angular.min.js', 44 | 'node_modules/angular-mocks/angular-mocks.js', 45 | 'node_modules/babel-polyfill/dist/polyfill.min.js' 46 | ] 47 | }; 48 | -------------------------------------------------------------------------------- /gulp/cdn-s3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This one was abit tricky until i found this guide on how to use AWS 3 | * https://medium.com/@WoloxEngineering/deploy-your-angularjs-app-to-aws-s3-with-ssl-3635a62533ab#.gpunuvxbj 4 | * 5 | * AWS Docs are terrible btw!!! 6 | */ 7 | 8 | // Import native modules 9 | var fs = require('fs'); 10 | var path = require('path'); 11 | 12 | // Import modules 13 | var awspublish = require('gulp-awspublish'); 14 | 15 | // Import config 16 | var config = require('./_config'); 17 | 18 | // Copy to S3 19 | module.exports = function(gulp, useS3) { 20 | var awsKeys = false; 21 | var headers = { 22 | 'Cache-Control': 'max-age=315360000, no-transform, public' 23 | }; 24 | 25 | if (useS3) { 26 | try { 27 | awsKeys = require('../.aws-keys.js'); 28 | } catch (e) { 29 | console.log('[ERROR] .aws-keys.js not found: ', e); 30 | } 31 | } 32 | 33 | gulp.task('copyToS3', function() { 34 | // If the aws file are unavailable do nothing 35 | if (!awsKeys) { 36 | // To setup permissions, and policies check the article linked in the top 37 | console.log('Setup your aws keys, and bucket correctly guidelines are found in the link in gulp/cdn-s3.js file'); 38 | return gulp.src('./dist/**'); 39 | } 40 | 41 | var publisher = awspublish.create(awsKeys); 42 | 43 | return gulp.src([ 44 | './dist/**', 45 | '!dist/**/*.test*', 46 | '!dist/rev-manifest.json', 47 | ]) 48 | .pipe(awspublish.gzip()) 49 | .pipe(publisher.publish(headers)) 50 | .pipe(publisher.cache()) 51 | .pipe(publisher.sync()) 52 | .pipe(awspublish.reporter()); 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /gulp/copy.js: -------------------------------------------------------------------------------- 1 | // External modules 2 | var del = require('del'); 3 | var critical = require('critical').stream; 4 | 5 | // Import config 6 | var config = require('./_config'); 7 | 8 | // Html module 9 | module.exports = function(gulp, livereload) { 10 | gulp.task('html', function() { 11 | return gulp.src(config.html) 12 | .pipe(gulp.dest('dist')) 13 | .pipe(livereload()); 14 | }); 15 | 16 | gulp.task('html--deploy', function() { 17 | return gulp.src(config.html) 18 | .pipe(critical({ 19 | base: 'dist/', 20 | inline: true, 21 | css: ['dist/app.css'] 22 | })) 23 | .pipe(gulp.dest('dist')); 24 | }); 25 | 26 | gulp.task('images', function() { 27 | return gulp.src(config.images) 28 | .pipe(gulp.dest('dist/images')) 29 | .pipe(livereload()); 30 | }); 31 | 32 | gulp.task('assets', function() { 33 | return gulp.src(config.assets) 34 | .pipe(gulp.dest('dist/assets')) 35 | .pipe(livereload()); 36 | }); 37 | 38 | gulp.task('fixtures', function() { 39 | return gulp.src(config.fixtures) 40 | .pipe(gulp.dest('dist')) 41 | .pipe(livereload()); 42 | }); 43 | 44 | gulp.task('clean-html-tmp', function () { 45 | return del(['dist/tmp-**']); 46 | }); 47 | 48 | gulp.task('clean-dist', function () { 49 | return del(['dist/**']); 50 | }); 51 | }; 52 | -------------------------------------------------------------------------------- /gulp/libs.js: -------------------------------------------------------------------------------- 1 | // Import modules 2 | var concat = require('gulp-concat'); 3 | var gulpif = require('gulp-if'); 4 | var uglify = require('gulp-uglify'); 5 | 6 | // Import config 7 | var config = require('./_config'); 8 | 9 | var env = process.env.NODE_ENV || 'dev'; 10 | var live = env === 'prod' || env === 'stag'; 11 | 12 | // Html module 13 | module.exports = function(gulp, livereload) { 14 | gulp.task('libs', function() { 15 | return gulp.src(config.libs) 16 | .pipe(concat('app-libs.js')) 17 | .pipe(gulpif(live, uglify())) 18 | .pipe(gulp.dest('dist')) 19 | .pipe(livereload()); 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /gulp/revReplace.js: -------------------------------------------------------------------------------- 1 | var rev = require('gulp-rev'); 2 | var imagemin = require('gulp-imagemin'); 3 | var revReplace = require('gulp-rev-replace'); 4 | var revdel = require('gulp-rev-delete-original'); 5 | 6 | module.exports = function(gulp, useS3) { 7 | var awsConf = false; 8 | 9 | if (useS3) { 10 | try { 11 | awsConf = require('../.aws-conf.js'); 12 | } catch (e) { 13 | console.log('[ERROR] .aws-conf.js not found: ', e); 14 | } 15 | } 16 | 17 | // Build rev files 18 | gulp.task('rev', function() { 19 | return gulp.src([ 20 | 'dist/**/*.{css,js,json,html,jpg,gif,png,svg,ico,map}', 21 | '!dist/index.html' 22 | ]) 23 | .pipe(rev()) 24 | .pipe(revdel()) 25 | .pipe(imagemin()) 26 | .pipe(gulp.dest('dist')) 27 | .pipe(rev.manifest()) 28 | .pipe(gulp.dest('dist')); 29 | }); 30 | 31 | // Replace paths in the following files 32 | gulp.task('rev-replace', function() { 33 | var manifest = gulp.src('./dist/rev-manifest.json'); 34 | var replaceOptions = { 35 | manifest: manifest, 36 | replaceInExtensions: ['.js', '.css', '.html', '.hbs', '.json'] 37 | }; 38 | 39 | if (awsConf !== false) { 40 | replaceOptions.prefix = awsConf.url; 41 | } 42 | 43 | return gulp.src([ 44 | 'dist/**/*.{html,js,css,json}' 45 | ]) 46 | .pipe(revReplace(replaceOptions)) 47 | .pipe(gulp.dest('dist')); 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /gulp/sass.js: -------------------------------------------------------------------------------- 1 | // Global modules 2 | var fs = require('fs'); 3 | var path = require('path'); 4 | 5 | // Import modules 6 | var sass = require('gulp-sass'); 7 | var gulpif = require('gulp-if'); 8 | var concat = require('gulp-concat'); 9 | var cssnano = require('gulp-cssnano'); 10 | var replace = require('gulp-replace'); 11 | var sourcemaps = require('gulp-sourcemaps'); 12 | var autoprefixer = require('gulp-autoprefixer'); 13 | var uncss = require('gulp-uncss'); 14 | var merge = require('merge-stream'); 15 | var yaml = require('js-yaml'); 16 | var sassLint = require('gulp-sass-lint'); 17 | 18 | // Import config 19 | var config = require('./_config'); 20 | 21 | var env = process.env.NODE_ENV || 'dev'; 22 | var live = env === 'prod' || env === 'stag'; 23 | 24 | // Sass module 25 | module.exports = function(gulp, livereload) { 26 | var nanoConf = { 27 | safe: true 28 | }; 29 | 30 | // If a lib is stated then use the merge stream otherwise use the original sass task 31 | if (config.cssLibs.length > 0) { 32 | gulp.task('sass', function() { 33 | var sassStream; 34 | var cssStream; 35 | 36 | //compile sass 37 | sassStream = gulp.src(config.sass) 38 | .pipe(sass().on('error', sass.logError)) 39 | .pipe(autoprefixer()); 40 | 41 | //select additional css files 42 | cssStream = gulp.src(config.cssLibs); 43 | 44 | //merge the two streams and concatenate their contents into a single file 45 | return merge(sassStream, cssStream) 46 | .pipe(gulpif(live, uncss({ 47 | html: ['dist/**/*.html'], 48 | ignore: [ 49 | /is-/ 50 | ] 51 | }))) 52 | .pipe(gulpif(live, cssnano(nanoConf))) 53 | .pipe(gulpif(live, sourcemaps.write('./'))) 54 | .pipe(gulpif(live, replace(/\/\/# sourceMappingURL=.*$/g, ''))) 55 | .pipe(gulp.dest('dist')) 56 | .pipe(livereload()); 57 | }); 58 | } else { 59 | gulp.task('sass', function() { 60 | return gulp.src(config.sass) 61 | .pipe(gulpif(live, sourcemaps.init())) 62 | .pipe(sass().on('error', sass.logError)) 63 | .pipe(autoprefixer()) 64 | .pipe(gulpif(live, uncss({ 65 | html: ['dist/**/*.html'], 66 | ignore: [ 67 | /is-/ 68 | ] 69 | }))) 70 | .pipe(gulpif(live, cssnano(nanoConf))) 71 | .pipe(gulpif(live, sourcemaps.write('./'))) 72 | .pipe(gulpif(live, replace(/\/\/# sourceMappingURL=.*$/g, ''))) 73 | .pipe(gulp.dest('dist')) 74 | .pipe(livereload()); 75 | }); 76 | } 77 | 78 | gulp.task('sass-lint', function () { 79 | var sassLintConfig = yaml.safeLoad(fs.readFileSync(path.join(__dirname, '../', '.sass-lint.yml'), 'utf8')); 80 | 81 | return gulp.src(config.sass) 82 | .pipe(sassLint(sassLintConfig)) 83 | .pipe(sassLint.format()); 84 | }); 85 | }; 86 | -------------------------------------------------------------------------------- /gulp/scripts.js: -------------------------------------------------------------------------------- 1 | // Import native modules 2 | var path = require('path'); 3 | 4 | // Import modules 5 | var del = require('del'); 6 | var concat = require('gulp-concat'); 7 | var babel = require('gulp-babel'); 8 | var gulpif = require('gulp-if'); 9 | var jscs = require('gulp-jscs'); 10 | var uglify = require('gulp-uglify'); 11 | var replace = require('gulp-replace'); 12 | var gulpDocs = require('gulp-ngdocs'); 13 | var sourcemaps = require('gulp-sourcemaps'); 14 | var ngAnnotate = require('gulp-ng-annotate'); 15 | 16 | // Import config 17 | var config = require('./_config'); 18 | var scripts = config.scripts.concat(config.scriptsSkip); 19 | 20 | var env = process.env.NODE_ENV || 'dev'; 21 | var live = env === 'prod' || env === 'stag'; 22 | 23 | // Html module 24 | module.exports = function(gulp, livereload) { 25 | var concatConf = { 26 | newLine: '\n' 27 | }; 28 | 29 | gulp.task('scripts', function() { 30 | return gulp.src(scripts) 31 | .pipe(gulpif(live, sourcemaps.init())) 32 | .pipe(concat('app.js', concatConf)) 33 | .pipe(ngAnnotate()) 34 | .pipe(gulpif(live, uglify())) 35 | .pipe(gulpif(live, sourcemaps.write('./'))) 36 | .pipe(gulpif(live, replace(/\/\/# sourceMappingURL=.*$/g, ''))) 37 | .pipe(gulp.dest('dist')) 38 | .pipe(livereload()); 39 | }); 40 | 41 | gulp.task('script-lint', function() { 42 | return gulp.src(config.scripts) 43 | .pipe(jscs({ 44 | fix: false, 45 | configPath: path.join(__dirname, '..', '/.jscsrc') 46 | })) 47 | .pipe(jscs.reporter()); 48 | }); 49 | 50 | gulp.task('clean-docs', function() { 51 | // Clean docs before making a new one 52 | return del(['docs']); 53 | }); 54 | 55 | gulp.task('script-docs', function () { 56 | var libs = config.libs.concat(config.docLibs); 57 | var options = { 58 | scripts: libs, 59 | loadDefaults: { 60 | angular: false, 61 | angularAnimate: false, 62 | marked: false 63 | }, 64 | html5Mode: true, 65 | startPage: '/docs/api', 66 | title: 'Prototype builder', 67 | image: 'http://localhost:3000/assets/favicon.ico', 68 | imageLink: '/docs/api', 69 | titleLink: '/docs/api' 70 | }; 71 | 72 | return gulp.src(scripts) 73 | .pipe(gulpDocs.process(options)) 74 | .pipe(gulp.dest('./docs')); 75 | }); 76 | 77 | gulp.task('build-docs', gulp.series('clean-docs', 'script-docs')); 78 | }; 79 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // Include main scripts 2 | var gulp = require('gulp'); 3 | var argv = require('yargs').argv; 4 | var livereload = require('gulp-livereload'); 5 | 6 | // Prep configuration 7 | var config = require('./gulp/_config'); 8 | var bumpType = [argv.bump] || ['build']; 9 | var port = argv.p || 8000; 10 | 11 | // If your not using s3 set this to false to improve build speed 12 | var useS3 = false; 13 | 14 | /** 15 | * Include gulp tasks 16 | */ 17 | 18 | /** 19 | * Copy assets and html 20 | * 21 | * Tasks: 22 | * - html 23 | * - html--deploy 24 | * - clean-html-tmp 25 | * - clean-dist 26 | * - assets 27 | * - images 28 | */ 29 | require('./gulp/copy')(gulp, livereload); 30 | 31 | /** 32 | * Compile sass 33 | * 34 | * Tasks: 35 | * - sass 36 | * - sass-lint 37 | */ 38 | require('./gulp/sass')(gulp, livereload); 39 | 40 | /** 41 | * Compile js libs 42 | * 43 | * Tasks: 44 | * - libs 45 | */ 46 | require('./gulp/libs')(gulp, livereload); 47 | 48 | /** 49 | * Compile js scripts 50 | * 51 | * Tasks: 52 | * - scripts 53 | * - scripts-lint 54 | * - build-docs 55 | * - clean-docs 56 | * - script-docs 57 | */ 58 | require('./gulp/scripts')(gulp, livereload); 59 | 60 | /** 61 | * File revision for cache busting 62 | * 63 | * Tasks: 64 | * - rev 65 | * - rev-replace 66 | */ 67 | require('./gulp/revReplace')(gulp, useS3); 68 | 69 | /** 70 | * Copy to S3 71 | * 72 | * Tasks: 73 | * - copyToS3 74 | */ 75 | require('./gulp/cdn-s3')(gulp, useS3); 76 | 77 | 78 | /** 79 | * Setup primary tasks 80 | */ 81 | 82 | // Default build 83 | gulp.task('default', gulp.series('clean-dist', gulp.parallel('sass-lint', 'sass', 'libs', 'script-lint', 'scripts', 'html', 'images', 'assets', 'fixtures'))); 84 | 85 | // Build for deployment 86 | gulp.task('deploy', gulp.series('clean-dist', 'html', gulp.parallel('sass', 'libs', 'scripts', 'images', 'assets', 'fixtures'), 'html--deploy', 'clean-html-tmp', 'rev', 'rev-replace', 'copyToS3')); 87 | 88 | // Watch files for changes and run tasks 89 | gulp.task('watch', gulp.series('default', function () { 90 | livereload.listen(); 91 | 92 | gulp.watch(config.libs, gulp.parallel('libs')); 93 | gulp.watch(config.images, gulp.parallel('images')); 94 | gulp.watch(config.assets, gulp.parallel('assets')); 95 | gulp.watch(config.sass, gulp.parallel('sass', 'sass-lint')); 96 | gulp.watch(config.html, gulp.parallel('html', 'clean-html-tmp')); 97 | gulp.watch(config.scripts, gulp.parallel('scripts', 'script-lint')); 98 | })); 99 | -------------------------------------------------------------------------------- /karma-conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Modified on Sun Mar 06 2017 14:37:13 GMT+0100 (CET) 3 | 4 | module.exports = function(config) { 5 | var filesConfig = require('./gulp/_config'); 6 | var files = filesConfig.testLibs 7 | .concat(filesConfig.libs) 8 | .concat(filesConfig.scripts) 9 | .concat(filesConfig.fixtures) 10 | .concat(filesConfig.html); 11 | 12 | config.set({ 13 | // base path that will be used to resolve all patterns (eg. files, exclude) 14 | basePath: __dirname, 15 | 16 | // frameworks to use 17 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 18 | frameworks: [ 19 | 'mocha', 20 | 'chai' 21 | ], 22 | 23 | plugins: [ 24 | 'karma-phantomjs-launcher', 25 | 'karma-mocha', 26 | 'karma-chai', 27 | 'karma-ng-html2js-preprocessor', 28 | 'karma-json-fixtures-preprocessor' 29 | ], 30 | 31 | // list of files / patterns to load in the browser 32 | files: files, 33 | 34 | // list of files to exclude 35 | exclude: [], 36 | 37 | // preprocess matching files before serving them to the browser 38 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 39 | preprocessors: { 40 | 'app/**/*.json': 'json_fixtures', 41 | 'app/**/*.html': 'ng-html2js' 42 | }, 43 | 44 | ngHtml2JsPreprocessor: { 45 | stripPrefix: 'app', 46 | moduleName: function (htmlPath, originalPath) { 47 | return htmlPath; 48 | } 49 | }, 50 | 51 | jsonFixturesPreprocessor: { 52 | stripPrefix: 'app', 53 | variableName: '__fixtures__', 54 | transformPath: function(path) { 55 | return path + '.js'; 56 | } 57 | }, 58 | 59 | // test results reporter to use 60 | // possible values: 'dots', 'progress' 61 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 62 | reporters: [ 63 | 'progress' 64 | ], 65 | 66 | // web server port 67 | port: 9876, 68 | 69 | // enable / disable colors in the output (reporters and logs) 70 | colors: true, 71 | 72 | // level of logging 73 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 74 | logLevel: config.LOG_INFO, 75 | 76 | // enable / disable watching file and executing tests whenever any file changes 77 | autoWatch: true, 78 | 79 | // start these browsers 80 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 81 | browsers: [ 82 | 'PhantomJS' 83 | ], 84 | 85 | // Continuous Integration mode 86 | // if true, Karma captures browsers, runs the tests and exits 87 | singleRun: false, 88 | 89 | // Concurrency level 90 | // how many browser should be started simultanous 91 | concurrency: Infinity, 92 | 93 | phantomjsLauncher: { 94 | // Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom) 95 | exitOnResourceError: true 96 | } 97 | }); 98 | }; 99 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prototype-boilerplate", 3 | "version": "3.2.2", 4 | "description": "This is a prototype-boilerplate which is a good way to start small html prototypes for show. With build-in seamless workflow", 5 | "main": "gulpfile.js", 6 | "homepage": "http://prototype-builder.nomis.dk/", 7 | "author": "Simon Dragsbæk Petersen - github.com/sp90 - dev@nomis.dk", 8 | "contributors": [ 9 | { 10 | "name": "Simon Petersen", 11 | "email": "dev@nomis.dk" 12 | } 13 | ], 14 | "bugs": { 15 | "url": "https://github.com/sp90/prototype-builder/issues" 16 | }, 17 | "license": "ISC", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/sp90/prototype-builder.git" 21 | }, 22 | "scripts": { 23 | "test": "./node_modules/karma/bin/karma start karma-conf.js --single-run", 24 | "test:watch": "./node_modules/karma/bin/karma start karma-conf.js --auto-watch", 25 | "start": "node server.js", 26 | "docker-start": "docker run -p 80:80 -v $PWD/dist:/var/www --rm --name=prototype prototype", 27 | 28 | "deploy:prod": "NODE_ENV=prod gulp deploy", 29 | "deploy:stag": "NODE_ENV=stag gulp deploy", 30 | "deploy:dev": "NODE_ENV=dev gulp deploy", 31 | 32 | "add:service": "node scaffolding/index.js service", 33 | "add:controller": "node scaffolding/index.js controller", 34 | "add:factory": "node scaffolding/index.js factory", 35 | "add:filter": "node scaffolding/index.js filter", 36 | "add:constant": "node scaffolding/index.js constant", 37 | "add:component": "node scaffolding/index.js component", 38 | "add:ser": "node scaffolding/index.js service", 39 | "add:con": "node scaffolding/index.js controller", 40 | "add:cons": "node scaffolding/index.js constant", 41 | "add:fac": "node scaffolding/index.js factory", 42 | "add:fil": "node scaffolding/index.js filter", 43 | "add:com": "node scaffolding/index.js component" 44 | }, 45 | "devDependencies": { 46 | "angular-animate": "^1.5.6", 47 | "angular-mocks": "^1.5.6", 48 | "babel-polyfill": "^6.9.1", 49 | "chai": "^3.5.0", 50 | "chalk": "^1.1.3", 51 | "critical": "^0.6.0", 52 | "del": "^2.2.0", 53 | "glob": "^7.0.5", 54 | "gulp": "github:gulpjs/gulp#4.0", 55 | "gulp-autoprefixer": "^2.2.0", 56 | "gulp-awspublish": "^3.2.0", 57 | "gulp-babel": "^6.1.0", 58 | "gulp-bump": "^0.3.1", 59 | "gulp-concat": "^2.5.2", 60 | "gulp-cssnano": "^2.1.2", 61 | "gulp-if": "^2.0.1", 62 | "gulp-imagemin": "^3.0.1", 63 | "gulp-jscs": "^3.0.2", 64 | "gulp-livereload": "^3.8.1", 65 | "gulp-ng-annotate": "^2.0.0", 66 | "gulp-ngdocs": "^0.2.13", 67 | "gulp-replace": "^0.5.4", 68 | "gulp-rev": "^7.0.0", 69 | "gulp-rev-delete-original": "^0.1.0", 70 | "gulp-rev-replace": "^0.4.3", 71 | "gulp-sass": "^2.0.1", 72 | "gulp-sass-lint": "^1.1.1", 73 | "gulp-sourcemaps": "^1.6.0", 74 | "gulp-uglify": "^1.5.3", 75 | "gulp-uncss": "^1.0.4", 76 | "js-yaml": "^3.6.1", 77 | "karma": "^0.13.21", 78 | "karma-chai": "^0.1.0", 79 | "karma-json-fixtures-preprocessor": "0.0.6", 80 | "karma-mocha": "^0.2.2", 81 | "karma-ng-html2js-preprocessor": "^1.0.0", 82 | "karma-phantomjs-launcher": "^1.0.0", 83 | "lodash": "^4.13.1", 84 | "marked": "^0.3.5", 85 | "merge-stream": "^1.0.0", 86 | "mocha": "^2.4.5", 87 | "phantomjs-prebuilt": "^2.1.7", 88 | "prettify": "*", 89 | "yargs": "^3.10.0" 90 | }, 91 | "dependencies": { 92 | "angular": "^1.5.7", 93 | "angular-ui-router": "^0.2.18", 94 | "compression": "^1.6.1", 95 | "express": "^4.13.4", 96 | "fg-loadcss": "^1.2.0", 97 | "morgan": "^1.7.0" 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /prototype-builder.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /scaffolding/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | interpolate: /{{([\s\S]+?)}}/g, 3 | modules: [ 4 | { 5 | type: 'service', 6 | output: 'app/services/', 7 | fileTypes: '{js,test.js,fixture.json}' 8 | }, 9 | { 10 | type: 'filter', 11 | output: 'app/filters/', 12 | fileTypes: '{js,test.js}' 13 | }, 14 | { 15 | type: 'factory', 16 | output: 'app/factories/', 17 | fileTypes: '{js,test.js}' 18 | }, 19 | { 20 | type: 'constant', 21 | output: 'app/constants/', 22 | fileTypes: '{js,test.js}' 23 | }, 24 | { 25 | type: 'component', 26 | output: 'app/components/', 27 | fileTypes: '{scss,js,html,test.js,fixture.html}' 28 | }, 29 | { 30 | type: 'controller', 31 | output: 'app/controllers/', 32 | fileTypes: '{scss,js,html,test.js}' 33 | } 34 | ] 35 | }; 36 | -------------------------------------------------------------------------------- /scaffolding/index.js: -------------------------------------------------------------------------------- 1 | // Native modules 2 | var fs = require('fs'); 3 | var path = require('path'); 4 | 5 | // External modules 6 | var _ = require('lodash'); 7 | var glob = require("glob"); 8 | var chalk = require('chalk'); 9 | 10 | // Basic config 11 | var config = require('./_config'); 12 | var args = process.argv.slice(2); 13 | var baseProjectPath = path.join(__dirname, '../'); 14 | var baseTemplatePath = path.join(__dirname, '/templates'); 15 | var type = args[0]; 16 | 17 | // Test if args are passed? 18 | if (1 >= args.length) { 19 | console.log(chalk.red('You need to give the module a name')); 20 | console.log(chalk.yellow('npm run add:' + type + ' NAME')); 21 | return; 22 | } 23 | 24 | var dataObj = { 25 | name: args[1], 26 | nameUpper: capitalizeFirstLetter(args[1]), 27 | nameLower: args[1].toLowerCase(), 28 | nameSlugified: slugify(args[1]) 29 | }; 30 | 31 | // Setup based on config 32 | if (!_.isUndefined(config.interpolate)) { 33 | _.templateSettings.interpolate = config.interpolate; 34 | } 35 | 36 | var module = config.modules.filter(function (obj) { 37 | return obj.type === type; 38 | })[0]; 39 | 40 | build(module, function(filesPath, outputPath) { 41 | var arrLength = filesPath.length; 42 | var moduleDirName = type === 'constant' ? path.join(__dirname, '../', outputPath) : path.join(__dirname, '../', outputPath, dataObj.name); 43 | 44 | if (!fs.existsSync(moduleDirName) && type !== 'constant'){ 45 | // If i does not exists create it 46 | fs.mkdirSync(moduleDirName); 47 | } else if (type !== 'constant') { 48 | // Close program 49 | return moduleExists(moduleDirName); 50 | } 51 | 52 | _.map(filesPath, function(filePath, i) { 53 | var pathParts = filePath.split('/'); 54 | var pathEnding = pathParts[pathParts.length - 1]; 55 | var n = pathEnding.indexOf('.'); 56 | var resultEnding = pathEnding.substring(n); 57 | 58 | read(filePath, function(fileContent) { 59 | var setPath = resultEnding === '.scss' ? path.join(moduleDirName, '_' + dataObj.name + resultEnding) : path.join(moduleDirName, dataObj.name + resultEnding); 60 | 61 | // Check if the file exists (should only be constants) 62 | if (fs.existsSync(setPath)) { 63 | // Close program 64 | return fileExsists(setPath); 65 | } 66 | 67 | write(setPath, _.template(fileContent)(dataObj), function() { 68 | // Only show logs on the finish of the last file 69 | if (arrLength - 1 === i) { 70 | return moduleCreated(); 71 | } 72 | }); 73 | }); 74 | }); 75 | }); 76 | 77 | function build(module, callback) { 78 | var modulePath = path.join(baseTemplatePath, module.type); 79 | var moduleFilesGlob = modulePath + '/*.' + module.fileTypes; 80 | 81 | glob(moduleFilesGlob, function (err, filesPath) { 82 | if (err) { 83 | return console.log(chalk.red(err)); 84 | } 85 | 86 | callback(filesPath, module.output); 87 | }); 88 | } 89 | 90 | function read(path, cb) { 91 | fs.readFile(path, 'utf8', function(err, data) { 92 | if (err) { 93 | return console.log(chalk.red(err)); 94 | } 95 | 96 | cb(data); 97 | }); 98 | } 99 | 100 | function write(path, content, cb) { 101 | fs.writeFile(path, content, function (err,data) { 102 | if (err) { 103 | return console.log(chalk.red(err)); 104 | } 105 | 106 | cb(data); 107 | }); 108 | } 109 | 110 | function capitalizeFirstLetter(string) { 111 | return string.charAt(0).toUpperCase() + string.slice(1); 112 | } 113 | 114 | function slugify(text) { 115 | return text.replace( /([a-z])([A-Z])/g, '$1-$2' ).toLowerCase(); 116 | } 117 | 118 | function moduleExists(path) { 119 | console.log(chalk.red('The module with that name already exists')); 120 | console.log(chalk.red('Please select another one')); 121 | console.log('-------------------------------'); 122 | console.log(chalk.yellow.bold('FolderPath')); 123 | console.log(chalk.yellow(path)); 124 | } 125 | 126 | function fileExsists(path) { 127 | console.log(chalk.red('A file with this name do already exist')); 128 | console.log(chalk.red('Please select another one')); 129 | console.log('-------------------------------'); 130 | console.log(chalk.yellow.bold('Filepath')); 131 | console.log(chalk.yellow(path)); 132 | } 133 | 134 | function moduleCreated() { 135 | console.log(chalk.green('The new module has been created')); 136 | console.log(chalk.bold.green('the module name is: ' + type + '.' + dataObj.name)); 137 | console.log('-------------------------------'); 138 | 139 | if (type === 'controller') { 140 | console.log(chalk.yellow('Remember to bind the sass file in app.scss in the root application folder')); 141 | console.log(chalk.yellow('And Bind your controller in app.js')); 142 | } else if (type === 'component') { 143 | console.log(chalk.yellow('Remember to bind the sass file in app.scss in the root application folder')); 144 | console.log(chalk.yellow('And add this component as a dependency in the controller you need it')); 145 | } else { 146 | console.log(chalk.yellow('Remember to bind the dependency where ever you need this module')); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /scaffolding/templates/component/_component.scss: -------------------------------------------------------------------------------- 1 | .{{nameSlugified}} { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /scaffolding/templates/component/component.fixture.html: -------------------------------------------------------------------------------- 1 | <{{nameSlugified}}> 2 | -------------------------------------------------------------------------------- /scaffolding/templates/component/component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /scaffolding/templates/component/component.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('directive.{{name}}', []) 6 | .directive('{{name}}', {{name}}); 7 | 8 | function {{name}}() { 9 | return { 10 | restrict: 'E', 11 | templateUrl: '/components/{{name}}/{{name}}.html', 12 | scope: { 13 | content: '=' 14 | }, 15 | link: link 16 | }; 17 | 18 | function link(scope, element, attrs) { 19 | angular.extend(scope, { 20 | 21 | }); 22 | } 23 | } 24 | })(); 25 | -------------------------------------------------------------------------------- /scaffolding/templates/component/component.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('{{nameUpper}} component', function() { 5 | var $outerScope, $scope, element; 6 | 7 | beforeEach(module('directive.{{name}}')); 8 | beforeEach(module('/components/{{name}}/{{name}}.html')); 9 | beforeEach(module('/components/{{name}}/{{name}}.fixture.html')); 10 | 11 | beforeEach(inject(function($compile, $rootScope, $templateCache) { 12 | // Get fixture 13 | var fixture = $templateCache.get('/components/{{name}}/{{name}}.fixture.html'); 14 | // Create scope 15 | $outerScope = $rootScope.$new(); 16 | // Compile scope & fixture into the compiled element 17 | element = $compile(angular.element(fixture))($outerScope); 18 | // Init digest, to test before it has been given any data 19 | $outerScope.$digest(); 20 | })); 21 | 22 | it('should do something', function() { 23 | // Do outerScope changes, and remember to digest after 24 | // $outerScope.something = 'test'; 25 | // $outerScope.$digest(); 26 | 27 | // Html: 28 | // element.html(); 29 | 30 | // Inner scope 31 | // var $scope = element.isolateScope(); 32 | }); 33 | }); 34 | })(); 35 | -------------------------------------------------------------------------------- /scaffolding/templates/constant/constant.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('constant.{{name}}') 6 | .constant('{{name}}', []); 7 | })(); 8 | -------------------------------------------------------------------------------- /scaffolding/templates/controller/_controller.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * {{nameUpper}} styles 3 | */ 4 | 5 | .{{nameSlugified}} { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /scaffolding/templates/controller/controller.html: -------------------------------------------------------------------------------- 1 |
2 |

{{nameUpper}}

3 |
4 | -------------------------------------------------------------------------------- /scaffolding/templates/controller/controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // No strict because of babel.js 3 | 4 | var modules = []; 5 | 6 | angular 7 | .module('controller.{{name}}', modules) 8 | .controller('{{nameUpper}}Ctrl', {{nameUpper}}Ctrl); 9 | 10 | function {{nameUpper}}Ctrl($scope) { 11 | var {{name}} = this; 12 | 13 | angular.extend({{name}}, { 14 | title: '...' 15 | }); 16 | } 17 | })(); 18 | -------------------------------------------------------------------------------- /scaffolding/templates/controller/controller.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // Some test here 5 | describe('{{nameUpper}}Controller function', function() { 6 | var $scope; 7 | 8 | beforeEach(module('controller.{{name}}')); 9 | beforeEach(module('/controllers/{{name}}/{{name}}.html')); 10 | 11 | beforeEach(inject(function($rootScope, $controller, $httpBackend) { 12 | $scope = $rootScope.$new(); 13 | 14 | $controller('{{nameUpper}}Controller', { 15 | $scope: $scope 16 | }); 17 | 18 | // Get fixture if any http requests is made on init 19 | // var fixture = window.__fixtures__['/services/romans/romans.fixture']; 20 | // $httpBackend.whenGET('/services/romans/romans.fixture.json').respond(fixture); 21 | // $httpBackend.flush(); 22 | })); 23 | 24 | it('should create something', function() { 25 | // Expect something 26 | $scope.$digest(); 27 | 28 | console.log("$scope: ", $scope); 29 | }); 30 | }); 31 | })(); 32 | -------------------------------------------------------------------------------- /scaffolding/templates/factory/factory.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('factory.{{name}}', []) 6 | .factory('{{nameUpper}}', {{nameUpper}}); 7 | 8 | function {{nameUpper}}() { 9 | return { 10 | method: method 11 | }; 12 | 13 | function method() { 14 | 15 | } 16 | } 17 | })(); 18 | -------------------------------------------------------------------------------- /scaffolding/templates/factory/factory.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('{{nameUpper}} factory', function () { 5 | var factory; 6 | 7 | beforeEach('factory.{{name}}')); 8 | beforeEach(inject(function({{nameUpper}}) { 9 | factory = {{nameUpper}}; 10 | })); 11 | 12 | describe('Method', function() { 13 | it('Should define method', function() { 14 | expect(factory.method).to.not.be.undefined; 15 | expect(factory).to.respondTo('method'); 16 | }); 17 | }); 18 | }); 19 | })(); 20 | -------------------------------------------------------------------------------- /scaffolding/templates/filter/filter.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('filter.{{name}}', []) 6 | .filter('{{name}}', {{name}}); 7 | 8 | function {{name}}() { 9 | return function(val) { 10 | 11 | // Output {{name}} val 12 | return val; 13 | }; 14 | } 15 | })(); 16 | -------------------------------------------------------------------------------- /scaffolding/templates/filter/filter.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('{{nameUpper}} filter', function () { 5 | var $filter; 6 | 7 | beforeEach('filter.{{name}}')); 8 | beforeEach(inject(function(_$filter_) { 9 | $filter = _$filter_; 10 | })); 11 | 12 | it('should do something', function() { 13 | // Some test 14 | }); 15 | }); 16 | })(); 17 | -------------------------------------------------------------------------------- /scaffolding/templates/service/service.fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [] 3 | } 4 | -------------------------------------------------------------------------------- /scaffolding/templates/service/service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('service.{{name}}', []) 6 | .service('{{nameUpper}}', function($http, $q) { 7 | return { 8 | get: get 9 | }; 10 | 11 | function get() { 12 | return $q(function(resolve, reject) { 13 | $http({ 14 | method: 'GET', 15 | url: '/services/{{name}}/{{name}}.fixture.json' 16 | }) 17 | .success(function(res) { 18 | resolve(res.data); 19 | }) 20 | .error(function(err) { 21 | reject(err); 22 | }); 23 | }); 24 | } 25 | }); 26 | })(); 27 | -------------------------------------------------------------------------------- /scaffolding/templates/service/service.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe("{{nameUpper}} service", function () { 5 | var {{nameUpper}}, $httpBackend; 6 | 7 | beforeEach(module('service.{{name}}')); 8 | beforeEach(inject(function (_{{nameUpper}}_, _$httpBackend_) { 9 | {{nameUpper}} = _{{nameUpper}}_; 10 | $httpBackend = _$httpBackend_; 11 | })); 12 | 13 | it("should do something", function () { 14 | // Get fixture 15 | var fixture = window.__fixtures__['/services/{{name}}/{{name}}.fixture']; 16 | $httpBackend.whenGET('/services/{{name}}/{{name}}.fixture.json').respond(fixture); 17 | 18 | {{nameUpper}}.get() 19 | .then(function(result) { 20 | expect(fixture.data).to.deep.equal(result); 21 | }); 22 | 23 | $httpBackend.flush(); 24 | }); 25 | }); 26 | })(); 27 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | //Core Node.js 2 | var path = require('path'); 3 | 4 | //External Dependencies 5 | var express = require('express'); 6 | var morgan = require('morgan'); 7 | var compression = require('compression'); 8 | 9 | var app = express(); 10 | var port = process.env.PORT || 3000; 11 | 12 | app.use(compression()); 13 | app.use(morgan('dev')); 14 | app.use(express.static(path.join(__dirname, '/dist'), { maxAge: 86400000 })); 15 | app.use('/docs/', express.static(path.join(__dirname, '/docs'), { maxAge: 86400000 })); 16 | 17 | app.all('/docs/*', function(req, res) { 18 | return res.sendFile(path.join(__dirname, '/docs/index.html')); 19 | }); 20 | 21 | app.all('*', function(req, res) { 22 | return res.sendFile(path.join(__dirname, '/dist/index.html')); 23 | }); 24 | 25 | app.listen(port); 26 | 27 | console.log('listening on port: %d', port); 28 | --------------------------------------------------------------------------------