├── src ├── components │ ├── test.styl │ └── test.component.ts ├── typings │ └── webpack.d.ts ├── app.component.ts ├── app.routes.ts ├── index.html ├── vendor.ts ├── bootstrap.ts ├── app.component.spec.ts └── ie-shims │ └── ie-shims.js ├── jsconfig.json ├── .gitignore ├── test └── app.e2e.js ├── tsconfig.json ├── protractor.conf.js ├── karma.entry.ts ├── typings.json ├── tslint.json ├── .editorconfig ├── README.md ├── webpack.config.js ├── package.json └── karma.conf.js /src/components/test.styl: -------------------------------------------------------------------------------- 1 | :host 2 | color #333 -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6" 4 | } 5 | } -------------------------------------------------------------------------------- /src/typings/webpack.d.ts: -------------------------------------------------------------------------------- 1 | declare let WEBPACK_ENV: string; 2 | declare let System: { 3 | import: Function 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | 3 | node_modules 4 | 5 | dist 6 | 7 | coverage 8 | 9 | typings 10 | 11 | .vscode 12 | .idea 13 | -------------------------------------------------------------------------------- /src/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'sg-app', 5 | template: ` 6 | 7 | ` 8 | }) 9 | export class AppComponent {} 10 | -------------------------------------------------------------------------------- /test/app.e2e.js: -------------------------------------------------------------------------------- 1 | describe('App', () => { 2 | 3 | beforeEach(() => { 4 | browser.get('/'); 5 | }); 6 | 7 | it('should have proper title', () => { 8 | expect(browser.getTitle()).toEqual('Angular 2'); 9 | }); 10 | 11 | }); 12 | -------------------------------------------------------------------------------- /src/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | import { TestComponent } from './components/test.component'; 3 | 4 | export const AppRoutes: Routes = [ 5 | { path: '', component: TestComponent }, 6 | { path: 'test', component: TestComponent } 7 | ]; 8 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/test.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'sg-test', 5 | template: 'Hello from component: {{ test }}', 6 | styles: [require('./test.styl').toString()] 7 | }) 8 | export class TestComponent { 9 | public test: string = 'test'; 10 | constructor() {} 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildOnSave": false, 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "target": "ES5", 6 | "module": "commonjs", 7 | "inlineSourceMap": true, 8 | "sourceMap": false, 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "removeComments": false, 12 | "noImplicitAny": true, 13 | "types": ["node", "jasmine"] 14 | }, 15 | "exclude": [ 16 | "node_modules" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/vendor.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // local shims 4 | import './ie-shims/ie-shims'; 5 | 6 | // polyfills 7 | import 'core-js'; 8 | 9 | // (these modules are what is in 'angular2/bundles/angular2-polyfills' so don't use that here) 10 | import 'reflect-metadata'; 11 | 12 | require('zone.js/dist/zone'); 13 | 14 | if (WEBPACK_ENV !== 'production') { 15 | require('zone.js/dist/long-stack-trace-zone'); 16 | } 17 | 18 | // Angular 2 Deps 19 | import 'rxjs/Rx'; 20 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | baseUrl: 'http://localhost:8080/', 3 | 4 | allScriptsTimeout: 10000, 5 | 6 | framework: 'jasmine', 7 | 8 | jasmineNodeOpts: { 9 | defaultTimeoutInterval: 60000, 10 | showTiming: true 11 | }, 12 | 13 | capabilities: { 14 | 'browserName': 'chrome', 15 | 'chromeOptions': { 16 | 'args': ['show-fps-counter=true'] 17 | } 18 | }, 19 | 20 | specs: [ 21 | 'test/**/*.e2e.js' 22 | ], 23 | 24 | onPrepare: function() { 25 | require('babel-core/register'); 26 | browser.ignoreSynchronization = true; 27 | } 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /karma.entry.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import 'zone.js/dist/zone'; 3 | import 'zone.js/dist/sync-test'; 4 | import 'zone.js/dist/async-test'; 5 | import 'zone.js/dist/fake-async-test'; 6 | import 'zone.js/dist/proxy'; 7 | import 'zone.js/dist/jasmine-patch'; 8 | 9 | const testContext = (<{ context?: Function }>require).context('./src', true, /\.spec\.ts/); 10 | testContext.keys().forEach(testContext); 11 | 12 | const coverageContext = (<{ context?: Function }>require).context( 13 | './src', 14 | true, 15 | /^(?=(?!.*[.]spec\.ts))(?=(?!.*[.]d\.ts))(?=(?!\.\/bootstrap\.ts$))(?=(?!\.\/vendor\.ts$)).*\.ts$/ 16 | ); 17 | coverageContext.keys().forEach(coverageContext); 18 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": {}, 3 | "globalDependencies": { 4 | "angular-protractor": "github:DefinitelyTyped/DefinitelyTyped/angular-protractor/angular-protractor.d.ts#17fa1e5f269189f7f8e0f53f8c443e6c2eac562c", 5 | "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd", 6 | "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#bc92442c075929849ec41d28ab618892ba493504", 7 | "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#aee0039a2d6686ec78352125010ebb38a7a7d743", 8 | "selenium-webdriver": "github:DefinitelyTyped/DefinitelyTyped/selenium-webdriver/selenium-webdriver.d.ts#a83677ed13add14c2ab06c7325d182d0ba2784ea" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "directive-selector": [true, "attribute", "sg", "camelCase"], 7 | "component-selector": [true, "element", "sg", "kebab-case"], 8 | "use-input-property-decorator": true, 9 | "use-output-property-decorator": true, 10 | "use-host-property-decorator": true, 11 | "no-attribute-parameter-decorator": true, 12 | "no-input-rename": true, 13 | "no-output-rename": true, 14 | "no-forward-ref" :true, 15 | "use-life-cycle-interface": true, 16 | "use-pipe-transform-interface": true, 17 | "pipe-naming": [true, "camelCase", "sg"], 18 | "component-class-suffix": true, 19 | "directive-class-suffix": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.js] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.hbs] 21 | insert_final_newline = false 22 | indent_style = space 23 | indent_size = 2 24 | 25 | [*.css] 26 | indent_style = space 27 | indent_size = 2 28 | 29 | [*.styl] 30 | indent_style = space 31 | indent_size = 2 32 | 33 | [*.html] 34 | indent_style = space 35 | indent_size = 2 36 | 37 | [*.{diff,md}] 38 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | 3 | if (WEBPACK_ENV === 'production') { 4 | enableProdMode(); 5 | } 6 | 7 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 8 | 9 | import { NgModule } from '@angular/core'; 10 | import { RouterModule } from '@angular/router'; 11 | import { BrowserModule } from '@angular/platform-browser'; 12 | 13 | import { AppComponent } from './app.component'; 14 | import { AppRoutes } from './app.routes'; 15 | import { TestComponent } from './components/test.component'; 16 | 17 | @NgModule({ 18 | declarations: [ 19 | AppComponent, 20 | TestComponent, 21 | ], 22 | imports: [ 23 | BrowserModule, 24 | RouterModule.forRoot(AppRoutes), 25 | ], 26 | bootstrap: [ 27 | AppComponent 28 | ], 29 | }) 30 | export class AppModule {} 31 | 32 | platformBrowserDynamic().bootstrapModule(AppModule); 33 | -------------------------------------------------------------------------------- /src/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AppComponent } from './app.component'; 2 | 3 | import { RouterModule } from '@angular/router'; 4 | import { async, TestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | import { APP_BASE_HREF } from '@angular/common'; 7 | 8 | TestBed.initTestEnvironment( 9 | BrowserDynamicTestingModule, 10 | platformBrowserDynamicTesting() 11 | ); 12 | 13 | describe('App', () => { 14 | 15 | beforeEach(() => { 16 | TestBed.configureTestingModule({ 17 | declarations: [ 18 | AppComponent 19 | ], 20 | imports: [ 21 | RouterModule.forRoot([]) 22 | ], 23 | providers: [{ provide: APP_BASE_HREF, useValue: '/' }] 24 | }); 25 | }); 26 | 27 | it('should be able to test', async(() => { 28 | const fixture = TestBed.createComponent(AppComponent); 29 | fixture.whenStable().then(() => { 30 | expect(true).toEqual(true); 31 | }); 32 | })); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular2-webpack2 2 | 3 | Angular 2 Webpack 2 minimal starter. Includes both unit and e2e tests. 4 | 5 | ## Project scripts 6 | 7 | ### Install packages 8 | The only think you need when when you have prerequisites installed is to run: 9 | ``` 10 | npm install 11 | ``` 12 | 13 | ### Custom scripts 14 | 15 | Running in dev mode: 16 | ``` 17 | npm run dev 18 | ``` 19 | 20 | Running prod build: 21 | ``` 22 | npm run build 23 | ``` 24 | 25 | Running unit tests: 26 | ``` 27 | npm test 28 | ``` 29 | 30 | Running e2e tests: 31 | ``` 32 | npm run e2e 33 | ``` 34 | 35 | ## Prerequisites 36 | 37 | ### NodeJS with npm 38 | 39 | #### Mac OS X 40 | If you don't have [Brew](http://brew.sh) it is high time to install it: 41 | ``` 42 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 43 | ``` 44 | 45 | Then just run: 46 | ``` 47 | brew install node 48 | ``` 49 | 50 | #### Debian and Ubuntu 51 | ``` 52 | sudo apt-get install nodejs 53 | ``` 54 | 55 | #### Windows 56 | 57 | [Windows NodeJS Installer](http://nodejs.org/#download) 58 | 59 | 60 | ### Note for Windows users: install Python 2 (to run tests) 61 | 62 | This one is built-in when using Mac OS X and Linux. When you run Windows you have to care of it by yourself. Here's [offical Python website](https://www.python.org/downloads/) 63 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | 6 | const config = { 7 | entry: { 8 | 'vendor': './src/vendor', 9 | 'app': './src/bootstrap' 10 | }, 11 | output: { 12 | path: path.resolve(__dirname, './dist'), 13 | filename: '[name].js' 14 | }, 15 | resolve: { 16 | extensions: ['.ts', '.es6', '.js', '.json'] 17 | }, 18 | module: { 19 | rules: [ 20 | { enforce: 'pre', test: /\.ts$/, exclude: /node_modules/, loader: 'tslint-loader' }, 21 | { test: /\.ts$/, exclude: /node_modules/, loader: 'ts-loader' }, 22 | { test: /\.json$/, loader: 'json-loader' }, 23 | { test: /\.html/, loader: 'html-loader?minimize=false' }, 24 | { test: /\.styl$/, loader: 'css-loader!stylus-loader' }, 25 | { test: /\.css$/, loader: 'style-loader!css-loader' }, 26 | { test: /\.(gif|png|jpe?g)$/i, loader: 'file-loader?name=dist/images/[name].[ext]' }, 27 | { test: /\.woff2?$/, loader: 'url-loader?name=dist/fonts/[name].[ext]&limit=10000&mimetype=application/font-woff' }, 28 | { test: /\.(ttf|eot|svg)$/, loader: 'file-loader?name=dist/fonts/[name].[ext]' } 29 | ] 30 | }, 31 | plugins: [ 32 | // Fixes Angular 2 error 33 | new webpack.ContextReplacementPlugin( 34 | /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, 35 | __dirname 36 | ) 37 | ] 38 | }; 39 | 40 | if (!(process.env.WEBPACK_ENV === 'production')) { 41 | config.devtool = 'source-map'; 42 | config.plugins = config.plugins.concat([ 43 | new webpack.DefinePlugin({ 44 | 'WEBPACK_ENV': '"dev"' 45 | }) 46 | ]) 47 | } else { 48 | config.devtool = 'hidden-source-map'; 49 | config.plugins = config.plugins.concat([ 50 | new webpack.optimize.UglifyJsPlugin({ 51 | compress: { 52 | screw_ie8: true, 53 | warnings: false 54 | }, 55 | comments: false, 56 | sourceMap: true 57 | }), 58 | new webpack.DefinePlugin({ 59 | 'WEBPACK_ENV': '"production"' 60 | }), 61 | new CopyWebpackPlugin([{ from: './src/index.html' }], {}) 62 | ]); 63 | } 64 | 65 | module.exports = config; 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-webpack", 3 | "version": "1.0.0", 4 | "description": "Angular 2", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "WEBPACK_ENV=production webpack --progress --hide-modules", 8 | "dev": "webpack-dev-server --history-api-fallback --content-base ./src --open", 9 | "e2e": "protractor", 10 | "postinstall": "npm run webdriver-update", 11 | "test": "karma start", 12 | "posttest": "npm run coverage", 13 | "coverage": "npm run coverage:remap && npm run coverage:report", 14 | "coverage:remap": "remap-istanbul -i coverage/coverage.json -o coverage/coverage.json -t json -e node_modules,tests,karma.entry.ts", 15 | "coverage:report": "istanbul report", 16 | "webdriver-update": "webdriver-manager update" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/wkwiatek/angular2-webpack" 21 | }, 22 | "author": "wkwiatek ", 23 | "license": "SEE LICENSE IN LICENSE", 24 | "dependencies": { 25 | "@angular/common": "^2.0.0", 26 | "@angular/compiler": "^2.0.0", 27 | "@angular/core": "^2.0.0", 28 | "@angular/forms": "^2.0.0", 29 | "@angular/http": "^2.0.0", 30 | "@angular/platform-browser": "^2.0.0", 31 | "@angular/platform-browser-dynamic": "^2.0.0", 32 | "@angular/router": "^3.0.0", 33 | "@types/core-js": "^0.9.34", 34 | "@types/jasmine": "^2.2.34", 35 | "@types/node": "^6.0.40", 36 | "@types/selenium-webdriver": "^2.53.30", 37 | "core-js": "^2.4.1", 38 | "reflect-metadata": "^0.1.3", 39 | "rxjs": "5.0.0-rc.4", 40 | "zone.js": "^0.7.2" 41 | }, 42 | "devDependencies": { 43 | "babel-core": "^6.3.17", 44 | "babel-loader": "^6.2.0", 45 | "codelyzer": "^2.0.0-beta.2", 46 | "copy-webpack-plugin": "^4.0.0", 47 | "css-loader": "^0.26.0", 48 | "file-loader": "^0.9.0", 49 | "html-loader": "^0.4.4", 50 | "istanbul-instrumenter-loader": "^1.0.0", 51 | "jasmine-core": "^2.4.1", 52 | "json-loader": "^0.5.4", 53 | "karma": "^1.0.0", 54 | "karma-chrome-launcher": "^2.0.0", 55 | "karma-coverage": "^1.1.1", 56 | "karma-jasmine": "^1.0.0", 57 | "karma-mocha-reporter": "^2.0.0", 58 | "karma-remap-istanbul": "^0.2.1", 59 | "karma-source-map-support": "^1.1.0", 60 | "karma-sourcemap-loader": "^0.3.6", 61 | "karma-webpack": "^1.8.0", 62 | "protractor": "^4.0.0", 63 | "raw-loader": "^0.5.1", 64 | "stylus": "^0.54.2", 65 | "stylus-loader": "^2.0.0", 66 | "ts-loader": "^1.2.0", 67 | "tslint": "^4.1.1", 68 | "tslint-loader": "^3.3.0", 69 | "typescript": "^2.0.0", 70 | "webpack": "^2.2.0-rc.1", 71 | "webpack-dev-server": "^2.2.0-rc.0" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | 3 | const ENV_PRODUCTION = process.env.WEBPACK_ENV === 'production'; 4 | 5 | module.exports = config => { 6 | config.set({ 7 | 8 | // base path that will be used to resolve all patterns (eg. files, exclude) 9 | basePath: '', 10 | 11 | 12 | // frameworks to use 13 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 14 | frameworks: ['jasmine', 'source-map-support'], 15 | 16 | 17 | // list of files / patterns to load in the browser 18 | files: [ 19 | './karma.entry.ts' 20 | ], 21 | 22 | 23 | // list of files to exclude 24 | exclude: [ 25 | ], 26 | 27 | 28 | // preprocess matching files before serving them to the browser 29 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 30 | preprocessors: { 31 | './karma.entry.ts': ['webpack'] 32 | }, 33 | 34 | coverageReporter: { 35 | dir: 'coverage', 36 | reporters: [{ 37 | type: 'json', 38 | subdir: '.', 39 | file: 'coverage.json' 40 | }] 41 | }, 42 | 43 | webpack: { 44 | devtool: 'inline-source-map', 45 | resolve: { 46 | extensions: ['.ts', '.js', '.json'] 47 | }, 48 | module: { 49 | rules: [ 50 | // { enforce: 'pre', test: /\.ts$/, exclude: ['node_modules', /\.spec.ts$/], loader: 'istanbul-instrumenter-loader' }, 51 | { test: /\.ts$/, exclude: /node_modules/, loader: 'ts-loader' }, 52 | { test: /\.html/, loader: 'raw-loader' }, 53 | { test: /\.styl$/, loader: 'css-loader!stylus-loader' }, 54 | { test: /\.css$/, loader: 'css-loader' }, 55 | { test: /\.(gif|png|jpe?g)$/i, loader: 'file-loader' } 56 | ] 57 | }, 58 | stats: { colors: true, reasons: true }, 59 | plugins: [ 60 | // Fixes Angular 2 error 61 | new webpack.ContextReplacementPlugin( 62 | /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, 63 | __dirname 64 | ) 65 | ] 66 | }, 67 | 68 | webpackMiddleware: { 69 | noInfo: true //please don't spam the console when running in karma! 70 | }, 71 | 72 | // test results reporter to use 73 | // possible values: 'dots', 'progress' 74 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 75 | reporters: ['mocha'], 76 | 77 | 78 | // web server port 79 | port: 9876, 80 | 81 | 82 | // enable / disable colors in the output (reporters and logs) 83 | colors: true, 84 | 85 | 86 | // level of logging 87 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 88 | logLevel: config.LOG_INFO, 89 | 90 | 91 | // enable / disable watching file and executing tests whenever any file changes 92 | autoWatch: ENV_PRODUCTION ? false : true, 93 | 94 | // start these browsers 95 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 96 | browsers: ['Chrome'], 97 | 98 | 99 | // Continuous Integration mode 100 | // if true, Karma captures browsers, runs the tests and exits 101 | singleRun: ENV_PRODUCTION ? true : false, 102 | 103 | // fix for Chrome 55 104 | mime: { 105 | 'text/x-typescript': ['ts','tsx'] 106 | }, 107 | 108 | }); 109 | }; 110 | -------------------------------------------------------------------------------- /src/ie-shims/ie-shims.js: -------------------------------------------------------------------------------- 1 | // function.name (all IE) 2 | /*! @source http://stackoverflow.com/questions/6903762/function-name-not-supported-in-ie*/ 3 | if (!Object.hasOwnProperty('name')) { 4 | Object.defineProperty(Function.prototype, 'name', { 5 | get: function() { 6 | var matches = this.toString().match(/^\s*function\s*((?![0-9])[a-zA-Z0-9_$]*)\s*\(/); 7 | var name = matches && matches.length > 1 ? matches[1] : ""; 8 | // For better performance only parse once, and then cache the 9 | // result through a new accessor for repeated access. 10 | Object.defineProperty(this, 'name', {value: name}); 11 | return name; 12 | } 13 | }); 14 | } 15 | 16 | // URL polyfill for SystemJS (all IE) 17 | /*! @source https://github.com/ModuleLoader/es6-module-loader/blob/master/src/url-polyfill.js*/ 18 | // from https://gist.github.com/Yaffle/1088850 19 | (function(global) { 20 | function URLPolyfill(url, baseURL) { 21 | if (typeof url != 'string') { 22 | throw new TypeError('URL must be a string'); 23 | } 24 | var m = String(url).replace(/^\s+|\s+$/g, "").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 25 | if (!m) { 26 | throw new RangeError(); 27 | } 28 | var protocol = m[1] || ""; 29 | var username = m[2] || ""; 30 | var password = m[3] || ""; 31 | var host = m[4] || ""; 32 | var hostname = m[5] || ""; 33 | var port = m[6] || ""; 34 | var pathname = m[7] || ""; 35 | var search = m[8] || ""; 36 | var hash = m[9] || ""; 37 | if (baseURL !== undefined) { 38 | var base = baseURL instanceof URLPolyfill ? baseURL : new URLPolyfill(baseURL); 39 | var flag = protocol === "" && host === "" && username === ""; 40 | if (flag && pathname === "" && search === "") { 41 | search = base.search; 42 | } 43 | if (flag && pathname.charAt(0) !== "/") { 44 | pathname = (pathname !== "" ? (((base.host !== "" || base.username !== "") && base.pathname === "" ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + pathname) : base.pathname); 45 | } 46 | // dot segments removal 47 | var output = []; 48 | pathname.replace(/^(\.\.?(\/|$))+/, "") 49 | .replace(/\/(\.(\/|$))+/g, "/") 50 | .replace(/\/\.\.$/, "/../") 51 | .replace(/\/?[^\/]*/g, function (p) { 52 | if (p === "/..") { 53 | output.pop(); 54 | } else { 55 | output.push(p); 56 | } 57 | }); 58 | pathname = output.join("").replace(/^\//, pathname.charAt(0) === "/" ? "/" : ""); 59 | if (flag) { 60 | port = base.port; 61 | hostname = base.hostname; 62 | host = base.host; 63 | password = base.password; 64 | username = base.username; 65 | } 66 | if (protocol === "") { 67 | protocol = base.protocol; 68 | } 69 | } 70 | 71 | // convert windows file URLs to use / 72 | if (protocol == 'file:') 73 | pathname = pathname.replace(/\\/g, '/'); 74 | 75 | this.origin = protocol + (protocol !== "" || host !== "" ? "//" : "") + host; 76 | this.href = protocol + (protocol !== "" || host !== "" ? "//" : "") + (username !== "" ? username + (password !== "" ? ":" + password : "") + "@" : "") + host + pathname + search + hash; 77 | this.protocol = protocol; 78 | this.username = username; 79 | this.password = password; 80 | this.host = host; 81 | this.hostname = hostname; 82 | this.port = port; 83 | this.pathname = pathname; 84 | this.search = search; 85 | this.hash = hash; 86 | } 87 | global.URLPolyfill = URLPolyfill; 88 | })(typeof self != 'undefined' ? self : global); 89 | 90 | //classList (IE9) 91 | /*! @license please refer to http://unlicense.org/ */ 92 | /*! @author Eli Grey */ 93 | /*! @source https://github.com/eligrey/classList.js */ 94 | ;if("document" in self&&!("classList" in document.createElement("_"))){(function(j){"use strict";if(!("Element" in j)){return}var a="classList",f="prototype",m=j.Element[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p