diff --git a/gulpfile.js b/gulpfile.js index 33aaac72ad..129383e917 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -876,3 +876,17 @@ gulp.task('tooling', function(){ .pipe(gulp.dest('dist')); }) }); + + +/** + * TS LINT + */ +gulp.task("tslint", function() { + var tslint = require("gulp-tslint"); + gulp.src([ + 'ionic/**/*.ts', + '!ionic/components/*/test/**/*', + '!ionic/util/test/*' + ]).pipe(tslint()) + .pipe(tslint.report('verbose')); +}); diff --git a/ionic/animations/animation.ts b/ionic/animations/animation.ts index 876737f923..d01c206a3f 100644 --- a/ionic/animations/animation.ts +++ b/ionic/animations/animation.ts @@ -179,7 +179,7 @@ export class Animation { if (!isNaN(num)) { fxState.num = num; } - fxState.unit = (r[0] != r[2] ? r[2] : ''); + fxState.unit = (r[0] !== r[2] ? r[2] : ''); } else if (typeof val === 'number') { fxState.num = val; @@ -216,7 +216,7 @@ export class Animation { } return this; } - } + }; } get after() { @@ -239,7 +239,7 @@ export class Animation { } return this; } - } + }; } play(opts: PlayOptions = {}) { @@ -818,10 +818,10 @@ interface EffectState { } const TRANSFORMS = { - 'translateX':1, 'translateY':1, 'translateZ':1, - 'scale':1, 'scaleX':1, 'scaleY':1, 'scaleZ':1, - 'rotate':1, 'rotateX':1, 'rotateY':1, 'rotateZ':1, - 'skewX':1, 'skewY':1, 'perspective':1 + 'translateX': 1, 'translateY': 1, 'translateZ': 1, + 'scale': 1, 'scaleX': 1, 'scaleY': 1, 'scaleZ': 1, + 'rotate': 1, 'rotateX': 1, 'rotateY': 1, 'rotateZ': 1, + 'skewX': 1, 'skewY': 1, 'perspective': 1 }; const CSS_VALUE_REGEX = /(^-?\d*\.?\d*)(.*)/; diff --git a/ionic/components/ion.ts b/ionic/components/ion.ts index ba8826f952..3aade6fe8d 100644 --- a/ionic/components/ion.ts +++ b/ionic/components/ion.ts @@ -1,7 +1,7 @@ import {ElementRef} from 'angular2/core'; import * as dom from '../util/dom'; -let ids:number = 0; +let ids: number = 0; /** * Base class for all Ionic components. Exposes some common functionality diff --git a/ionic/config/bootstrap.ts b/ionic/config/bootstrap.ts index 4593b369fd..9dccff432e 100644 --- a/ionic/config/bootstrap.ts +++ b/ionic/config/bootstrap.ts @@ -20,7 +20,7 @@ import {Translate} from '../translation/translate'; /** * @private */ -export function ionicProviders(args: any={}) { +export function ionicProviders(args: any = {}) { let platform = new Platform(); let navRegistry = new NavRegistry(args.pages); diff --git a/ionic/decorators/app.ts b/ionic/decorators/app.ts index 8f885d8e86..1d370bcc44 100644 --- a/ionic/decorators/app.ts +++ b/ionic/decorators/app.ts @@ -5,7 +5,7 @@ import {TapClick} from '../components/tap-click/tap-click'; import {ionicProviders} from '../config/bootstrap'; import {IONIC_DIRECTIVES} from '../config/directives'; -const _reflect: any=Reflect; +const _reflect: any = Reflect; export interface AppMetadata { prodMode?: boolean; @@ -64,7 +64,7 @@ export interface AppMetadata { * @property {string} [template] - the template to use for the app root. * @property {string} [templateUrl] - a relative URL pointing to the template to use for the app root. */ -export function App(args: AppMetadata={}) { +export function App(args: AppMetadata = {}) { return function(cls) { // get current annotations @@ -100,5 +100,5 @@ export function App(args: AppMetadata={}) { }); return cls; - } + }; } diff --git a/ionic/decorators/page.ts b/ionic/decorators/page.ts index 18adba1204..5d83eb47aa 100644 --- a/ionic/decorators/page.ts +++ b/ionic/decorators/page.ts @@ -1,7 +1,7 @@ -import {Component, ChangeDetectionStrategy, ViewEncapsulation, Type} from 'angular2/core' +import {Component, ChangeDetectionStrategy, ViewEncapsulation, Type} from 'angular2/core'; import {IONIC_DIRECTIVES} from '../config/directives'; -const _reflect: any=Reflect; +const _reflect: any = Reflect; export interface PageMetadata { selector?: string; @@ -107,5 +107,5 @@ export function Page(config: PageMetadata) { annotations.push(new Component(config)); _reflect.defineMetadata('annotations', annotations, cls); return cls; - } + }; } diff --git a/ionic/gestures/gesture.ts b/ionic/gestures/gesture.ts index 4e17d706c8..c4cb8d4e65 100644 --- a/ionic/gestures/gesture.ts +++ b/ionic/gestures/gesture.ts @@ -36,7 +36,7 @@ export class Gesture { } on(type: string, cb: Function) { - if(type == 'pinch' || type == 'rotate') { + if (type === 'pinch' || type === 'rotate') { this._hammer.get('pinch').set({enable: true}); } this._hammer.on(type, cb); diff --git a/ionic/gestures/hammer.ts b/ionic/gestures/hammer.ts index 1e169523fa..25fff48b99 100644 --- a/ionic/gestures/hammer.ts +++ b/ionic/gestures/hammer.ts @@ -1,3 +1,4 @@ +/* tslint:disable */ import {assign} from '../util/util'; const win: any = window; diff --git a/ionic/platform/platform.ts b/ionic/platform/platform.ts index 619b51698d..36e86c6b01 100644 --- a/ionic/platform/platform.ts +++ b/ionic/platform/platform.ts @@ -25,14 +25,14 @@ import {Config} from '../config/config'; */ export class Platform { private _platforms: Array; - private _versions: any={}; + private _versions: any = {}; private _dir: string; private _lang: string; private _url: string; private _qs: any; private _ua: string; private _bPlt: string; - private _onResizes: Array=[]; + private _onResizes: Array = []; private _readyPromise: Promise; private _readyResolve: any; private _engineReady: any; @@ -43,7 +43,7 @@ export class Platform { */ platformOverride: string; - constructor(platforms=[]) { + constructor(platforms = []) { this._platforms = platforms; this._readyPromise = new Promise(res => { this._readyResolve = res; } ); } diff --git a/ionic/transitions/transition-ios.ts b/ionic/transitions/transition-ios.ts index 431898a793..e03ac44e7d 100644 --- a/ionic/transitions/transition-ios.ts +++ b/ionic/transitions/transition-ios.ts @@ -8,7 +8,7 @@ const OPACITY = 'opacity'; const TRANSLATEX = 'translateX'; const OFF_RIGHT = '99.5%'; const OFF_LEFT = '-33%'; -const CENTER = '0%' +const CENTER = '0%'; const OFF_OPACITY = 0.8; const SHOW_BACK_BTN_CSS = 'show-back-button'; diff --git a/ionic/transitions/transition-md.ts b/ionic/transitions/transition-md.ts index 633b1bcd5b..8aadb7c934 100644 --- a/ionic/transitions/transition-md.ts +++ b/ionic/transitions/transition-md.ts @@ -4,7 +4,7 @@ import {ViewController} from '../components/nav/view-controller'; const TRANSLATEY = 'translateY'; const OFF_BOTTOM = '40px'; -const CENTER = '0px' +const CENTER = '0px'; const SHOW_BACK_BTN_CSS = 'show-back-button'; diff --git a/ionic/translation/translate.ts b/ionic/translation/translate.ts index 8d0c1aff73..5a45a2f693 100644 --- a/ionic/translation/translate.ts +++ b/ionic/translation/translate.ts @@ -45,7 +45,7 @@ export class Translate { translate(key, lang) { // If the language isn't specified and we have no overridden one, return the string passed. - if(!lang && !this._language) { + if (!lang && !this._language) { return key; } @@ -53,7 +53,7 @@ export class Translate { let map = this.getTranslations(setLanguage); - if(!map) { + if (!map) { console.warn('I18N: No translation for key', key, 'using language', setLanguage); return ''; } diff --git a/ionic/translation/translate_pipe.ts b/ionic/translation/translate_pipe.ts index c2658dca3b..ceb141ca72 100644 --- a/ionic/translation/translate_pipe.ts +++ b/ionic/translation/translate_pipe.ts @@ -16,14 +16,14 @@ import {Translate} from './translate'; @Pipe({name: 'translate'}) @Injectable() export class TranslatePipe implements PipeTransform { - private translate :any = {}; + private translate: any = {}; constructor(translate: Translate) { this.translate = translate; } transform(value, args) { let lang; - if(args.length > 0) { + if (args.length > 0) { lang = args[0]; } return this.translate.translate(value, lang); diff --git a/ionic/util/dom.ts b/ionic/util/dom.ts index ab00a3e712..d233eaa031 100644 --- a/ionic/util/dom.ts +++ b/ionic/util/dom.ts @@ -194,9 +194,9 @@ export function hasFocus(ele) { export function isTextInput(ele) { return !!ele && - (ele.tagName == 'TEXTAREA' || + (ele.tagName === 'TEXTAREA' || ele.contentEditable === 'true' || - (ele.tagName == 'INPUT' && !(/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i).test(ele.type))); + (ele.tagName === 'INPUT' && !(/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i).test(ele.type))); } export function hasFocusedTextInput() { @@ -207,7 +207,7 @@ export function hasFocusedTextInput() { return false; } -const skipInputAttrsReg = /^(value|checked|disabled|type|class|style|id|autofocus|autocomplete|autocorrect)$/i +const skipInputAttrsReg = /^(value|checked|disabled|type|class|style|id|autofocus|autocomplete|autocorrect)$/i; export function copyInputAttributes(srcElement, destElement) { // copy attributes from one element to another // however, skip over a few of them as they're already @@ -222,7 +222,7 @@ export function copyInputAttributes(srcElement, destElement) { } let matchesFn: string; -let matchesMethods: Array = ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector']; +let matchesMethods: Array = ['matches', 'webkitMatchesSelector', 'mozMatchesSelector', 'msMatchesSelector']; matchesMethods.some((fn: string) => { if (typeof document.documentElement[fn] === 'function') { matchesFn = fn; @@ -299,4 +299,4 @@ export function flushDimensionCache() { dimensionCache = {}; } -let dimensionCache:any = {}; +let dimensionCache: any = {}; diff --git a/ionic/util/keyboard.ts b/ionic/util/keyboard.ts index a64abb17a3..94b9d8e454 100644 --- a/ionic/util/keyboard.ts +++ b/ionic/util/keyboard.ts @@ -70,7 +70,7 @@ export class Keyboard { * @param {function} callback method you want to call when the keyboard has been closed * @return {function} returns a callback that gets fired when the keyboard is closed */ - onClose(callback, pollingInternval=KEYBOARD_CLOSE_POLLING) { + onClose(callback, pollingInternval = KEYBOARD_CLOSE_POLLING) { console.debug('keyboard onClose'); const self = this; let checks = 0; @@ -152,7 +152,7 @@ export class Keyboard { // default is to add the focus-outline when the tab key is used function keyDown(ev) { - if (!isKeyInputEnabled && ev.keyCode == 9) { + if (!isKeyInputEnabled && ev.keyCode === 9) { isKeyInputEnabled = true; enableKeyInput(); } diff --git a/ionic/util/scroll-view.ts b/ionic/util/scroll-view.ts index fbb213f0db..fe84f264e9 100644 --- a/ionic/util/scroll-view.ts +++ b/ionic/util/scroll-view.ts @@ -74,11 +74,11 @@ export class ScrollView { // fraction based on the easing method let easedT = (--time) * time * time + 1; - if (fromY != y) { + if (fromY !== y) { self.setTop((easedT * (y - fromY)) + fromY); } - if (fromX != x) { + if (fromX !== x) { self._el.scrollLeft = Math.floor((easedT * (x - fromX)) + fromX); } diff --git a/ionic/util/util.ts b/ionic/util/util.ts index 44c1efc0fb..225e1264e5 100644 --- a/ionic/util/util.ts +++ b/ionic/util/util.ts @@ -134,7 +134,9 @@ export const isCheckedProperty = function(a: any, b: any): boolean { } // not using strict comparison on purpose + /* tslint:disable */ return (a == b); + /* tslint:enable */ }; /** @@ -170,7 +172,7 @@ export const array = { arr.splice(index, 1); return true; } -} +}; /** * Grab all query strings keys and values. diff --git a/package.json b/package.json index c80cfff49d..74ae3cfc41 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "gulp-sass": "^2.0.4", "gulp-shell": "^0.4.0", "gulp-strip-debug": "^1.1.0", + "gulp-tslint": "^4.3.4", "gulp-typescript": "2.12.1", "gulp-util": "^3.0.6", "gulp-watch": "^4.2.4", @@ -79,6 +80,7 @@ "strip-sourcemap-loader": "0.0.1", "systemjs": "0.19.6", "through2": "^0.6.3", + "tslint": "^3.7.1", "typescript": "1.8.7", "vinyl": "^0.4.6", "webpack": "^1.12.2", diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..0173f9ad1f --- /dev/null +++ b/tslint.json @@ -0,0 +1,57 @@ +{ + "rules": { + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "indent": [ + true, + "spaces" + ], + "no-duplicate-variable": true, + "no-eval": true, + "no-internal-module": true, + "no-trailing-whitespace": true, + "no-var-keyword": false, + "one-line": [ + true, + "check-open-brace", + "check-whitespace" + ], + "quotemark": [ + true, + "single" + ], + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [ + true, + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} \ No newline at end of file