├── src
├── common
│ ├── user
│ │ ├── user.spec.js
│ │ ├── user.js
│ │ └── user.factory.js
│ ├── hero
│ │ ├── hero.jade
│ │ ├── hero.controller.js
│ │ ├── hero.styl
│ │ ├── hero.js
│ │ ├── hero.component.js
│ │ └── hero.spec.js
│ ├── navbar
│ │ ├── navbar.controller.js
│ │ ├── navbar.js
│ │ ├── navbar.styl
│ │ ├── navbar.component.js
│ │ ├── navbar.html
│ │ └── navbar.spec.js
│ └── common.js
├── styles.scss
├── components
│ ├── contact
│ │ ├── contact.address.jade
│ │ ├── contact.controller.js
│ │ ├── contact.address.controller.js
│ │ ├── contact.form.jade
│ │ ├── contact.form.component.js
│ │ ├── contact.address.component.js
│ │ ├── contact.component.js
│ │ ├── contact.js
│ │ ├── contact.html
│ │ ├── contact.address.js
│ │ ├── contact.form.js
│ │ └── contact.form.controller.js
│ ├── home
│ │ ├── home.controller.js
│ │ ├── home.component.js
│ │ ├── home.html
│ │ └── home.js
│ ├── new
│ │ ├── new.html
│ │ ├── new.controller.js
│ │ ├── new.component.js
│ │ └── new.js
│ ├── forms
│ │ ├── forms.component.js
│ │ ├── forms.html
│ │ ├── forms.js
│ │ ├── forms.controller.js
│ │ ├── base.js
│ │ └── forms.spec.js
│ ├── github
│ │ ├── github.component.js
│ │ ├── github.controller.js
│ │ ├── github.html
│ │ ├── github.js
│ │ └── github.service.js
│ └── components.js
├── app.html
├── app.component.js
├── utils.js
├── app.js
├── index.html
└── utils.spec.js
├── requirements.txt
├── .gitignore
├── config
├── webpack.dev.js
├── webpack.common.js
└── webpack.prod.js
├── webpack.config.js
├── .travis.yml
├── .eslintrc
├── spec.bundle.js
├── test.robot
├── karma.conf.js
├── package.json
└── README.rst
/src/common/user/user.spec.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 80px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/components/contact/contact.address.jade:
--------------------------------------------------------------------------------
1 | h2 Contact Address
2 | div {{ vm.address }}
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | robotframework
2 | robotframework-selenium2library
3 | robotframework-debuglibrary
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | .env/
4 | log.html
5 | output.xml
6 | report.html
7 | *.png
8 | npm-debug.log
9 |
10 |
--------------------------------------------------------------------------------
/src/common/hero/hero.jade:
--------------------------------------------------------------------------------
1 | div.jumbotron
2 | h1 Angular, ES6, Webpack Starter!
3 | h3 You can find my template inside {{ vm.name }}.html
4 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/src/common/hero/hero.controller.js:
--------------------------------------------------------------------------------
1 | class HeroController {
2 | constructor() {
3 | this.name = 'hero';
4 | }
5 | }
6 |
7 | export default HeroController;
8 |
--------------------------------------------------------------------------------
/src/components/home/home.controller.js:
--------------------------------------------------------------------------------
1 | class HomeController {
2 | constructor() {
3 | this.name = 'home';
4 | }
5 | }
6 |
7 | export default HomeController;
8 |
--------------------------------------------------------------------------------
/src/components/new/new.html:
--------------------------------------------------------------------------------
1 |
2 | You can find my template inside {{ vm.name }}.html
3 |
4 | New Component Example.
5 |
6 |
--------------------------------------------------------------------------------
/src/common/hero/hero.styl:
--------------------------------------------------------------------------------
1 | @import '../common'
2 |
3 | .hero
4 | background-color $darkBgColor
5 | height 50rem
6 | padding 3rem
7 | *
8 | color $lightTextColor
9 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.controller.js:
--------------------------------------------------------------------------------
1 | class NavbarController {
2 | constructor() {
3 | this.name = 'navbar';
4 | }
5 | }
6 |
7 | export default NavbarController;
8 |
--------------------------------------------------------------------------------
/src/components/new/new.controller.js:
--------------------------------------------------------------------------------
1 | class NewController {
2 | constructor() {
3 | this.name = 'New Component Syntax';
4 | }
5 | }
6 |
7 | export default NewController;
8 |
--------------------------------------------------------------------------------
/config/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const webpackMerge = require('webpack-merge');
2 | const commonConfig = require('./webpack.common.js');
3 |
4 | module.exports = webpackMerge(commonConfig, {});
5 |
--------------------------------------------------------------------------------
/src/components/contact/contact.controller.js:
--------------------------------------------------------------------------------
1 | class ContactController {
2 | constructor() {
3 | this.name = 'Contact Us';
4 | }
5 | }
6 |
7 | export default ContactController;
8 |
--------------------------------------------------------------------------------
/src/app.component.js:
--------------------------------------------------------------------------------
1 | import template from './app.html';
2 |
3 | let appComponent = () => {
4 | return {
5 | template,
6 | restrict: 'E'
7 | };
8 | };
9 |
10 | export default appComponent;
11 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | // add field to existing json schema
4 | let addField = function(schema, field) {
5 | return _.merge(schema, {'properties': field});
6 | };
7 |
8 | export default addField;
9 |
--------------------------------------------------------------------------------
/src/common/user/user.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import UserFactory from './user.factory';
3 |
4 | let userModule = angular.module('user', [])
5 |
6 | .factory('User', UserFactory);
7 |
8 | export default userModule;
9 |
--------------------------------------------------------------------------------
/src/components/contact/contact.address.controller.js:
--------------------------------------------------------------------------------
1 | class ContactAddressController {
2 | constructor() {
3 | this.name = 'Our Address';
4 | this.address = 'Bornheimer Straße 37; 531111 Bonn';
5 | }
6 | }
7 |
8 | export default ContactAddressController;
9 |
--------------------------------------------------------------------------------
/src/common/common.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import Navbar from './navbar/navbar';
3 | import Hero from './hero/hero';
4 | import User from './user/user';
5 |
6 | export default angular.module('app.common', [
7 | Navbar.name,
8 | Hero.name,
9 | User.name
10 | ]);
11 |
--------------------------------------------------------------------------------
/src/common/hero/hero.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import heroComponent from './hero.component';
4 |
5 | let heroModule = angular.module('hero', [
6 | uiRouter
7 | ])
8 |
9 | .directive('hero', heroComponent);
10 |
11 | export default heroModule;
12 |
--------------------------------------------------------------------------------
/src/components/contact/contact.form.jade:
--------------------------------------------------------------------------------
1 | h2 Contact Form
2 | form(name='form' sf-schema='vm.schema', sf-form='vm.form', sf-model='vm.model', ng-submit="vm.onSubmit(form)")
3 |
4 | h3 Schema
5 | pre {{vm.schema | json}}
6 |
7 | h3 Form
8 | pre {{vm.form | json}}
9 |
10 | h3 Model
11 | pre {{vm.model | json}}
12 |
--------------------------------------------------------------------------------
/src/components/new/new.component.js:
--------------------------------------------------------------------------------
1 | import template from './new.html';
2 | import controller from './new.controller';
3 |
4 | let newComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template: template,
8 | controller: controller,
9 | controllerAs: 'vm'
10 | };
11 |
12 | export default newComponent;
13 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import navbarComponent from './navbar.component';
4 |
5 | let navbarModule = angular.module('navbar', [
6 | uiRouter
7 | ])
8 |
9 | .directive('navbar', navbarComponent);
10 |
11 | export default navbarModule;
12 |
--------------------------------------------------------------------------------
/src/common/user/user.factory.js:
--------------------------------------------------------------------------------
1 | let UserFactory = function () {
2 | const user = {};
3 |
4 | let getUser = () => {
5 | return user;
6 | };
7 |
8 | let isSignedIn = () => {
9 | return user.isSignedIn;
10 | };
11 |
12 | return { getUser, isSignedIn };
13 | };
14 |
15 | export default UserFactory;
16 |
--------------------------------------------------------------------------------
/src/components/forms/forms.component.js:
--------------------------------------------------------------------------------
1 | import template from './forms.html';
2 | import controller from './forms.controller';
3 |
4 | let formsComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template: template,
8 | controller: controller,
9 | controllerAs: 'vm'
10 | };
11 |
12 | export default formsComponent;
13 |
--------------------------------------------------------------------------------
/src/components/home/home.component.js:
--------------------------------------------------------------------------------
1 | import template from './home.html';
2 | import controller from './home.controller';
3 |
4 | let homeComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template,
8 | controller,
9 | controllerAs: 'vm',
10 | bindToController: true
11 | };
12 |
13 | export default homeComponent;
14 |
--------------------------------------------------------------------------------
/src/components/github/github.component.js:
--------------------------------------------------------------------------------
1 | import template from './github.html';
2 | import controller from './github.controller';
3 |
4 | let githubComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template,
8 | controller,
9 | controllerAs: 'vm',
10 | bindToController: true
11 | };
12 |
13 | export default githubComponent;
14 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.styl:
--------------------------------------------------------------------------------
1 | @import '../common'
2 |
3 | .navbar
4 | height 6.5rem
5 | background-color $primaryColor
6 | padding 1rem
7 | .nav-links
8 | .logo
9 | display inline-block
10 | .logo
11 | color $lightTextColor
12 | margin-right 50%
13 | .nav-links
14 | span
15 | color $lightTextColor
16 | font-size 1.6rem
17 |
--------------------------------------------------------------------------------
/src/components/home/home.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
You can find my template inside {{ vm.name }}.html
8 |
9 | - Angular 1.5
10 | - UI Router
11 | - Webpack
12 | - ES 6 / Babel
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/contact/contact.form.component.js:
--------------------------------------------------------------------------------
1 | import template from './contact.form.jade';
2 | import controller from './contact.form.controller';
3 |
4 | let contactFormComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template,
8 | controller,
9 | controllerAs: 'vm',
10 | bindToController: true
11 | };
12 |
13 | export default contactFormComponent;
14 |
--------------------------------------------------------------------------------
/src/common/hero/hero.component.js:
--------------------------------------------------------------------------------
1 | import template from './hero.jade';
2 | import controller from './hero.controller';
3 |
4 | let heroComponent = function () {
5 | return {
6 | restrict: 'E',
7 | scope: {},
8 | template,
9 | controller,
10 | controllerAs: 'vm',
11 | bindToController: true
12 | };
13 | };
14 |
15 | export default heroComponent;
16 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.component.js:
--------------------------------------------------------------------------------
1 | import template from './navbar.html';
2 | import controller from './navbar.controller';
3 |
4 | let navbarComponent = function () {
5 | return {
6 | restrict: 'E',
7 | scope: {},
8 | template,
9 | controller,
10 | controllerAs: 'vm',
11 | bindToController: true
12 | };
13 | };
14 |
15 | export default navbarComponent;
16 |
--------------------------------------------------------------------------------
/src/components/contact/contact.address.component.js:
--------------------------------------------------------------------------------
1 | import template from './contact.address.jade';
2 | import controller from './contact.address.controller';
3 |
4 | let contactAddressComponent = {
5 | restrict: 'E',
6 | scope: {},
7 | template,
8 | controller,
9 | controllerAs: 'vm',
10 | bindToController: true
11 | };
12 |
13 | export default contactAddressComponent;
14 |
--------------------------------------------------------------------------------
/src/components/github/github.controller.js:
--------------------------------------------------------------------------------
1 | class GithubController {
2 |
3 | constructor(githubService) {
4 | this.result = {};
5 | this.service = githubService;
6 | }
7 |
8 | getDetails() {
9 | this.service.getItems(this.githubUsername).then((res) => {
10 | this.result = res.data;
11 | });
12 | }
13 |
14 | }
15 |
16 | export default GithubController;
17 |
--------------------------------------------------------------------------------
/src/components/contact/contact.component.js:
--------------------------------------------------------------------------------
1 | import template from './contact.html';
2 | import controller from './contact.controller';
3 |
4 | let contactComponent = function () {
5 | return {
6 | restrict: 'E',
7 | scope: {},
8 | template,
9 | controller,
10 | controllerAs: 'vm',
11 | bindToController: true
12 | };
13 | };
14 |
15 | export default contactComponent;
16 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | switch (process.env.NODE_ENV) {
2 | case 'prod':
3 | case 'production':
4 | module.exports = require('./config/webpack.prod');
5 | break;
6 | case 'test':
7 | case 'testing':
8 | module.exports = require('./config/webpack.test');
9 | break;
10 | case 'dev':
11 | case 'development':
12 | default:
13 | module.exports = require('./config/webpack.dev');
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/new/new.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import newComponent from './new.component';
4 |
5 | let newModule = angular.module('new', [
6 | uiRouter
7 | ])
8 |
9 | .config(($stateProvider) => {
10 | $stateProvider
11 | .state('new', {
12 | url: '/new',
13 | template: ''
14 | });
15 | })
16 |
17 | .component('new', newComponent);
18 |
19 | export default newModule;
20 |
--------------------------------------------------------------------------------
/src/components/forms/forms.html:
--------------------------------------------------------------------------------
1 |
2 | Forms
3 |
4 |
9 |
10 | Schema
11 | {{vm.schema | json}}
12 |
13 | Form
14 | {{vm.form | json}}
15 |
16 | Model
17 | {{vm.model | json}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import 'jquery';
2 | import 'bootstrap/dist/css/bootstrap.min.css';
3 | import angular from 'angular';
4 | import uiRouter from 'angular-ui-router';
5 | import AppComponent from './app.component.js';
6 | import Common from './common/common';
7 | import Components from './components/components';
8 | import './styles.scss';
9 |
10 | angular.module('myApp', [
11 | uiRouter,
12 | Common.name,
13 | Components.name
14 | ])
15 | .directive('app', AppComponent);
16 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Angular Webpack Example
7 |
8 |
9 |
10 |
11 |
12 |
13 | Loading...
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/contact/contact.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import contactComponent from './contact.component';
4 |
5 | let contactModule = angular.module('contact', [
6 | uiRouter
7 | ])
8 |
9 | .config(($stateProvider) => {
10 | $stateProvider
11 | .state('contact', {
12 | url: '/contact',
13 | template: ''
14 | });
15 | })
16 |
17 | .component('contact', contactComponent);
18 |
19 | export default contactModule;
20 |
--------------------------------------------------------------------------------
/src/components/github/github.html:
--------------------------------------------------------------------------------
1 |
2 | Github User Details
3 |
15 |
--------------------------------------------------------------------------------
/src/components/home/home.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import homeComponent from './home.component';
4 |
5 | let homeModule = angular.module('home', [
6 | uiRouter
7 | ])
8 |
9 | .config(($stateProvider, $urlRouterProvider) => {
10 | $urlRouterProvider.otherwise('/');
11 |
12 | $stateProvider
13 | .state('home', {
14 | url: '/',
15 | template: ''
16 | });
17 | })
18 |
19 | .component('home', homeComponent);
20 |
21 | export default homeModule;
22 |
--------------------------------------------------------------------------------
/src/components/contact/contact.html:
--------------------------------------------------------------------------------
1 |
2 | You can find my template inside {{ vm.name }}.html
3 |
21 |
--------------------------------------------------------------------------------
/src/components/contact/contact.address.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import contactAddressComponent from './contact.address.component';
4 |
5 | let contactAddressModule = angular.module('contactAddress', [
6 | uiRouter
7 | ])
8 |
9 | .config(($stateProvider) => {
10 | $stateProvider
11 | .state('contact.address', {
12 | url: '/address',
13 | template: ''
14 | });
15 | })
16 |
17 | .component('address', contactAddressComponent);
18 |
19 | export default contactAddressModule;
20 |
--------------------------------------------------------------------------------
/src/components/components.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import Home from './home/home';
3 | import Contact from './contact/contact';
4 | import ContactAddress from './contact/contact.address';
5 | import ContactForm from './contact/contact.form';
6 | import Github from './github/github';
7 | import Forms from './forms/forms';
8 | import New from './new/new';
9 |
10 | export default angular.module('app.components', [
11 | Contact.name,
12 | ContactAddress.name,
13 | ContactForm.name,
14 | Home.name,
15 | Github.name,
16 | Forms.name,
17 | New.name
18 | ]);
19 |
--------------------------------------------------------------------------------
/src/components/github/github.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import githubComponent from './github.component';
4 | import githubService from './github.service';
5 |
6 | let githubModule = angular.module('github', [
7 | uiRouter
8 | ])
9 |
10 | .config(($stateProvider) => {
11 | $stateProvider
12 | .state('github', {
13 | url: '/github',
14 | template: ''
15 | });
16 | })
17 |
18 | .component('github', githubComponent)
19 | .service('githubService', githubService);
20 |
21 | export default githubModule;
22 |
--------------------------------------------------------------------------------
/src/components/forms/forms.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import formsComponent from './forms.component';
4 | // order important: tv4 -> objectpath -> shemaForm -> shemaForm-bootstrap
5 | import 'tv4';
6 | import 'objectpath';
7 | import schemaForm from 'angular-schema-form';
8 | import 'script!angular-schema-form-bootstrap';
9 |
10 | let formsModule = angular.module('forms', [
11 | schemaForm.name,
12 | uiRouter
13 | ])
14 |
15 | .config(($stateProvider) => {
16 | $stateProvider
17 | .state('forms', {
18 | url: '/forms',
19 | template: ''
20 | });
21 | })
22 |
23 | .component('forms', formsComponent);
24 |
25 | export default formsModule;
26 |
--------------------------------------------------------------------------------
/src/components/github/github.service.js:
--------------------------------------------------------------------------------
1 | class GithubService {
2 |
3 | constructor($http) {
4 | this.$http = $http;
5 | }
6 |
7 | getItems(githubUsername) {
8 | var githubUrl = 'https://api.github.com';
9 | return this.$http({
10 | method: 'JSONP',
11 | url: githubUrl + '/users/' +
12 | githubUsername + '?callback=JSON_CALLBACK'
13 | }).success(function(data) {
14 | // this callback will be called asynchronously
15 | // when the response is available
16 | return data.data.toJSON();
17 | }).
18 | error(function(data, status) {
19 | // called asynchronously if an error occurs
20 | // or server returns response with an error status.
21 | alert(status);
22 | });
23 | }
24 |
25 | }
26 |
27 | export default GithubService;
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 4.4.5
4 | env:
5 | - NODE_ENV=prod
6 | - NODE_ENV=dev
7 | cache:
8 | directories:
9 | - node_modules
10 | dist: trusty
11 | addons:
12 | apt:
13 | sources:
14 | - google-chrome
15 | packages:
16 | - google-chrome-stable
17 | install:
18 | - npm install -g babel
19 | - npm install -g webpack
20 | - npm install -g webpack-dev-server
21 | - npm install -g eslint
22 | - npm install
23 | - sudo pip install -r requirements.txt
24 | before_script:
25 | - wget "http://chromedriver.storage.googleapis.com/2.30/chromedriver_linux64.zip"
26 | - unzip chromedriver_linux64.zip
27 | - sudo mv chromedriver /usr/local/bin
28 | - "export DISPLAY=:99.0"
29 | - "sh -e /etc/init.d/xvfb start"
30 | - sleep 2
31 | script:
32 | - npm run lint:travis
33 | - npm run test
34 | - pybot test.robot
35 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [angular],
3 | "extends": ["eslint:recommended", "angular"],
4 | "rules": {
5 | "indent": [
6 | 2,
7 | 2,
8 | { "SwitchCase": 1 }
9 | ],
10 | "quotes": [
11 | 2,
12 | "single"
13 | ],
14 | "linebreak-style": [
15 | 2,
16 | "unix"
17 | ],
18 | "semi": [
19 | 2,
20 | "always"
21 | ],
22 | "angular/di": [
23 | 2,
24 | "$inject"
25 | ]
26 | },
27 | "env": {
28 | "es6": true,
29 | "browser": true,
30 | "jasmine": true,
31 | "mocha": true,
32 | "amd": true
33 | },
34 | "ecmaFeatures": {
35 | "modules": true
36 | },
37 | "globals" : {
38 | "chai" : false,
39 | "describe" : false,
40 | "it" : false,
41 | "before" : false,
42 | "beforeEach" : false,
43 | "after" : false,
44 | "afterEach" : false,
45 | "inject" : false
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/components/contact/contact.form.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular';
2 | import uiRouter from 'angular-ui-router';
3 | import contactFormComponent from './contact.form.component';
4 | import 'angular-sanitize';
5 | require('script!tv4/tv4.js');
6 | require('script!objectpath/lib/ObjectPath');
7 | require('script!angular-schema-form/dist/schema-form');
8 | require('script!angular-schema-form/dist/bootstrap-decorator');
9 | // XXX: regular import do not work!
10 | // import schemaForm from 'angular-schema-form/dist/schema-form';
11 | // import 'angular-schema-form/dist/bootstrap-decorator';
12 |
13 | let contactFormModule = angular.module('contactForm', [
14 | uiRouter,
15 | 'schemaForm'
16 | ])
17 |
18 | .config(($stateProvider) => {
19 | $stateProvider
20 | .state('contact.form', {
21 | url: '/form',
22 | template: ''
23 | });
24 | })
25 |
26 | .component('contactform', contactFormComponent);
27 |
28 | export default contactFormModule;
29 |
--------------------------------------------------------------------------------
/src/components/forms/forms.controller.js:
--------------------------------------------------------------------------------
1 | import BaseFormController from './base.js';
2 |
3 | class FormController extends BaseFormController {
4 | constructor($scope) {
5 | super($scope);
6 | this.schema = {
7 | type: 'object',
8 | properties: {
9 | title: {
10 | type: 'string',
11 | enum: ['dr','jr','sir','mrs','mr','NaN','dj']
12 | },
13 | name: { type: 'string', minLength: 2, title: 'Name', description: 'Name or alias' },
14 | email: {
15 | 'title': 'Email',
16 | 'type': 'string',
17 | 'pattern': '^\\S+@\\S+$',
18 | 'description': 'Invalid email address'
19 | },
20 | comment: {
21 | 'title': 'Comment',
22 | 'type': 'string',
23 | 'maxLength': 20,
24 | 'validationMessage': 'Maximum length is 20 characters'
25 | }
26 | },
27 | 'required': [
28 | 'name'
29 | ]
30 | };
31 | }
32 | }
33 |
34 | export default FormController;
35 |
--------------------------------------------------------------------------------
/src/components/contact/contact.form.controller.js:
--------------------------------------------------------------------------------
1 | class ContactFormController {
2 | constructor($scope, $log) {
3 | this.name = 'Contact Us';
4 | this.model = {};
5 | this.schema = {
6 | type: 'object',
7 | properties: {
8 | name: { type: 'string', minLength: 2, title: 'Name', description: 'Name or alias' },
9 | title: {
10 | type: 'string',
11 | enum: ['dr','jr','sir','mrs','mr','NaN','dj']
12 | }
13 | },
14 | 'required': [
15 | 'name'
16 | ]
17 | };
18 | this.form = [
19 | '*',
20 | {
21 | type: 'submit',
22 | title: 'Save'
23 | }
24 | ];
25 |
26 | this.onSubmit = function(form) {
27 | // First we broadcast an event so all fields validate themselves
28 | $scope.$broadcast('schemaFormValidate');
29 |
30 | // Then we check if the form is valid
31 | if (form.$valid) {
32 | $log('form is valid');
33 | } else {
34 | $log('form is invalid');
35 | }
36 | };
37 | }
38 | }
39 |
40 | export default ContactFormController;
41 |
--------------------------------------------------------------------------------
/src/utils.spec.js:
--------------------------------------------------------------------------------
1 | import addField from './utils';
2 |
3 | // do not truncate diffs
4 | chai.config.truncateThreshold = 0;
5 |
6 |
7 | describe('Test addField', () => {
8 |
9 | it('add empty field', () => {
10 | let schema = {
11 | 'properties': {
12 | 'one': {'one': 'foo'}
13 | }
14 | };
15 | addField(schema, {});
16 | let expected = {
17 | 'properties': {
18 | 'one': {'one': 'foo'}
19 | }
20 | };
21 | // console.log(JSON.stringify(expected, null, 2));
22 | // console.log(JSON.stringify(schema, null, 2));
23 | expect(expected).to.deep.equal(schema);
24 | });
25 |
26 | it('add simple field', () => {
27 | let schema = {
28 | 'properties': {
29 | 'one': {'one': 'foo'}
30 | }
31 | };
32 | addField(schema, {'two': {'two': 'bar'}});
33 | let expected = {
34 | 'properties': {
35 | 'one': {'one': 'foo'},
36 | 'two': {'two': 'bar'}
37 | }
38 | };
39 | // console.log(JSON.stringify(expected, null, 2));
40 | // console.log(JSON.stringify(schema, null, 2));
41 | expect(expected).to.deep.equal(schema);
42 | });
43 |
44 | });
45 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.html:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/src/components/forms/base.js:
--------------------------------------------------------------------------------
1 | class BaseFormController {
2 | constructor($scope) {
3 | this.name = 'Form Component Syntax';
4 | this.model = {};
5 | this.schema = {
6 | type: 'object',
7 | properties: {},
8 | 'required': []
9 | };
10 | this.form = [
11 | '*',
12 | {
13 | type: 'submit',
14 | title: 'Save'
15 | }
16 | ];
17 |
18 | this.onSubmit = function(form) {
19 | // First we broadcast an event so all fields validate themselves
20 | $scope.$broadcast('schemaFormValidate');
21 |
22 | // Then we check if the form is valid
23 | var msg = [];
24 | if (form.$valid) {
25 | msg = [{
26 | 'type': 'help',
27 | 'helpvalue': 'Form submitted successfully
'
28 | }];
29 | this.form = msg.concat(this.form);
30 | } else {
31 | msg = [{
32 | 'type': 'help',
33 | 'helpvalue': 'Form is invalid
'
34 | }];
35 | this.form = msg.concat(this.form);
36 |
37 | }
38 | };
39 | }
40 | }
41 |
42 | export default BaseFormController;
43 |
--------------------------------------------------------------------------------
/spec.bundle.js:
--------------------------------------------------------------------------------
1 | /*
2 | * When testing with Webpack and ES6, we have to do some
3 | * preliminary setup. Because we are writing our tests also in ES6,
4 | * we must transpile those as well, which is handled inside
5 | * `karma.conf.js` via the `karma-webpack` plugin. This is the entry
6 | * file for the Webpack tests. Similarly to how Webpack creates a
7 | * `bundle.js` file for the compressed app source files, when we
8 | * run our tests, Webpack, likewise, compiles and bundles those tests here.
9 | */
10 |
11 | import angular from 'angular';
12 | // Built by the core Angular team for mocking dependencies
13 | import mocks from 'angular-mocks';
14 |
15 | // We use the context method on `require` which Webpack created
16 | // in order to signify which files we actually want to require or import.
17 | // Below, `context` will be a/an function/object with file names as keys.
18 | // Using that regex, we scan within `client/app` and target
19 | // all files ending with `.spec.js` and trace its path.
20 | // By passing in true, we permit this process to occur recursively.
21 | let context = require.context('./src', true, /\.spec\.js/);
22 |
23 | // Get all files, for each file, call the context function
24 | // that will require the file and load it here. Context will
25 | // loop and require those spec files here.
26 | context.keys().forEach(context);
27 |
--------------------------------------------------------------------------------
/src/common/navbar/navbar.spec.js:
--------------------------------------------------------------------------------
1 | import NavbarModule from './navbar';
2 | import NavbarController from './navbar.controller';
3 | import NavbarComponent from './navbar.component';
4 | import NavbarTemplate from './navbar.html';
5 |
6 | describe('Navbar', () => {
7 | let makeController;
8 |
9 | beforeEach(window.module(NavbarModule.name)); // eslint-disable-line
10 | beforeEach(inject(() => {
11 | makeController = () => {
12 | return new NavbarController();
13 | };
14 | }));
15 |
16 | describe('Module', () => {
17 | // top-level specs: i.e., routes, injection, naming
18 | });
19 |
20 | describe('Controller', () => {
21 | // controller specs
22 | it('has a name property', () => { // erase if removing this.name from the controller
23 | let controller = makeController();
24 | expect(controller).to.have.property('name');
25 | });
26 | });
27 |
28 | describe('Component', () => {
29 | // component/directive specs
30 | let component = NavbarComponent();
31 |
32 | it('includes the intended template',() => {
33 | expect(component.template).to.equal(NavbarTemplate);
34 | });
35 |
36 | it('uses `controllerAs` syntax', () => {
37 | expect(component).to.have.property('controllerAs');
38 | });
39 |
40 | it('invokes the right controller', () => {
41 | expect(component.controller).to.equal(NavbarController);
42 | });
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/src/common/hero/hero.spec.js:
--------------------------------------------------------------------------------
1 | import HeroModule from './hero';
2 | import HeroController from './hero.controller';
3 | import HeroComponent from './hero.component';
4 | import HeroTemplate from './hero.jade';
5 |
6 | describe('Hero', () => {
7 | let makeController;
8 |
9 | beforeEach(window.module(HeroModule.name)); // eslint-disable-line
10 | beforeEach(inject(() => {
11 | makeController = () => {
12 | return new HeroController();
13 | };
14 | }));
15 |
16 | describe('Module', () => {
17 | // top-level specs: i.e., routes, injection, naming
18 | });
19 |
20 | describe('Controller', () => {
21 | // controller specs
22 | it('has a name property', () => { // erase if removing this.name from the controller
23 | let controller = makeController();
24 | expect(controller).to.have.property('name');
25 | });
26 | });
27 |
28 | describe('Template', () => {
29 | // template specs
30 | // tip: use regex to ensure correct bindings are used e.g., {{ }}
31 | it('has name in template', () => {
32 | expect(HeroTemplate).to.match(/{{\s?vm\.name\s?}}/g);
33 | });
34 | });
35 |
36 | describe('Component', () => {
37 | // component/directive specs
38 | let component = HeroComponent();
39 |
40 | it('includes the intended template',() => {
41 | expect(component.template).to.equal(HeroTemplate);
42 | });
43 |
44 | it('uses `controllerAs` syntax', () => {
45 | expect(component).to.have.property('controllerAs');
46 | });
47 |
48 | it('invokes the right controller', () => {
49 | expect(component.controller).to.equal(HeroController);
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/test.robot:
--------------------------------------------------------------------------------
1 | *** Variables ***
2 |
3 | ${HOSTNAME} 127.0.0.1
4 | ${PORT} 3000
5 | ${SERVER} http://${HOSTNAME}:${PORT}/
6 | ${BROWSER} chrome
7 |
8 |
9 | *** Settings ***
10 |
11 | Documentation Webpack Starter Angular Acceptance Tests
12 | Library Process
13 | Library DebugLibrary
14 | Library Selenium2Library timeout=10 implicit_wait=0
15 | Suite Setup Test Setup
16 | Suite Teardown Test Teardown
17 |
18 |
19 | *** Keywords ***
20 |
21 | Test Setup
22 | ${webpack-dev-server}= Start Process node_modules/webpack-dev-server/bin/webpack-dev-server.js --bail --inline --port 3000 --content-base ${CURDIR}/dist cwd=${CURDIR} shell=true
23 | Set Suite Variable ${WEBPACK-DEV-SERVER} ${webpack-dev-server}
24 | Sleep 5s
25 | Open Browser ${SERVER} ${BROWSER}
26 | Set Window Size 1280 1024
27 |
28 | Test Teardown
29 | Close Browser
30 | Log ${WEBPACK-DEV-SERVER}
31 | Terminate Process ${WEBPACK-DEV-SERVER}
32 |
33 |
34 | *** Test Cases ***
35 |
36 | Front Page
37 | Go To ${SERVER}
38 | Wait until page contains Webpack Starter
39 | Page Should Contain Webpack Starter
40 |
41 | Forms
42 | Go To ${SERVER}
43 | Wait until page contains Webpack Starter
44 | Click Link Forms
45 | Wait until page contains Forms
46 | Page should contain element name
47 | Page should contain element title
48 | Input Text name John Doe
49 | Select From List By Label title mr
50 | Input Text email john@doe.com
51 | Input Text comment Hi World
52 | Click Element css=.btn-primary
53 | Wait until page contains element css=.alert
54 | Page should contain Form submitted successfully
55 |
56 |
57 |
--------------------------------------------------------------------------------
/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 |
5 |
6 | module.exports = {
7 | entry: './src/app.js',
8 | output: {
9 | path: path.join(__dirname, '..', 'dist'),
10 | filename: 'bundle.js'
11 | },
12 | plugins: [
13 | new HtmlWebpackPlugin({
14 | title: 'Webpack Starter Angular - kitconcept',
15 | template: 'src/index.html',
16 | minify: {
17 | collapseWhitespace: true,
18 | removeComments: true,
19 | removeRedundantAttributes: true,
20 | removeScriptTypeAttributes: true,
21 | removeStyleLinkTypeAttributes: true
22 | }
23 | })
24 | ],
25 | module: {
26 | loaders: [
27 | { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
28 | { test: /\.css$/, loader: 'style-loader!css-loader' },
29 | { test: /\.scss$/, loaders: ['style', 'css?sourceMap', 'sass?sourceMap']},
30 | { test: /\.html$/, loader: 'raw' },
31 | { test: /\.jade$/, loader: 'jade-loader' },
32 | // inline base64 URLs for <=8k images, direct URLs for the rest
33 | { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'},
34 | // helps to load bootstrap's css.
35 | { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
36 | loader: 'url?limit=10000&minetype=application/font-woff' },
37 | { test: /\.woff2$/,
38 | loader: 'url?limit=10000&minetype=application/font-woff' },
39 | { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
40 | loader: 'url?limit=10000&minetype=application/octet-stream' },
41 | { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
42 | loader: 'file' },
43 | { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
44 | loader: 'url?limit=10000&minetype=image/svg+xml' }
45 | ]
46 | },
47 | devtool: 'eval-source-map'
48 | };
49 |
--------------------------------------------------------------------------------
/src/components/forms/forms.spec.js:
--------------------------------------------------------------------------------
1 | import FormsModule from './forms';
2 | import FormsController from './forms.controller';
3 | import FormsComponent from './forms.component';
4 | import FormsTemplate from './forms.html';
5 |
6 | describe('Forms', () => {
7 | let makeController;
8 |
9 | beforeEach(window.module(FormsModule.name)); // eslint-disable-line
10 | beforeEach(inject(() => {
11 | makeController = () => {
12 | return new FormsController();
13 | };
14 | }));
15 |
16 | describe('Module', () => {
17 | // top-level specs: i.e., routes, injection, naming
18 | });
19 |
20 | describe('Controller', () => {
21 | // controller specs
22 | it('has a name/from/schema/model property', () => { // erase if removing this.name from the controller
23 | let controller = makeController();
24 | expect(controller).to.have.property('name');
25 | expect(controller).to.have.property('form');
26 | expect(controller).to.have.property('schema');
27 | expect(controller).to.have.property('model');
28 | });
29 | });
30 |
31 | describe('Template', () => {
32 | // template specs
33 | // tip: use regex to ensure correct bindings are used e.g., {{ }}
34 | it('has schema/form/model in template', () => {
35 | expect(FormsTemplate).to.match(/\s?vm\.schema\s?/g);
36 | expect(FormsTemplate).to.match(/\s?vm\.form\s?/g);
37 | expect(FormsTemplate).to.match(/\s?vm\.model\s?/g);
38 | });
39 | });
40 |
41 |
42 | describe('Component', () => {
43 | // component/directive specs
44 | let component = FormsComponent;
45 |
46 | it('includes the intended template',() => {
47 | expect(component.template).to.equal(FormsTemplate);
48 | });
49 |
50 | it('uses `controllerAs` syntax', () => {
51 | expect(component).to.have.property('controllerAs');
52 | });
53 |
54 | it('invokes the right controller', () => {
55 | expect(component.controller).to.equal(FormsController);
56 | });
57 | });
58 |
59 | });
60 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function (config) {
2 |
3 | var configuration = {
4 | // base path used to resolve all patterns
5 | basePath: '',
6 |
7 | // frameworks to use
8 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
9 | frameworks: ['mocha', 'chai'],
10 |
11 | // list of files/patterns to load in the browser
12 | files: [{ pattern: 'spec.bundle.js', watched: false }],
13 |
14 | // files to exclude
15 | exclude: [],
16 |
17 | // preprocess matching files before serving them to the browser
18 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
19 | preprocessors: { 'spec.bundle.js': ['webpack', 'sourcemap'] },
20 |
21 | webpack: {
22 | devtool: 'inline-source-map',
23 | module: {
24 | loaders: [
25 | { test: /\.js/, exclude: [/app\/lib/, /node_modules/], loader: 'babel' },
26 | { test: /\.html/, loader: 'raw' },
27 | { test: /\.jade$/, loader: 'jade-loader' },
28 | { test: /\.styl$/, loader: 'style!css!stylus' },
29 | { test: /\.css$/, loader: 'style!css' }
30 | ]
31 | }
32 | },
33 |
34 | webpackServer: {
35 | noInfo: true // prevent console spamming when running in Karma!
36 | },
37 |
38 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
39 | reporters: ['mocha'],
40 |
41 | // web server port
42 | port: 9876,
43 |
44 | // enable colors in the output
45 | colors: true,
46 |
47 | // level of logging
48 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
49 | logLevel: config.LOG_INFO,
50 |
51 | // toggle whether to watch files and rerun tests upon incurring changes
52 | autoWatch: true,
53 |
54 | // start these browsers
55 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
56 | browsers: ['Chrome'],
57 |
58 | customLaunchers: {
59 | Chrome_travis_ci: {
60 | base: 'Chrome',
61 | flags: ['--no-sandbox']
62 | }
63 | },
64 |
65 | // if true, Karma runs tests once and exits
66 | singleRun: true
67 | };
68 |
69 | if(process.env.TRAVIS){
70 | configuration.browsers = ['Chrome_travis_ci'];
71 | // configuration.reporters = configuration.reporters.concat(['coverage', 'coveralls']);
72 | // configuration.coverageReporter = {
73 | // type : 'lcovonly',
74 | // dir : 'coverage/'
75 | // };
76 | }
77 |
78 | config.set(configuration);
79 |
80 | };
81 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack-starter-angular",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "keywords": [
7 | "bundle",
8 | "bundling",
9 | "webpack",
10 | "npm",
11 | "angular"
12 | ],
13 | "author": "Timo Stollenwerk",
14 | "license": "MIT",
15 | "babel": {
16 | "presets": [
17 | "es2015"
18 | ]
19 | },
20 | "devDependencies": {
21 | "angular-mocks": "1.5.8",
22 | "babel-core": "6.3.26",
23 | "babel-loader": "6.1.0",
24 | "babel-polyfill": "6.3.14",
25 | "babel-preset-es2015": "6.1.18",
26 | "chai": "^4.1.2",
27 | "css-loader": "~0.21.0",
28 | "eslint": "1.7.3",
29 | "eslint-config-angular": "0.4.0",
30 | "eslint-plugin-angular": "0.12.0",
31 | "file-loader": "~0.8.4",
32 | "html-webpack-plugin": "~1.7.0",
33 | "jade": "~1.11.0",
34 | "jade-loader": "~0.7.1",
35 | "karma": "1.2.0",
36 | "karma-chai": "0.1.0",
37 | "karma-chrome-launcher": "2.0.0",
38 | "karma-mocha": "1.1.1",
39 | "karma-mocha-reporter": "2.1.0",
40 | "karma-sourcemap-loader": "0.3.7",
41 | "karma-webpack": "1.8.0",
42 | "mocha": "~2.3.0",
43 | "node-sass": "~3.3.3",
44 | "raw-loader": "~0.5.1",
45 | "rimraf": "~2.5.2",
46 | "sass-loader": "~3.0.0",
47 | "script-loader": "~0.6.1",
48 | "style-loader": "~0.13.0",
49 | "url-loader": "~0.5.6",
50 | "webpack": "~1.12.14",
51 | "webpack-dev-server": "1.12.1",
52 | "webpack-md5-hash": "0.0.5",
53 | "webpack-merge": "~0.14.0"
54 | },
55 | "dependencies": {
56 | "angular": "1.5.8",
57 | "angular-sanitize": "1.5.8",
58 | "angular-schema-form": "0.8.13",
59 | "angular-schema-form-bootstrap": "0.2.0",
60 | "angular-ui-bootstrap": "1.1.2",
61 | "angular-ui-router": "0.2.18",
62 | "bootstrap": "3.3.7",
63 | "jquery": "2.2.4",
64 | "lodash": "4.6.1",
65 | "objectpath": "1.2.1",
66 | "tv4": "1.2.7"
67 | },
68 | "scripts": {
69 | "analyze": "webpack --json | webpack-bundle-size-analyzer",
70 | "clean": "npm cache clean && rimraf -- node_modules doc typings coverage dist",
71 | "build": "export NODE_ENV=dev && webpack",
72 | "build:production": "export NODE_ENV=prod && webpack -p",
73 | "lint": "eslint src/ || true",
74 | "lint:travis": "eslint src/",
75 | "start": "node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --port 3000 --content-base dist/",
76 | "test": "karma start",
77 | "test:debug": "karma start karma.conf.js --log-level=debug --single-run=False",
78 | "test:watch": "karma start karma.conf.js --auto-watch=true --single-run=False"
79 | },
80 | "repository": "git@github.com:kitconcept/webpack-starter-angular.git"
81 | }
82 |
--------------------------------------------------------------------------------
/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpackMerge = require('webpack-merge');
3 | const commonConfig = require('./webpack.common.js');
4 |
5 | // webpack plugins
6 | const WebpackMd5Hash = require('webpack-md5-hash');
7 | const DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
8 | const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
9 |
10 |
11 | module.exports = webpackMerge(commonConfig, {
12 |
13 | /**
14 | * Disable debug mode for production.
15 | *
16 | * See: http://webpack.github.io/docs/configuration.html#debug
17 | */
18 | debug: false,
19 |
20 | /**
21 | * Developer tool to enhance debugging.
22 | *
23 | * The 'source-map' settings is meant to be used in production only. It
24 | * splits the source map in a separate file and it is slow to compute.
25 | *
26 | * See: http://webpack.github.io/docs/configuration.html#devtool
27 | * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
28 | */
29 | devtool: 'source-map',
30 |
31 |
32 | /**
33 | * Options affecting the output of the compilation.
34 | *
35 | * See: http://webpack.github.io/docs/configuration.html#output
36 | */
37 | output: {
38 |
39 | /**
40 | * The output directory as absolute path (required).
41 | *
42 | * See: http://webpack.github.io/docs/configuration.html#output-path
43 | */
44 | path: path.join(__dirname, '..', 'dist'),
45 |
46 | /**
47 | * Specifies the name of each output file on disk.
48 | * IMPORTANT: You must not specify an absolute path here!
49 | *
50 | * See: http://webpack.github.io/docs/configuration.html#output-filename
51 | */
52 | filename: '[name].[chunkhash].bundle.js',
53 |
54 | /**
55 | * The filename of the SourceMaps for the JavaScript files.
56 | * They are inside the output.path directory.
57 | *
58 | * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
59 | */
60 | sourceMapFilename: '[name].[chunkhash].bundle.map',
61 |
62 | /**
63 | * The filename of non-entry chunks as relative path
64 | * inside the output.path directory.
65 | *
66 | * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
67 | */
68 | chunkFilename: '[id].[chunkhash].chunk.js'
69 |
70 | },
71 |
72 | /**
73 | * Add additional plugins to the compiler.
74 | *
75 | * See: http://webpack.github.io/docs/configuration.html#plugins
76 | */
77 | plugins: [
78 |
79 | /**
80 | * Plugin: WebpackMd5Hash
81 | * Description: Plugin to replace a standard webpack chunkhash with md5.
82 | *
83 | * See: https://www.npmjs.com/package/webpack-md5-hash
84 | */
85 | new WebpackMd5Hash(),
86 |
87 | /**
88 | * Plugin: DedupePlugin
89 | * Description: Prevents the inclusion of duplicate code into your bundle
90 | * and instead applies a copy of the function at runtime.
91 | *
92 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
93 | * See: https://github.com/webpack/docs/wiki/optimization#deduplication
94 | */
95 | new DedupePlugin(),
96 |
97 | /**
98 | * Plugin: UglifyJsPlugin
99 | * Description: Minimize all JavaScript output of chunks.
100 | * Loaders are switched into minimizing mode.
101 | *
102 | * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
103 | */
104 | // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
105 | // new UglifyJsPlugin({
106 | // // beautify: true, //debug
107 | // // mangle: false, //debug
108 | // // dead_code: false, //debug
109 | // // unused: false, //debug
110 | // // deadCode: false, //debug
111 | // // compress: {
112 | // // screw_ie8: true,
113 | // // keep_fnames: true,
114 | // // drop_debugger: false,
115 | // // dead_code: false,
116 | // // unused: false
117 | // // }, // debug
118 | // // comments: true, //debug
119 |
120 |
121 | // // beautify: false, //prod
122 | // // mangle: { screw_ie8 : true }, //prod
123 | // // compress: { screw_ie8: true }, //prod
124 | // // comments: false //prod
125 | // })
126 |
127 | ]
128 |
129 | });
130 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | .. image:: https://travis-ci.org/kitconcept/webpack-starter-angular.svg?branch=master
2 | :target: https://travis-ci.org/kitconcept/webpack-starter-angular
3 |
4 |
5 | Webpack Starter Angular
6 | =======================
7 |
8 | Stack
9 | -----
10 |
11 | - NPM
12 | - Webpack
13 | - Angular 1.5
14 | - Angular UI Router (with self-registering components)
15 | - ES 6 / Babel (Module Loading)
16 | - SASS
17 | - Jade
18 | - Tests
19 | - Karma (Test Runner, http://karma-runner.github.io/)
20 | - Mocha (Test Framework, http://mochajs.org/)
21 | - Chai (BDD/TSS assertion library, http://chaijs.com/)
22 |
23 |
24 | Requirements
25 | ------------
26 |
27 | ToDo:
28 |
29 | - SASS variables
30 | - Angular New Router -> http://www.heise.de/developer/artikel/AngularJS-1-x-und-2-0-mit-dem-Component-Router-parallel-betreiben-2679282.html
31 |
32 | Done:
33 |
34 | - DONE: ES 6 with Angular 1.4
35 | - DONE: Bundling
36 | - DONE: Delivering static files separately -> Possible via https://webpack.github.io/docs/stylesheets.html#separate-css-bundle
37 | - DONE: Splitting large files -> Possible via https://webpack.github.io/docs/code-splitting.html
38 | - DONE: SASS support
39 | - DONE: Angular UI Router
40 | - DONE: Self-registering components
41 | - DONE: Jade support
42 |
43 | Planed:
44 |
45 | - ES7 Decorators (@Component())
46 | - Typescript?
47 |
48 |
49 | Prerequisits
50 | ------------
51 |
52 | Install a few dependencies globally::
53 |
54 | $ npm install -g babel
55 | $ npm install -g webpack
56 | $ npm install -g webpack-dev-server
57 | $ npm install -g eslint
58 |
59 |
60 | Development
61 | -----------
62 |
63 | Create a JS bundle with Webpack::
64 |
65 | $ npm run build
66 |
67 | Start the Webpack development server on 'localhost:3000'::
68 |
69 | $ npm run start
70 |
71 | Run tests::
72 |
73 | $ npm run test
74 |
75 | Linting::
76 |
77 | $ npm run lint
78 |
79 |
80 | HTML Webpack Plugin
81 | -------------------
82 |
83 | Installation::
84 |
85 | $ npm install html-webpack-plugin --save-dev
86 |
87 | webpack.config.js::
88 |
89 | var HtmlWebpackPlugin = require('html-webpack-plugin')
90 |
91 | module.exports = {
92 | ...
93 | plugins: [
94 | new HtmlWebpackPlugin({
95 | title: 'Website Starter',
96 | template: 'src/index.html',
97 | minify: {
98 | collapseWhitespace: true,
99 | removeComments: true,
100 | removeRedundantAttributes: true,
101 | removeScriptTypeAttributes: true,
102 | removeStyleLinkTypeAttributes: true
103 | }
104 | })
105 | ],
106 | }
107 |
108 |
109 | ES 6 Imports
110 | ------------
111 |
112 | Default import::
113 |
114 | import localName from 'src/my_lib';
115 |
116 | Namespace import: imports the module as an object (with one property per named export)::
117 |
118 | import * as my_lib from 'src/my_lib';
119 |
120 | Named imports::
121 |
122 | import { name1, name2 } from 'src/my_lib';
123 |
124 | Renaming named imports::
125 |
126 | // Renaming: import `name1` as `localName1`
127 | import { name1 as localName1, name2 } from 'src/my_lib';
128 | Empty import: only loads the module, doesn’t import anything. The first such import in a program executes the body of the module.
129 | import 'src/my_lib';
130 |
131 | Source: http://exploringjs.com/es6/ch_modules.html
132 |
133 | Imports for broken modules::
134 |
135 | require('script!objectpath/lib/ObjectPath');
136 |
137 | Source: https://webpack.github.io/docs/shimming-modules.html
138 |
139 |
140 | SASS Loader
141 | -----------
142 |
143 | Installation::
144 |
145 | $ npm install sass-loader --save-dev
146 |
147 | Webpack Configuration (webpack.config.js)::
148 |
149 | module.exports = {
150 | ...
151 | module: {
152 | loaders: [
153 | ...
154 | { test: /\.scss$/, loaders: ["style", "css?sourceMap", "sass?sourceMap"]},
155 | ]
156 | },
157 | devtool: 'source-map'
158 | }
159 |
160 | Javascript::
161 |
162 | import Styles from './styles.scss';
163 |
164 | SASS (styles.scss)::
165 |
166 | body {
167 | padding-top: 80px;
168 | }
169 |
170 |
171 | Jade Loader
172 | -----------
173 |
174 | Installation::
175 |
176 | $ npm install jade-loader --save-dev
177 |
178 | Webpack Configuration (webpack.config.js)::
179 |
180 | module.exports = {
181 | ...
182 | module: {
183 | loaders: [
184 | ...
185 | { test: /\.jade$/, loader: 'jade-loader' },
186 | ]
187 | }
188 | }
189 |
190 | Javascript::
191 |
192 | import template from './hero.jade';
193 |
194 | Jade (hero.jade)::
195 |
196 | div.jumbotron
197 | h1 Angular, ES6, Webpack Starter!
198 | h3 You can find my template inside {{ vm.name }}.html
199 |
200 |
201 | Angular Schema Form
202 | -------------------
203 |
204 | Installation::
205 |
206 | $ npm install angular-schema-form --save
207 | $ npm install objectpath --save
208 | $ npm install tv4 --save
209 | $ npm install angular-sanitize --save
210 |
211 | Javascript::
212 |
213 | import 'angular-sanitize';
214 | require('script!tv4/tv4.js');
215 | require('script!objectpath/lib/ObjectPath');
216 | require('script!angular-schema-form/dist/schema-form');
217 | require('script!angular-schema-form/dist/bootstrap-decorator');
218 |
219 | let formsModule = angular.module('forms', [
220 | uiRouter,
221 | 'schemaForm'
222 | ])
223 |
224 | ...
225 |
226 | Controller::
227 |
228 | class FormsController {
229 | constructor() {
230 | this.name = 'Contact Us';
231 | this.model = {};
232 | this.schema = {
233 | type: 'object',
234 | properties: {
235 | name: { type: 'string', minLength: 2, title: 'Name', description: 'Name or alias' },
236 | title: {
237 | type: 'string',
238 | enum: ['dr','jr','sir','mrs','mr','NaN','dj']
239 | }
240 | },
241 | 'required': [
242 | 'name'
243 | ]
244 | };
245 | this.form = [
246 | '*',
247 | {
248 | type: 'submit',
249 | title: 'Save'
250 | }
251 | ];
252 | }
253 | }
254 |
255 | export default FormsController;
256 |
257 |
258 | Service
259 | -------
260 |
261 | ...
262 |
263 | Travis CI
264 | ---------
265 |
266 | - Enable Travis for repository
267 |
268 | .travis.yml::
269 |
270 | language: node_js
271 | node_js:
272 | - 4.2.1
273 | cache:
274 | directories:
275 | - node_modules
276 | before_install:
277 | - export CHROME_BIN=chromium-browser
278 | - export DISPLAY=:99.0
279 | - sh -e /etc/init.d/xvfb start
280 | install:
281 | - npm install -g babel
282 | - npm install -g webpack
283 | - npm install -g webpack-dev-server
284 | - npm install -g eslint
285 | - npm install
286 | script:
287 | - npm run test
288 | notifications:
289 | email:
290 | - stollenwerk@kitconcept.com
291 |
292 | webpack.config.js::
293 |
294 | ...
295 |
296 | ESLint
297 | ------
298 |
299 | Installation::
300 |
301 | $ npm install eslint -g
302 |
303 | Sublime Text 3 Installation:
304 |
305 | https://github.com/roadhump/SublimeLinter-eslint
306 |
307 | Sources
308 | -------
309 |
310 | - Webpack: https://github.com/faassen/bundle_example
311 | - Angular: https://github.com/angular-class/NG6-starter
312 | - Angular: http://angular-tips.com/blog/2015/06/using-angular-1-dot-x-with-es6-and-webpack/
313 | - Webpack and Babel6: https://github.com/rauschma/webpack-babel-demo
314 |
315 |
--------------------------------------------------------------------------------