From 6bebfe15cc05eda33824b7b7b9d4c80cb1feea1e Mon Sep 17 00:00:00 2001 From: Malte Brunnlieb Date: Tue, 8 Dec 2015 10:23:35 +0100 Subject: [PATCH] oasp/oasp4js#80: Multiple configuration adaptions enabling development with TypeScript --- .eslintrc | 37 +++++++++ .gitignore | 3 + gulp/build.js | 165 +------------------------------------ gulp/lib/config-factory.js | 111 ++++++++++++------------- gulp/lib/module-parser.js | 2 +- gulp/parts/fonts.js | 14 ++++ gulp/parts/html.js | 20 +++++ gulp/parts/i18n.js | 23 ++++++ gulp/parts/img.js | 47 +++++++++++ gulp/parts/index-html.js | 26 ++++++ gulp/parts/ng-templates.js | 26 ++++++ gulp/parts/scripts.js | 24 ++++++ gulp/parts/styles.js | 20 +++++ gulp/proxy.js | 31 +++---- gulp/server.js | 9 +- gulp/unit-tests.js | 67 +++++++-------- gulp/watch.js | 5 +- karma.conf.js | 33 +++++++- package.json | 128 ++++++++++++++-------------- system.config.js | 78 ++++++++++++++++++ tslint.json | 80 ++++++++++++++++++ 21 files changed, 604 insertions(+), 345 deletions(-) create mode 100644 .eslintrc create mode 100644 gulp/parts/fonts.js create mode 100644 gulp/parts/html.js create mode 100644 gulp/parts/i18n.js create mode 100644 gulp/parts/img.js create mode 100644 gulp/parts/index-html.js create mode 100644 gulp/parts/ng-templates.js create mode 100644 gulp/parts/scripts.js create mode 100644 gulp/parts/styles.js create mode 100644 system.config.js create mode 100644 tslint.json diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..5022e37 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,37 @@ +{ + "rules": { + "quotes": [ + 2, + "single" + ], + "semi": [ + 2, + "always" + ], + "strict": 2 + }, + "env": { + "browser": true, + "node": true, + "es6": true + }, + "ecmaFeatures": { + "modules": true + }, + "globals": { + "angular": true, + // Angular Mocks + "inject": false, + // JASMINE + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false, + "expect": false, + "jasmine": false, + "spyOn": false + }, + "extends": "eslint:recommended" +} diff --git a/.gitignore b/.gitignore index 2cb4287..b771d40 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ java/target .sonar *.bak docs/ +typings/ +.vscode/ +tsd.json \ No newline at end of file diff --git a/gulp/build.js b/gulp/build.js index 8b0f65f..9e4abbf 100644 --- a/gulp/build.js +++ b/gulp/build.js @@ -30,171 +30,8 @@ gulp.task('build:ci', gulpsync.sync(['test', 'build:dist'])); gulp.task('build:dist', ['env:prod', 'build']); -gulp.task('build', ['indexHtml', 'styles', 'img', 'fonts', 'i18n', 'html']); +gulp.task('build', ['indexHtml', 'scripts', 'styles', 'img', 'fonts', 'i18n', 'html']); gulp.task('clean', function (done) { return $.del(config.outputs(), done); }); -/** ======================================== styles ======================================== **/ -gulp.task('styles', function () { - return gulp.src(config.styles.src()) - .pipe($.concat(config.styles.output())) - .pipe($.less({ - paths: config.styles.includePaths() - })) - .pipe($.plumber()) - .pipe(gulp.dest(config.paths.tmp)) - .pipe($.size()); -}); - -gulp.task('style:copy', function () { - return gulp.src(config.styles.allSrc(), { base: config.paths.src}) - .pipe(gulp.dest(config.output())) - .pipe($.size()); -}); - -/** ======================================== indexHtml ======================================== **/ -gulp.task('indexHtml', gulpsync.sync([ - ['styles', 'img:sprite', 'ngTemplates'], - 'indexHtml:html' -])); - -//only build index.html without dependencies -gulp.task('indexHtml:html', function () { - return gulp.src(config.indexHtml.src()) - //TODO fix it - .pipe($.wiredep.stream({ - directory: 'bower_components', - exclude: ['bootstrap.js'] - })) - .pipe($.inject(gulp.src(config.scripts.src(), {read: false}), { - addRootSlash: false, - ignorePath: [config.paths.src, config.paths.tmp] - })) - .pipe($.inject(gulp.src(config.styles.injects(), {read: false}), { - addRootSlash: false, - ignorePath: [config.paths.src, config.paths.tmp, config.paths.dist] - })) - .pipe($.processhtml({commentMarker: 'process', - recursive: true, - includeBase: config.paths.src})) - .pipe($.if(isBuildForProd(), $.usemin({ - path: '{' + config.paths.tmp + ',' + config.paths.src + '}', - css: [$.minifyCss(), 'concat', $.rev()], - jsModernizr: [$.ngAnnotate(), $.uglify({preserveComments: $.uglifySaveLicense}), $.rev()], - jsVendor: [$.ngAnnotate(), $.uglify({preserveComments: $.uglifySaveLicense}), $.rev()], - jsApp: [$.ngAnnotate(), $.uglify({preserveComments: $.uglifySaveLicense}), $.rev()] - }))) - .pipe(gulp.dest(config.output())) - .pipe($.size()); -}); - -/** ======================================== img ======================================== **/ -gulp.task('img', ['img:sprite', 'img:copy']); - -gulp.task('img:sprite', function () { - return gulp.src(config.img.sprite.src()) - .pipe($.spritesmith({ - imgName: config.img.sprite.output.img(), - cssName: config.img.sprite.output.css() - })) - .pipe(gulp.dest(config.paths.tmp)) - .pipe($.size()); -}); - -gulp.task('img:sprite:copy', ['img:sprite'], function (done) { - if (isBuildForProd()) { - return gulp.src(config.paths.tmp + '/' + config.img.sprite.output.img(), {base: config.paths.tmp}) - .pipe($.imagemin({ - optimizationLevel: 3, - progressive: true, - interlaced: true - })) - .pipe(gulp.dest(config.output())) - .pipe($.size()); - } else { - done(); - } -}); - -gulp.task('img:copy', ['img:sprite:copy'], function (done) { - if (isBuildForProd()) { - return gulp.src(config.img.src(), {base: config.paths.src}) - .pipe($.imagemin({ - optimizationLevel: 3, - progressive: true, - interlaced: true - })) - .pipe(gulp.dest(config.output())) - .pipe($.size()); - } else { - done(); - } -}); - -/** ======================================== fonts ======================================== **/ -gulp.task('fonts', function (done) { - //TODO check font awesome - if (isBuildForProd()) { - return gulp.src('bower_components/**/*.{eot,svg,ttf,woff,woff2}') - .pipe($.flatten()) - .pipe(gulp.dest(config.output() + '/fonts/')); - } else { - done(); - } -}); - -/** ======================================== i18n ======================================== **/ -gulp.task('i18n', function (done) { - if (isBuildForProd()) { - return gulp.src(config.i18n.src(), {base: config.paths.src}) - .pipe(gulp.dest(config.output())); - } else { - done(); - } -}); - -/** ======================================== html ======================================== **/ -gulp.task('html', function () { - return gulp.src(config.html.src(), { base: config.paths.src }) - .pipe($.newer(config.paths.tmp)) - .pipe($.processhtml({commentMarker: 'process', - recursive: true, - includeBase: config.paths.src})) - .pipe($.if(isBuildForProd(), $.minifyHtml({ - empty: true, - spare: true, - quotes: true - }))) - .pipe(gulp.dest(config.output())) - .pipe($.size()); -}); - -/** ======================================== ng-templates ======================================== **/ -var ngTemplatesTasks = []; -gulp.task('ngTemplates', gulpsync.sync(['ngTemplatesTasksGeneration', 'ngTemplatesTasksExecution'])); -gulp.task('ngTemplatesTasksExecution', ngTemplatesTasks); -gulp.task('ngTemplatesTasksGeneration', function () { - config.ngTemplates.conf().forEach(function (ngTemplatesItemConf) { - ngTemplatesTasks.push('ngTemplates[' + ngTemplatesItemConf.file + ']'); - gulp.task('ngTemplates[' + ngTemplatesItemConf.file + ']', function () { - return gulp.src(ngTemplatesItemConf.src) - .pipe($.processhtml({commentMarker: 'process', - recursive: true, - includeBase: config.paths.src})) - .pipe($.minifyHtml({ - empty: true, - spare: true, - quotes: true - })) - .pipe($.ngTemplates({ - module: ngTemplatesItemConf.module, - path: function (path, base) { - return path.replace(base, ngTemplatesItemConf.moduleDir + '/').replace('.tpl.html', '.html'); - } - })) - .pipe($.concat(ngTemplatesItemConf.file)) - .pipe(gulp.dest(config.paths.tmp)); - }); - }); -}); diff --git a/gulp/lib/config-factory.js b/gulp/lib/config-factory.js index 1483471..188a452 100644 --- a/gulp/lib/config-factory.js +++ b/gulp/lib/config-factory.js @@ -37,68 +37,81 @@ var configFactory = function (externalConfig) { return [pathsBuilder.build('{src}/index.html')]; } }, - styles: { - /** include only root files*/ + i18n: { src: function () { - return pathsBuilder.build('{src}/*.' + externalConfig.styles.type); - }, - /** include all*/ - allSrc: function () { - return pathsBuilder.build('{src}/**/*.' + externalConfig.styles.type); - }, - output: function () { - return externalConfig.styles.output; - }, - injects: function () { - return [pathsBuilder.build('{tmp}/**/*.css'), pathsBuilder.build('{src}/**/*.css')]; - }, - includePaths: function () { - return [ - externalConfig.paths.src, - bowerConfig.directory - ]; + return _.flatten([ + pathsBuilder.build('{src}/**/i18n/**/*.json') + ]); } }, - scripts: { + html: { src: function () { return _.flatten([ - pathsBuilder.build('{src}/*.module.js'), - pathsBuilder.buildForTopLevelModules( - '{src}/{moduleFile}', '{src}/{moduleDir}/**/*.module.js', '{src}/{moduleDir}/**/!(*spec|*mock).js', '{tmp}/{moduleDir}/**/*.js') + pathsBuilder.build('{src}/**/*.html'), + pathsBuilder.build('!{src}/index.html'), + pathsBuilder.build('!{src}/**/*.tpl.html') ]); + } + }, + scripts: { + src: function () { + return pathsBuilder.build('{src}/*.module.ts'); }, testSrc: function () { return _.flatten([ - pathsBuilder.build('{testSrc}/*.mock.js'), - pathsBuilder.buildForTopLevelModules( - '{testSrc}/{moduleDir}/**/*.mock.js' - ), - pathsBuilder.build('{testSrc}/*.spec.js'), - pathsBuilder.buildForTopLevelModules( - '{testSrc}/{moduleDir}/**/*.spec.js' - ) + //load main spec to guarantee angular-mock loading + pathsBuilder.build('{testSrc}/app.spec.ts'), + pathsBuilder.build('{src}/*.module.ts'), + pathsBuilder.build('{testSrc}/*.mock.ts'), + pathsBuilder.build('{testSrc}/**/*.mock.ts'), + pathsBuilder.build('{testSrc}/*.spec.ts'), + pathsBuilder.build('{testSrc}/**/*.spec.ts') ]); }, lintSrc: function () { return _.flatten([ - pathsBuilder.build('{src}/*.module.js'), - pathsBuilder.buildForTopLevelModules( - '{src}/{moduleFile}', '{src}/{moduleDir}/**/*.module.js', '{src}/{moduleDir}/**/!(*spec|*mock).js') + pathsBuilder.build('{src}/*.module.ts'), + pathsBuilder.build('{src}/**/*.ts') ]); } }, - i18n: { + ngTemplates: { src: function () { - return pathsBuilder.buildForTopLevelModules('{src}/{moduleDir}/i18n/**/*.json'); + return pathsBuilder.build('{src}/**/*.tpl.html'); + }, + targetModule: function () { + return 'ng'; + }, + target: function () { + return pathsBuilder.build('app/app.templates.js'); + } + }, + styles: { + /** include only root files*/ + src: function () { + return pathsBuilder.build('{src}/*.' + externalConfig.styles.type); + }, + /** include all*/ + allSrc: function () { + return pathsBuilder.build('{src}/**/*.' + externalConfig.styles.type); + }, + output: function () { + return externalConfig.styles.output; + }, + includePaths: function () { + return [ + externalConfig.paths.src, + externalConfig.paths.tmp + ]; } }, img: { src: function () { - return pathsBuilder.buildForTopLevelModules('{src}/{moduleDir}/**/img/**/*.*', '!{src}/{moduleDir}/**/img/sprite/**'); + return [pathsBuilder.build('{src}/**/img/**/*.*'), pathsBuilder.build('!{src}/**/img/sprite/**/*.*')]; }, sprite: { src: function () { - return pathsBuilder.buildForTopLevelModules('{src}/{moduleDir}/**/img/sprite/**/*.png'); + return pathsBuilder.build('{src}/**/img/sprite/**/*.png'); }, output: { css: function () { @@ -109,28 +122,6 @@ var configFactory = function (externalConfig) { } } } - }, - html: { - src: function () { - return pathsBuilder.buildForTopLevelModules( - '{src}/{moduleDir}/**/*.html', - '!{src}/{moduleDir}/**/*.tpl.html' - ); - } - }, - ngTemplates: { - conf: function () { - return pathsBuilder.visitTopLevelModules(function (module) { - if (module.ngModule) { - return { - module: module.ngModule + '.templates', - moduleDir: module.moduleDir, - file: pathsBuilder.build('{moduleDir}/{module}.templates.js', module), - src: pathsBuilder.build('{src}/{moduleDir}/**/*.tpl.html', module) - }; - } - }); - } } }; }; diff --git a/gulp/lib/module-parser.js b/gulp/lib/module-parser.js index 4c92f6d..eb0c85e 100644 --- a/gulp/lib/module-parser.js +++ b/gulp/lib/module-parser.js @@ -19,7 +19,7 @@ module.exports = { moduleAbsDir: joinFn(basePath, moduleDirectory) }; if (fs.existsSync(paths.join(basePath, module.moduleFile))) { - module.ngModule = ngParseModule.parse(paths.join(basePath, module.moduleFile)).name; + module.ngModule = 'app';//ngParseModule.parse(paths.join(basePath, module.moduleFile)).name; } modules.push(module); } diff --git a/gulp/parts/fonts.js b/gulp/parts/fonts.js new file mode 100644 index 0000000..317ae1c --- /dev/null +++ b/gulp/parts/fonts.js @@ -0,0 +1,14 @@ +/*global config, isBuildForProd, $*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('fonts', function (done) { + //TODO check font awesome + if (isBuildForProd()) { + return gulp.src('bower_components/**/*.{eot,svg,ttf,woff,woff2}') + .pipe($.flatten()) + .pipe(gulp.dest(config.output() + '/fonts/')); + } else { + done(); + } +}); diff --git a/gulp/parts/html.js b/gulp/parts/html.js new file mode 100644 index 0000000..f85e4bd --- /dev/null +++ b/gulp/parts/html.js @@ -0,0 +1,20 @@ +/*global config, isBuildForProd, $*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('html', function () { + return gulp.src(config.html.src(), {base: config.paths.src}) + .pipe($.newer(config.paths.tmp)) + .pipe($.processhtml({ + commentMarker: 'process', + recursive: true, + includeBase: config.paths.src + })) + .pipe($.if(isBuildForProd(), $.minifyHtml({ + empty: true, + spare: true, + quotes: true + }))) + .pipe(gulp.dest(config.output())) + .pipe($.size()); +}); diff --git a/gulp/parts/i18n.js b/gulp/parts/i18n.js new file mode 100644 index 0000000..0f055ae --- /dev/null +++ b/gulp/parts/i18n.js @@ -0,0 +1,23 @@ +/*global config, isBuildForProd*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('i18n', ['i18n-app', 'i18n-bower-modules']); + +gulp.task('i18n-app', function (done) { + if (isBuildForProd()) { + return gulp.src(config.i18n.src(), {base: config.paths.src}) + .pipe(gulp.dest(config.output())); + } else { + done(); + } +}); + +gulp.task('i18n-bower-modules', function () { + if (isBuildForProd()) { + return gulp.src($.mainBowerFiles()) + .pipe($.filter('**/*labels*.json')) + .pipe($.flatten()) + .pipe(gulp.dest(config.output() + '/i18n/')); + } +}); diff --git a/gulp/parts/img.js b/gulp/parts/img.js new file mode 100644 index 0000000..ab589d9 --- /dev/null +++ b/gulp/parts/img.js @@ -0,0 +1,47 @@ +/*global config, isBuildForProd, $*/ +'use strict'; +var gulp = require('gulp'); + + +gulp.task('img', ['img:sprite', 'img:copy']); + +gulp.task('img:sprite', function () { + return gulp.src(config.img.sprite.src()) + .pipe($.spritesmith({ + imgName: config.img.sprite.output.img(), + cssName: config.img.sprite.output.css() + })) + .pipe(gulp.dest(config.paths.tmp)) + .pipe($.size()); +}); + +gulp.task('img:sprite:copy', ['img:sprite'], function (done) { + if (isBuildForProd()) { + return gulp.src(config.paths.tmp + '/' + config.img.sprite.output.img(), {base: config.paths.tmp}) + .pipe($.imagemin({ + optimizationLevel: 3, + progressive: true, + interlaced: true + })) + .pipe(gulp.dest(config.output())) + .pipe($.size()); + } else { + done(); + } +}); + +gulp.task('img:copy', ['img:sprite:copy'], function (done) { + if (isBuildForProd()) { + return gulp.src(config.img.src(), {base: config.paths.src}) + .pipe($.imagemin({ + optimizationLevel: 3, + progressive: true, + interlaced: true + })) + .pipe(gulp.dest(config.output())) + .pipe($.size()); + } else { + done(); + } +}); + diff --git a/gulp/parts/index-html.js b/gulp/parts/index-html.js new file mode 100644 index 0000000..2c9718d --- /dev/null +++ b/gulp/parts/index-html.js @@ -0,0 +1,26 @@ +/*global config, isBuildForProd, gulpsync, $*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('indexHtml', gulpsync.sync([ + ['styles', 'scripts', 'img:sprite', 'ngTemplates'], + 'indexHtml:html' +])); + +//only build index.html without dependencies +gulp.task('indexHtml:html', function () { + return gulp.src(config.indexHtml.src()) + .pipe($.processhtml({ + commentMarker: 'process', + recursive: true, + environment: isBuildForProd() ? 'prod' : 'dev', + includeBase: config.paths.src + })) + .pipe($.if(isBuildForProd(), $.usemin({ + path: '{' + config.paths.tmp + ',' + config.paths.src + '}', + css: [$.minifyCss(), $.rev()], + js: [$.rev()] + }))) + .pipe(gulp.dest(config.output())) + .pipe($.size()); +}); diff --git a/gulp/parts/ng-templates.js b/gulp/parts/ng-templates.js new file mode 100644 index 0000000..84c61f0 --- /dev/null +++ b/gulp/parts/ng-templates.js @@ -0,0 +1,26 @@ +/*global config, $*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('ngTemplates', function () { + return gulp.src(config.ngTemplates.src()) + .pipe($.processhtml({ + commentMarker: 'process', + recursive: true, + includeBase: config.paths.src + })) + .pipe($.minifyHtml({ + empty: true, + spare: true, + quotes: true + })) + .pipe($.angularTemplatecache({ + module: config.ngTemplates.targetModule(), + filename: config.ngTemplates.target(), + transformUrl: function (url) { + return url.replace(/\.tpl\.html$/, '.html'); + } + })) + .pipe($.insert.prepend('import angular from \'angular\';')) + .pipe(gulp.dest(config.paths.tmp)); +}); diff --git a/gulp/parts/scripts.js b/gulp/parts/scripts.js new file mode 100644 index 0000000..be0db8c --- /dev/null +++ b/gulp/parts/scripts.js @@ -0,0 +1,24 @@ +/*global config, $*/ +'use strict'; +var gulp = require('gulp'); +var Builder = require('systemjs-builder'); +gulp.task('scripts', ['ngTemplates'], function (done) { + if (isBuildForProd()) { + var builder = new Builder('./', './system.config.js'); + //output.source; // generated bundle source + //output.sourceMap; // generated bundle source map + //output.modules; // array of module names defined in the bundle + builder.buildStatic('app/app.module.ts').then(function (output) { + $.file('app/app.module.js', output.source) + .pipe($.ngAnnotate()) + .pipe($.uglify()) + .pipe(gulp.dest(config.paths.tmp)) + .pipe($.callback(done)); + }, function (ex) { + done(new Error(ex)); + }); + } + else { + done(); + } +}); diff --git a/gulp/parts/styles.js b/gulp/parts/styles.js new file mode 100644 index 0000000..f37e700 --- /dev/null +++ b/gulp/parts/styles.js @@ -0,0 +1,20 @@ +/*global config, $*/ +'use strict'; +var gulp = require('gulp'); + +gulp.task('styles',['img:sprite'] ,function () { + return gulp.src(config.styles.src()) + .pipe($.concat(config.styles.output())) + .pipe($.less({ + paths: config.styles.includePaths() + })) + .pipe($.plumber()) + .pipe(gulp.dest(config.paths.tmp)) + .pipe($.size()); +}); + +gulp.task('style:copy', function () { + return gulp.src(config.styles.allSrc(), {base: config.paths.src}) + .pipe(gulp.dest(config.output())) + .pipe($.size()); +}); diff --git a/gulp/proxy.js b/gulp/proxy.js index 20f954a..f33bec5 100644 --- a/gulp/proxy.js +++ b/gulp/proxy.js @@ -11,26 +11,29 @@ var proxy = httpProxy.createProxyServer({ /** * Additional logging for 500 */ -proxy.on('error', function (error, req, res) { - res.writeHead(500, { - 'Content-Type': 'text/plain' - }); - - console.error(chalk.red('[Proxy]'), error); -}); +var onError = function (error, req, res) { + res.writeHead(500, { + 'Content-Type': 'text/plain' + }); + console.error(chalk.red('[Proxy]'), error); +}; /** * Update cookie to allow app be served on /. */ -proxy.on('proxyRes', function (proxyRes) { - if (proxyRes.headers['set-cookie']) { - proxyRes.headers['set-cookie'][0] = proxyRes.headers['set-cookie'][0].replace(config.proxy.context(), ''); - } -}); +var onProxyRes = function (proxyRes) { + if (proxyRes.headers['set-cookie']) { + proxyRes.headers['set-cookie'][0] = proxyRes.headers['set-cookie'][0].replace(config.proxy.context(), ''); + } +}; /** * Support Websockets. */ -proxy.on('upgrade', function (req, socket, head) { - proxy.ws(req, socket, head); +var onUpgrade = function (req, socket, head) { + proxy.ws(req, socket, head); +}; +var proxy = httpProxy.createProxyServer({ + target: config.proxy.url(), + ws: true }); /** * Create middleware and define routing diff --git a/gulp/server.js b/gulp/server.js index 28e761f..aceb99f 100644 --- a/gulp/server.js +++ b/gulp/server.js @@ -16,21 +16,24 @@ function browserSyncInit(baseDir, files, browser) { baseDir: baseDir, middleware: middleware, routes: { - '/bower_components': 'bower_components' + '/bower_components': 'bower_components', + '/system.config.js': 'system.config.js' } }, browser: browser, - ghostMode: false + ghostMode: false, + online: false }); } gulp.task('serve', gulpsync.sync(['build', 'watch']), function () { browserSyncInit([ + '.', config.paths.tmp, config.paths.src, 'bower_components/bootstrap/dist' ], _.flatten([ - config.paths.tmp + '/**' + config.paths.tmp + '/**' ])); }); diff --git a/gulp/unit-tests.js b/gulp/unit-tests.js index dc19152..92e016b 100644 --- a/gulp/unit-tests.js +++ b/gulp/unit-tests.js @@ -3,44 +3,39 @@ var gulp = require('gulp'); var $ = require('gulp-load-plugins')(); -var createKarmaTask = function (options) { - /** - * Pass empty array - karma will query for files. - */ - return gulp.src('dummy.dummy') - .pipe($.karma(options)) - .on('error', function (err) { - // Make sure failed tests cause gulp to exit non-zero - throw err; - }); -}; -gulp.task('test', ['lint', 'ngTemplates'], function () { - process.env.generateCoverage = true; - return createKarmaTask({ - configFile: 'karma.conf.js', - action: 'run' - }); +var Server = require('karma').Server; + +gulp.task('test', ['lint', 'ngTemplates'], function (done) { + process.env.generateCoverage = true; + new Server({ + configFile: __dirname + '/../karma.conf.js', + singleRun: true, + autoWatch: false + }, done).start(); }); -gulp.task('test:tdd', ['ngTemplates'], function () { - process.env.generateCoverage = false; - return createKarmaTask({ - configFile: 'karma.conf.js', - action: 'watch' - }); +gulp.task('test:tdd', ['ngTemplates'], function (done) { + process.env.generateCoverage = false; + new Server({ + configFile: __dirname + '/../karma.conf.js', + singleRun: false, + autoWatch: true + }, done).start(); }); -gulp.task('test:tdd:debug', ['ngTemplates'], function () { - process.env.generateCoverage = false; - return createKarmaTask({ - configFile: 'karma.conf.js', - action: 'watch', - browsers: [ - 'Chrome' - ] - }); +gulp.task('test:tdd:debug', ['ngTemplates'], function (done) { + process.env.generateCoverage = false; + new Server({ + configFile: __dirname + '/../karma.conf.js', + singleRun: false, + autoWatch: true, + browsers: [ + 'Chrome' + ] + }, done).start(); }); gulp.task('lint', function () { - return gulp.src(config.scripts.lintSrc()) - .pipe($.jshint()) - .pipe($.jshint.reporter('jshint-stylish')) - .pipe($.jshint.reporter('fail')); + return gulp.src(config.scripts.lintSrc()) + .pipe($.tslint({configuration: require('../tslint.json')})) + .pipe($.tslint.report('prose', { + emitError: true + })); }); diff --git a/gulp/watch.js b/gulp/watch.js index 88af028..e40ee38 100644 --- a/gulp/watch.js +++ b/gulp/watch.js @@ -12,8 +12,5 @@ gulp.task('watch', [], function () { gulp.start('indexHtml:html'); } }); - gulp.watch('bower.json', ['indexHtml:html']); - config.ngTemplates.conf().forEach(function (ngTemplatesItemConf) { - gulp.watch(ngTemplatesItemConf.src, ['ngTemplates[' + ngTemplatesItemConf.file + ']']); - }); + gulp.watch(config.ngTemplates.src(),['ngTemplates']); }); diff --git a/karma.conf.js b/karma.conf.js index 151ca66..7b52529 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -36,10 +36,10 @@ module.exports = function (config) { basePath: '.', // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], + frameworks: ['systemjs', 'jasmine'], // list of files / patterns to load in the browser - files: _.flatten([libs, pathsConf.scripts.src(), pathsConf.scripts.testSrc()]), + files: pathsConf.scripts.testSrc(), // list of files / patterns to exclude exclude: [], @@ -61,7 +61,11 @@ module.exports = function (config) { // Which plugins to enable plugins: [ - 'karma-phantomjs-launcher', 'karma-chrome-launcher', 'karma-junit-reporter', 'karma-jasmine' + 'karma-systemjs', + 'karma-phantomjs-launcher', + 'karma-chrome-launcher', + 'karma-junit-reporter', + 'karma-jasmine' ], // Continuous Integration mode @@ -81,6 +85,29 @@ module.exports = function (config) { junitReporter: { outputDir: pathsConf.paths.testOutput, outputFile: 'test-results.xml' + }, + systemjs: { + configFile: 'system.config.js', + config: { + paths: { + 'angular': 'bower:angular/angular.js', + 'tmp/*': '/base/.tmp/*', + 'es6-module-loader': 'node_modules/es6-module-loader/dist/es6-module-loader.js', + 'systemjs': 'node_modules/systemjs/dist/system.js', + 'system-polyfills': 'node_modules/systemjs/dist/system-polyfills.js', + 'phantomjs-polyfill': 'node_modules/phantomjs-polyfill/bind-polyfill.js', + "typescript": "node_modules/typescript/lib/typescript.js" + }, + meta: { + 'bower:angular/angular.js': { + format: 'global' + } + } + }, + + serveFiles: [ + 'bower_components/**/*', pathsConf.paths.src + '/**/*', pathsConf.paths.tmp + '/**/*' + ] } }; if (process.env.generateCoverage === 'true') { diff --git a/package.json b/package.json index ef2e79e..b26f10c 100644 --- a/package.json +++ b/package.json @@ -7,67 +7,75 @@ "connect": "3.4.0" }, "devDependencies": { - "browser-sync": "2.7.13", - "chalk": "1.1.0", - "coveralls": "2.11.2", - "del": "1.2.0", - "gulp": "3.9.0", - "gulp-concat": "2.6.0", - "gulp-filter": "2.0.2", - "gulp-flatten": "0.1.0", - "gulp-git": "1.2.4", - "gulp-if": "1.2.5", - "gulp-imagemin": "2.3.0", - "gulp-inject": "1.3.1", - "gulp-insert": "0.4.0", - "gulp-jshint": "1.11.2", - "gulp-karma": "0.0.4", - "gulp-less": "3.0.3", - "gulp-load-plugins": "0.10.0", - "gulp-plumber": "1.0.1", - "gulp-minify-css": "1.2.0", - "gulp-minify-html": "1.0.3", - "gulp-newer": "0.5.1", - "gulp-ng-annotate": "1.0.0", - "gulp-ng-templates": "0.0.6", - "gulp-processhtml": "1.1.0", - "gulp-protractor": "1.0.0", - "gulp-replace": "0.5.3", - "gulp-env": "0.2.0", - "gulp-rev": "5.1.0", - "gulp-size": "1.2.3", - "gulp-sonar": "1.0.3", - "gulp-sourcemaps": "1.5.2", - "gulp-sync": "0.1.4", - "gulp-uglify": "1.2.0", - "gulp-usemin": "0.3.11", - "gulp-util": "3.0.6", - "gulp.spritesmith": "3.8.2", - "http-proxy": "1.11.1", - "jasmine-core": "2.3.4", - "jshint-stylish": "2.0.1", - "karma": "0.12.37", - "karma-chrome-launcher": "0.2.0", - "karma-coverage": "0.4.2", - "karma-jasmine": "0.3.6", - "karma-junit-reporter": "0.3.3", - "karma-phantomjs-launcher": "0.2.0", - "lodash": "3.10.0", - "main-bower-files": "2.9.0", - "phantomjs": "1.9.17", - "protractor": "2.1.0", - "require-dir": "0.3.0", - "string": "3.3.0", - "through2": "2.0.0", - "uglify-save-license": "0.4.1", - "wiredep": "2.2.2", - "yargs": "3.15.0", - "glob": "5.0.14", - "ng-parse-module": "0.1.0" + "browser-sync": "2.7.13", + "chalk": "1.1.0", + "coveralls": "2.11.2", + "es6-module-loader": "^0.17.8", + "del": "1.2.0", + "gulp": "3.9.0", + "gulp-concat": "2.6.0", + "gulp-eslint": "^1.0.0", + "gulp-filter": "2.0.2", + "gulp-flatten": "0.1.0", + "gulp-git": "1.2.4", + "gulp-if": "1.2.5", + "gulp-imagemin": "2.3.0", + "gulp-inject": "1.3.1", + "gulp-insert": "0.4.0", + "gulp-jshint": "1.11.2", + "gulp-karma": "0.0.4", + "gulp-less": "3.0.3", + "gulp-load-plugins": "0.10.0", + "gulp-plumber": "1.0.1", + "gulp-minify-css": "1.2.0", + "gulp-minify-html": "1.0.3", + "gulp-newer": "0.5.1", + "gulp-ng-annotate": "1.0.0", + "gulp-ng-templates": "0.0.6", + "gulp-processhtml": "1.1.0", + "gulp-protractor": "1.0.0", + "gulp-replace": "0.5.3", + "gulp-env": "0.2.0", + "gulp-rev": "5.1.0", + "gulp-size": "1.2.3", + "gulp-sonar": "1.0.3", + "gulp-sourcemaps": "1.5.2", + "gulp-sync": "0.1.4", + "gulp-tslint": "3.6.0", + "gulp-uglify": "1.2.0", + "gulp-usemin": "0.3.11", + "gulp-util": "3.0.6", + "gulp.spritesmith": "3.8.2", + "http-proxy": "1.11.1", + "jasmine-core": "2.3.4", + "jshint-stylish": "2.0.1", + "karma": "0.12.37", + "karma-chrome-launcher": "0.2.0", + "karma-coverage": "0.4.2", + "karma-jasmine": "0.3.6", + "karma-junit-reporter": "0.3.3", + "karma-phantomjs-launcher": "0.2.0", + "karma-systemjs": "0.9.0", + "lodash": "3.10.0", + "main-bower-files": "2.9.0", + "phantomjs": "1.9.17", + "protractor": "2.1.0", + "require-dir": "0.3.0", + "string": "3.3.0", + "systemjs": "0.19.4", + "systemjs-builder": "0.14.8", + "through2": "2.0.0", + "tsd": "0.6.5", + "typescript": "1.6.2", + "uglify-save-license": "0.4.1", + "wiredep": "2.2.2", + "yargs": "3.15.0", + "glob": "5.0.14", + "ng-parse-module": "0.1.0" }, "engine": "node >= 0.10.0", "scripts": { - "postinstall": "bower install -F", - "test": "gulp test" + "postinstall": "bower install -F", + "test": "gulp test" } -} +} \ No newline at end of file diff --git a/system.config.js b/system.config.js new file mode 100644 index 0000000..2d7d48d --- /dev/null +++ b/system.config.js @@ -0,0 +1,78 @@ +System.config({ + baseURL: "/", + defaultJSExtensions: true, + transpiler: "typescript", + paths: { + "npm:*": "node_modules/*", + "tmp/*": "./.tmp/*", + "bower:*": "bower_components/*" + }, + + packages: { + "app": { + "defaultExtension": "ts" + } + }, + + meta: { + 'bower:jquery/dist/jquery.js': { + format: 'global' + }, + 'bower:angular-translate/angular-translate.js': { + format: 'cjs' + }, + 'bower:angular-translate-loader-static-files/angular-translate-loader-static-files.js': { + format: 'cjs' + }, + 'bower:spin.js/spin.js': { + format: 'global' + }, + 'bower:angular-spinner/angular-spinner.js': { + format: 'global' + }, + 'bower:jqtree/tree.jquery.js': { + format: 'global' + }, + 'bower:jsUri/Uri.js': { + format: 'global' + }, + 'bower:angular-mocks/angular-mocks.js': { + format: 'global' + } + }, + + map: { + "jquery": "bower:jquery/dist/jquery.js", + + "angular": "bower:angular/index.js", + "angular-mocks": "bower:angular-mocks/angular-mocks.js", + "angular-animate": "bower:angular-animate/index.js", + "angular-sanitize": "bower:angular-sanitize/index.js", + + "angular-ui-bootstrap": "bower:angular-ui-bootstrap-bower/index.js", + "angular-ui-grid": "bower:angular-ui-grid/ui-grid.js", + "angular-ui-select": "bower:angular-ui-select/dist/select.js", + "angular-ui-validate": "bower:adamas/js/systemjs/angular-ui-validate.js", + + "angular-translate": "bower:angular-translate/angular-translate.js", + "angular-translate-loader-static-files": "bower:angular-translate-loader-static-files/angular-translate-loader-static-files.js", + + "angular-breadcrumb": "bower:adamas/js/systemjs/angular-breadcrumb.js", + "angular-growl": "bower:adamas/js/systemjs/angular-growl.js", + "adamas": "bower:adamas/js/systemjs/adamas.js", + "jsuri": "bower:jsUri/Uri.js", + "angular-jsuri": "bower:adamas/js/systemjs/angular-jsuri.js", + "spin.js": "bower:spin.js/spin.js", + "angular-spinner": "bower:angular-spinner/angular-spinner.js", + + + "valdr": "bower:adamas/js/systemjs/valdr.js", + "valdr-message": "bower:valdr/valdr-message.js", + "pdfmake": "bower:pdfmake/build/pdfmake.js", + "pdfmake-fonts": "bower:pdfmake/build/vfs_fonts.js", + + "ui-router": "bower:ui-router/release/angular-ui-router.js", + "jqtree": "bower:jqtree/tree.jquery.js", + "typescript": "npm:typescript/lib/typescript.js" + } +}); diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..e5a9372 --- /dev/null +++ b/tslint.json @@ -0,0 +1,80 @@ +{ + "rules": { + "ban": [true, + ["_", "extend"], + ["_", "isNull"], + ["_", "isDefined"] + ], + "class-name": true, + "comment-format": [true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [true, 2], + "interface-name": true, + "jsdoc-format": true, + "label-position": true, + "label-undefined": true, + "max-line-length": [false, 140], + "member-ordering": [true, + "static-before-instance", + "variables-before-functions" + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-constructor-vars": false, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": true, + "no-eval": true, + "no-string-literal": true, + "no-switch-case-fall-through": true, + "no-trailing-comma": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-unreachable": true, + "no-use-before-declare": true, + "no-var-requires": true, + "one-line": [true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [true, "single"], + "radix": true, + "semicolon": true, + "triple-equals": [true, "allow-null-check"], + "typedef": [true, + "callSignature", + "indexSignature", + "parameter", + "propertySignature", + "variableDeclarator" + ], + "typedef-whitespace": [true, + ["callSignature", "noSpace"], + ["catchClause", "noSpace"], + ["indexSignature", "space"] + ], + "use-strict": false, + "variable-name": false, + "whitespace": [true, + "check-branch", + "check-operator", + "check-separator" + ] + } +}