jenkins-bot has submitted this change and it was merged.

Change subject: build: Replace jshint+jscs with eslint
......................................................................


build: Replace jshint+jscs with eslint

Bug: T152579
Change-Id: Ifbbb2100ee9cfdf4c01793559df5e1ebc139617c
---
A .eslintrc.json
D .jscsrc
D .jshintrc
M dev/wikipedia.org/assets/js/event-logging-lite.js
M dev/wikipedia.org/assets/js/lang-dropdown.js
M dev/wikipedia.org/assets/js/mediawiki.lite.js
M dev/wikipedia.org/assets/js/polyfills.js
M dev/wikipedia.org/assets/js/search-language-picker.js
M dev/wikipedia.org/assets/js/seedrandom.js
M dev/wikipedia.org/assets/js/topten-localized.js
M dev/wikipedia.org/assets/js/underscore.partial.js
M dev/wikipedia.org/assets/js/wikipedia-org-event-logging.js
M dev/wikipedia.org/assets/js/wm-portal.js
M dev/wikipedia.org/assets/js/wm-test.js
M dev/wikipedia.org/assets/js/wm-typeahead.js
M gulpfile.js
M hbs-helpers.global.js
M package.json
18 files changed, 186 insertions(+), 163 deletions(-)

Approvals:
  Jdrewniak: Looks good to me, approved
  VolkerE: Looks good to me, but someone else must approve
  jenkins-bot: Verified



diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..fc98626
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,17 @@
+{
+       "extends": "wikimedia",
+       "env": {
+               "browser": true,
+               "jquery": true,
+               "qunit": true
+       },
+       "globals": {
+               "mw": true,
+               "mediaWiki": false
+       },
+       "rules": {
+               "vars-on-top": 1,
+               "one-var": 1,
+               "dot-notation": [ "error", { "allowKeywords": true } ]
+       }
+}
diff --git a/.jscsrc b/.jscsrc
deleted file mode 100644
index c9db9ba..0000000
--- a/.jscsrc
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  // taken from core
-  "preset": "wikimedia",
-  "es3": true,
-
-  "requireVarDeclFirst": false,
-  "requireMultipleVarDecl": {"allExcept": ["require"]}, // added
-
-  "disallowQuotedKeysInObjects": "allButReserved",
-  "requireDotNotation": { "allExcept": [ "keywords" ] },
-  "jsDoc": {
-       "checkParamNames": true,
-       "checkRedundantReturns": true,
-       "checkTypes": "strictNativeCase",
-       "requireNewlineAfterDescription": true,
-       "requireParamTypes": true,
-       "requireReturnTypes": true
-  }
-}
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 0d23568..0000000
--- a/.jshintrc
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-       // Enforcing
-       "bitwise": true,
-       "eqeqeq": true,
-       "esversion": "6",
-       "freeze": true,
-       "latedef": true,
-       "noarg": true,
-       "nonew": true,
-       "undef": true,
-       "unused": true,
-
-       // Relaxing
-       "laxbreak": true,
-       "multistr": true,
-
-       // Environment
-       "browser": true,
-
-       "globals": {
-               "JSON": false
-       }
-}
diff --git a/dev/wikipedia.org/assets/js/event-logging-lite.js 
b/dev/wikipedia.org/assets/js/event-logging-lite.js
index 8918794..06761fd 100644
--- a/dev/wikipedia.org/assets/js/event-logging-lite.js
+++ b/dev/wikipedia.org/assets/js/event-logging-lite.js
@@ -1,29 +1,28 @@
-/*global
-    JSON, console
-*/
+/* global Uint8Array */
 
+/* eslint dot-notation: ["error", { "allowKeywords": false }] */
 /**
-*
-* A slimmed down version of the event logging API.
-* Mostly copy & pasted from:
-* 
https://github.com/wikimedia/mediawiki-extensions-EventLogging/blob/master/modules/ext.eventLogging.core.js
-* without dependencies on jQuery or mediawiki.js. For use on wikipedia.org 
portal page.
-*
-*/
+ *
+ * A slimmed down version of the event logging API.
+ * Mostly copy & pasted from:
+ * 
https://github.com/wikimedia/mediawiki-extensions-EventLogging/blob/master/modules/ext.eventLogging.core.js
+ * without dependencies on jQuery or mediawiki.js. For use on wikipedia.org 
portal page.
+ *
+ */
 
 ( function () {
 
        'use strict';
 
        var baseUrl = '/beacon/event',
-       byteToHex = [],
-       self, helpers;
+               byteToHex = [],
+               self, helpers;
 
        helpers = {
                // replaces $.extend
                extend: function ( defaults, options ) {
                        var extended = {},
-                       prop;
+                               prop;
 
                        for ( prop in defaults ) {
                                if ( Object.prototype.hasOwnProperty.call( 
defaults, prop ) && defaults[ prop ] ) {
@@ -38,7 +37,8 @@
                        return extended;
                },
                // replaces $.noop
-               noop: function () {}
+               noop: function () {
+               }
        };
 
        // byte to hex from
@@ -94,11 +94,11 @@
                 */
                generateRandomSessionId: function () {
 
-                       /*jshint bitwise:false */
+                       /* eslint-disable no-bitwise */
                        var rnds, i, r,
-                       hexRnds = new Array( 8 ),
-                       // Support: IE 11
-                       crypto = window.crypto || window.msCrypto;
+                               hexRnds = new Array( 8 ),
+                               // Support: IE 11
+                               crypto = window.crypto || window.msCrypto;
 
                        // Based on 
https://github.com/broofa/node-uuid/blob/bfd9f96127/uuid.js
                        if ( crypto && crypto.getRandomValues ) {
@@ -123,7 +123,7 @@
                        // Concatenation of two random integers with entrophy n 
and m
                        // returns a string with entrophy n+m if those strings 
are independent
                        return hexRnds.join( '' );
-
+                       /* eslint-enable no-bitwise */
                },
 
                /**
@@ -135,7 +135,7 @@
                 */
                validate: function ( obj, schema ) {
                        var key, val, prop,
-                       errors = [];
+                               errors = [];
 
                        if ( !schema || !schema.properties ) {
                                errors.push( 'Missing or empty schema' );
@@ -180,10 +180,12 @@
                prepare: function ( schema, eventData ) {
 
                        var event = helpers.extend( schema.defaults, eventData 
),
-                       errors = self.validate( event, schema );
+                               errors = self.validate( event, schema );
 
                        while ( errors.length ) {
+                               /* eslint-disable no-console */
                                console.log( errors[ errors.length - 1 ] );
+                               /* eslint-enable no-console */
                                errors.pop();
                        }
 
@@ -216,13 +218,19 @@
                 * $wgEventLoggingBaseUri is unset, this method is a no-op.
                 *
                 * @param {string} url URL to request from the server.
-                * @return undefined
                 */
-               sendBeacon: ( /1|yes/.test( navigator.doNotTrack ) || !baseUrl )
-               ? helpers.noop
-               : navigator.sendBeacon
-               ? function ( url ) { try { navigator.sendBeacon( url ); } catch 
( e ) {} }
-               : function ( url ) { document.createElement( 'img' ).src = url; 
},
+               sendBeacon: ( /1|yes/.test( navigator.doNotTrack ) || !baseUrl 
) ?
+                       helpers.noop :
+                       navigator.sendBeacon ?
+                               function ( url ) {
+                                       try {
+                                               navigator.sendBeacon( url );
+                                       } catch ( e ) {
+                                       }
+                               } :
+                               function ( url ) {
+                                       document.createElement( 'img' ).src = 
url;
+                               },
 
                /**
                 * Construct and transmit to a remote server a record of some 
event
@@ -236,8 +244,8 @@
                 */
                logEvent: function ( schemaName, eventData ) {
                        var event = self.prepare( schemaName, eventData ),
-                       url = self.makeBeaconUrl( event ),
-                       sizeError = self.checkUrlSize( schemaName, url );
+                               url = self.makeBeaconUrl( event ),
+                               sizeError = self.checkUrlSize( schemaName, url 
);
 
                        if ( !sizeError ) {
                                self.sendBeacon( url );
diff --git a/dev/wikipedia.org/assets/js/lang-dropdown.js 
b/dev/wikipedia.org/assets/js/lang-dropdown.js
index c3fc040..dcc41e0 100644
--- a/dev/wikipedia.org/assets/js/lang-dropdown.js
+++ b/dev/wikipedia.org/assets/js/lang-dropdown.js
@@ -1,4 +1,4 @@
-/* global addEvent, mw, wmTest */
+/* global addEvent, wmTest */
 /*
  * The following functions open and close the language list
  * via the language drop-down button.
@@ -49,4 +49,4 @@
                toggleActiveClass();
        } );
 
-} )();
+}() );
diff --git a/dev/wikipedia.org/assets/js/mediawiki.lite.js 
b/dev/wikipedia.org/assets/js/mediawiki.lite.js
index 4f58a1e..c7e44b5 100644
--- a/dev/wikipedia.org/assets/js/mediawiki.lite.js
+++ b/dev/wikipedia.org/assets/js/mediawiki.lite.js
@@ -1,4 +1,4 @@
-var mw = mw || {};
+var mw = mw || {}; // eslint-disable-line no-use-before-define
 
 mw.html = ( function () {
        function escapeCallback( s ) {
@@ -100,6 +100,7 @@
                 * Wrapper object for raw HTML passed to mw.html.element().
                 *
                 * @class mw.html.Raw
+                * @param {Mixed} value
                 */
                Raw: function ( value ) {
                        this.value = value;
@@ -109,6 +110,7 @@
                 * Wrapper object for CDATA element contents passed to 
mw.html.element()
                 *
                 * @class mw.html.Cdata
+                * @param {Mixed} value
                 */
                Cdata: function ( value ) {
                        this.value = value;
diff --git a/dev/wikipedia.org/assets/js/polyfills.js 
b/dev/wikipedia.org/assets/js/polyfills.js
index a38d078..47c7180 100644
--- a/dev/wikipedia.org/assets/js/polyfills.js
+++ b/dev/wikipedia.org/assets/js/polyfills.js
@@ -1,6 +1,4 @@
-// jshint ignore: start
-// jscs:disable
-
+/* eslint-disable */
 /**
  * Polyfills for IE8 and under
  * code taken from https://developer.mozilla.org/ is dedicated to the Public 
Domain:
diff --git a/dev/wikipedia.org/assets/js/search-language-picker.js 
b/dev/wikipedia.org/assets/js/search-language-picker.js
index 8427c3e..933fc68 100644
--- a/dev/wikipedia.org/assets/js/search-language-picker.js
+++ b/dev/wikipedia.org/assets/js/search-language-picker.js
@@ -43,6 +43,8 @@
                 * Creates a fancy label that will cover the native select.
                 *
                 * This obviously only affects users who have JS enabled.
+                *
+                * @return {HTMLElement}
                 */
                function createJSLangLabel() {
                        var langLabel = document.createElement( 'label' );
diff --git a/dev/wikipedia.org/assets/js/seedrandom.js 
b/dev/wikipedia.org/assets/js/seedrandom.js
index 1405340..d9aa673 100644
--- a/dev/wikipedia.org/assets/js/seedrandom.js
+++ b/dev/wikipedia.org/assets/js/seedrandom.js
@@ -1,6 +1,4 @@
-// jshint ignore: start
-// jscs:disable
-
+/* eslint-disable */
 // From 
http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html
 // Documentation at 
http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html
 // Altered not to replace the Math.random but Math.seededrandom
diff --git a/dev/wikipedia.org/assets/js/topten-localized.js 
b/dev/wikipedia.org/assets/js/topten-localized.js
index 091080e..710bef1 100644
--- a/dev/wikipedia.org/assets/js/topten-localized.js
+++ b/dev/wikipedia.org/assets/js/topten-localized.js
@@ -1,7 +1,4 @@
-/*global
- wmTest, translationsHash, mw
- */
-
+/* global wmTest, translationsHash */
 /**
  * This code was used to localize the top-ten language links
  * for the A/B test titled "A/B test: browser language detection"
@@ -13,7 +10,7 @@
  * https://www.mediawiki.org/wiki/Wikipedia.org_Portal_A/B_testing
  */
 
-function localizeTopTen( ) {
+function localizeTopTen() {
 
        /**
         * Helper function to safely parse JSON an return empty string on error.
@@ -32,9 +29,11 @@
        }
 
        /**
-       * Returns an array of language codes based on the lang attributes of 
the top-ten links.
-       * returns {Array} topLinkLangs.
-       */
+        * Returns an array of language codes based on the lang attributes of 
the top-ten links.
+        *
+        * @param {Array} topLinks List of top link elements.
+        * @return {Array} List of top link languages.
+        */
        function getTopLinkLangs( topLinks ) {
                var topLinkLangs = [ ];
 
@@ -99,8 +98,8 @@
         * Essentially, instead of creating new elements, we move existing 
elements and
         * replace their textContent and attributes with a different content.
         *
-        * @param {Element} node - a DOM Element from the top-ten links that 
will be modified.
-        * @param {Object} wikiInfo - The info to modify the node with.
+        * @param {HTMLElement} node A DOM Element from the top-ten links that 
will be modified.
+        * @param {Object} wikiInfo The info to modify the node with.
         */
        function updateTopLinkDOM( node, wikiInfo ) {
                var anchor = node.getElementsByTagName( 'a' )[ 0 ],
@@ -167,8 +166,8 @@
         * After a successful request, the data is appended to a localStorage 
variable to prevent
         * subsequest ajax requests.
         *
-        * @param {Element} node - A DOM node that will be modified with new 
info upon ajax success.
-        * @param {string} lang - Language code for which to get new wiki info.
+        * @param {HTMLElement} node A DOM node that will be modified with new 
info upon ajax success.
+        * @param {string} lang Language code for which to get new wiki info.
         */
        function getAjaxTranslation( node, lang ) {
 
@@ -200,8 +199,8 @@
        /**
         * Determines whether to ajax in new language info or use it from 
localStorage.
         *
-        * @param {Element} node - the DOM node that will be modified with new 
info.
-        * @param {string} lang - the language code with which to modify the 
node.
+        * @param {HTMLElement} node The DOM node that will be modified with 
new info.
+        * @param {string} lang The language code with which to modify the node.
         */
        function localizeTopLink( node, lang ) {
 
@@ -219,9 +218,9 @@
         * Returns the first DOM node that does not have a lang attribute that 
is
         * one of topLinkLangs.
         *
-        * @param {Array} topLinks - array of DOM nodes
-        * @param {Array} topLinkLangs - array of languages
-        * @returns {Element} - node that can be reused with new content
+        * @param {Array} topLinks List of DOM nodes.
+        * @param {string[]} topLinkLangs List of languages.
+        * @returns {HTMLElement} Node that can be reused with new content.
         */
        function findReusableTopLink( topLinks, topLinkLangs ) {
                var reusableTopLink = null;
diff --git a/dev/wikipedia.org/assets/js/underscore.partial.js 
b/dev/wikipedia.org/assets/js/underscore.partial.js
index 76b5b69..2a3dce8 100644
--- a/dev/wikipedia.org/assets/js/underscore.partial.js
+++ b/dev/wikipedia.org/assets/js/underscore.partial.js
@@ -27,8 +27,7 @@
  This is a partial version of the library that only includes a few
  underscore methods.
  */
-/* jscs:disable */
-/* jshint ignore:start */
+/* eslint-disable */
 var _ = _ || {};
 
 _.now = Date.now || function() {
diff --git a/dev/wikipedia.org/assets/js/wikipedia-org-event-logging.js 
b/dev/wikipedia.org/assets/js/wikipedia-org-event-logging.js
index e7cb30a..ae0e1d6 100644
--- a/dev/wikipedia.org/assets/js/wikipedia-org-event-logging.js
+++ b/dev/wikipedia.org/assets/js/wikipedia-org-event-logging.js
@@ -1,4 +1,4 @@
-// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
+/* eslint camelcase: ["error", {properties: "never"}] */
 /* global eventLoggingLite, wmTest, addEvent */
 
 ( function ( eventLoggingLite, wmTest ) {
@@ -6,7 +6,7 @@
        'use strict';
 
        var portalSchema, eventSections, docForms, eventData,
-       geoCookie = document.cookie.match( /GeoIP=.[^:]/ );
+               geoCookie = document.cookie.match( /GeoIP=.[^:]/ );
 
        if ( wmTest.group === 'rejected' || wmTest.loggingDisabled ) {
                return;
@@ -76,6 +76,7 @@
                }
        };
 
+       /* eslint-disable no-multi-spaces */
        eventSections = [
                { name: 'primary links',   nodes: document.querySelectorAll( 
'[data-el-section="primary links"]' ) },
                { name: 'search',          nodes: document.querySelectorAll( 
'[data-el-section="search"]' ) },
@@ -84,14 +85,15 @@
                { name: 'other languages', nodes: document.querySelectorAll( 
'[data-el-section="other languages"]' ) },
                { name: 'other projects',  nodes: document.querySelectorAll( 
'[data-el-section="other projects"]' ) }
        ];
+       /* eslint-enable no-multi-spaces */
 
        /**
         * Finds the section of the page the user interacted with based on
         * a DOM element. Returns the name of the section.
         *
-        * @param {Element} clickNode - DOM element.
-        * @param {Array} eventSections - Array of objects describing the DOM 
sections.
-        * @returns {string} - the name of the section the contains the 
clickNode.
+        * @param {HTMLElement} clickNode The DOM element.
+        * @param {Array} eventSections List of objects describing the DOM 
sections.
+        * @return {string} The name of the section the contains the clickNode.
         */
        function findEventSection( clickNode, eventSections ) {
 
@@ -104,7 +106,7 @@
 
                        for ( j = 0; j < nodes.length; j++ ) {
 
-                               if (  nodes[ j ].contains( clickNode ) ) {
+                               if ( nodes[ j ].contains( clickNode ) ) {
 
                                        eventSection = eventSections[ i ];
                                }
@@ -119,8 +121,8 @@
         * the child of an anchor element, in order to retrieve that parent
         * anchor. Ex: <a><strong>clicked here</strong></a> returns <a> element.
         *
-        * @param {Element} el - Element to check for parent anchor.
-        * @returns {Element} - parent anchor element.
+        * @param {HTMLElement} el Element to check for parent anchor.
+        * @return {HTMLElement} Parent anchor element.
         */
        function checkForParentAnchor( el ) {
 
@@ -149,6 +151,8 @@
         * Document click event handler. Intercepts all document click events 
and checks
         * if they are an <a> matching an event section. If so, logs an event 
that user
         * has interacted with a specific section.
+        *
+        * @param {Event} e
         */
        function interceptClick( e ) {
 
@@ -180,6 +184,8 @@
        /**
         * Document change event handler. Intercepts all document change events 
(e.g.
         * search box's language selector.
+        *
+        * @param {Event} e
         */
        function interceptChange( e ) {
                var event = e || window.event,
@@ -188,7 +194,7 @@
                if ( target.id === 'searchLanguage' ) {
 
                        if ( target.selectedIndex === -1 ) {
-                               return null;
+                               return;
                        }
 
                        eventData = {
@@ -206,6 +212,8 @@
        /**
         * Form submission event handler. Checks if a form belongs to an event 
section
         * and logs an event when user has submitted it.
+        *
+        * @param {Event} e
         */
        function interceptForm( e ) {
                var event = e || window.event,
diff --git a/dev/wikipedia.org/assets/js/wm-portal.js 
b/dev/wikipedia.org/assets/js/wm-portal.js
index d84d244..b6c1113 100644
--- a/dev/wikipedia.org/assets/js/wm-portal.js
+++ b/dev/wikipedia.org/assets/js/wm-portal.js
@@ -18,11 +18,14 @@
  */
 /* global addEvent, doWhenReady, getIso639, getDevicePixelRatio */
 
-( function ( ) {
+( function () {
        'use strict';
 
        /**
         * Returns the DOM element with the given ID.
+        *
+        * @param {string} id
+        * @return {HTMLElement}
         */
        function $( id ) {
                return document.getElementById( id );
@@ -30,14 +33,17 @@
 
        /**
         * Replaces the “hero graphic” with the given language edition’s logo.
+        *
+        * @param {string} lang
         */
        function updateBranding( lang ) {
                var option, logo;
 
                // Only Wiktionary has such a mess of logos.
-               if ( !document.querySelector
-                       || document.body.id !== 'www-wiktionary-org'
-                       || lang.match( /\W/ )
+               if (
+                       !document.querySelector ||
+                       document.body.id !== 'www-wiktionary-org' ||
+                       lang.match( /\W/ )
                ) {
                        return;
                }
@@ -51,6 +57,8 @@
 
        /**
         * Returns the user's preferred language according to browser 
preferences.
+        *
+        * @return {string}
         */
        function getUALang() {
                var uiLang = ( navigator.languages && navigator.languages[ 0 ] 
) ||
@@ -61,6 +69,8 @@
        /**
         * Returns the preferred language as stored in a cookie. Falls back on 
the
         * browser's language.
+        *
+        * @return {string}
         */
        function getSavedLang() {
                var match = document.cookie.match( /(?:^|\W)searchLang=([^;]+)/ 
);
@@ -85,6 +95,8 @@
         *
         * Convertible elements start out with traditional text and title 
attributes
         * along with simplified counterparts in the data-*-hans attributes.
+        *
+        * @param {string} lang
         */
        function convertChinese( lang ) {
                var i, elt,
@@ -116,6 +128,8 @@
        /**
         * Modifies links to the Chinese language edition to point to 
traditional or
         * simplified versions, based on the user's preference.
+        *
+        * @param {string} lang
         */
        function convertZhLinks( lang ) {
                var locale;
@@ -188,6 +202,8 @@
         * Stores the user's preferred language in a cookie. This function is 
called
         * once a language other than the browser's default is selected from the
         * dropdown.
+        *
+        * @param {string} lang
         */
        function setLang( lang ) {
                if ( !lang ) {
@@ -317,7 +333,7 @@
 
        doWhenReady( hidpi );
 
-}( ) );
+}() );
 
 /*
  * Depending on how this script is loaded, it may not have
diff --git a/dev/wikipedia.org/assets/js/wm-test.js 
b/dev/wikipedia.org/assets/js/wm-test.js
index 24232ea..bfa0b49 100644
--- a/dev/wikipedia.org/assets/js/wm-test.js
+++ b/dev/wikipedia.org/assets/js/wm-test.js
@@ -1,5 +1,4 @@
-// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
-/*global mw, eventLoggingLite, getIso639 */
+/* global eventLoggingLite, getIso639 */
 
 window.wmTest = ( function ( eventLoggingLite, mw ) {
 
@@ -68,6 +67,8 @@
 
        /**
         * Puts the user in a population group randomly.
+        *
+        * @return {string}
         */
        function getTestGroup() {
 
@@ -101,11 +102,11 @@
                if ( window.localStorage && !/1|yes/.test( navigator.doNotTrack 
) ) {
 
                        var storedSessionId = mw.storage.get( KEYS.SESSION_ID ),
-                               expires =  mw.storage.get( KEYS.EXPIRES ),
+                               expires = mw.storage.get( KEYS.EXPIRES ),
                                now = new Date().getTime();
 
                        // return storedSessionId if not expired
-                       if ( storedSessionId && expires > parseInt( now, 10 )  
) {
+                       if ( storedSessionId && expires > parseInt( now, 10 ) ) 
{
                                sessionId = storedSessionId;
                        } else {
                                // or create new sessionID
diff --git a/dev/wikipedia.org/assets/js/wm-typeahead.js 
b/dev/wikipedia.org/assets/js/wm-typeahead.js
index 1eb8bcb..48dec83 100644
--- a/dev/wikipedia.org/assets/js/wm-typeahead.js
+++ b/dev/wikipedia.org/assets/js/wm-typeahead.js
@@ -8,16 +8,16 @@
  * @param {string} searchInput - ID of a search input whose value will be used 
to generate search suggestions.
  *
  * @return {Object} Returns an object with the following properties:
- * @return {Element} WMTypeAhead.typeAheadEl - The type-ahead DOM object
- * @return {Function} WMTypeAhead.query - a function that loads the type-ahead 
suggestions.
+ * @return {HTMLElement} return.typeAheadEl The type-ahead DOM object.
+ * @return {Function} return.query A function that loads the type-ahead 
suggestions.
  *
  * @example
  * var typeAhead = new WMTypeAhead('containerID', 'inputID');
  * typeAhead.query('search string', 'en');
  *
-*/
+ */
 
-/* global addEvent, mw, getDevicePixelRatio */
+/* global addEvent, getDevicePixelRatio */
 /* exported WMTypeAhead */
 
 var WMTypeAhead = function ( appendTo, searchInput ) {
@@ -82,7 +82,7 @@
 
                        for ( var callback in this.queue ) {
                                if ( callback < j ) {
-                                       this.queue[ callback ]  = 
this.deleteSelfFromQueue.bind( window.callbackStack, callback );
+                                       this.queue[ callback ] = 
this.deleteSelfFromQueue.bind( window.callbackStack, callback );
                                }
                        }
                }
@@ -101,12 +101,18 @@
                },
                increment: function ( i ) {
                        this.index += i;
-                       if ( this.index < 0 ) { this.setIndex( this.max - 1 ); 
} // index reaches top
-                       if ( this.index === this.max ) { this.setIndex( 0 ); } 
// index reaches bottom
+                       if ( this.index < 0 ) {
+                               this.setIndex( this.max - 1 );
+                       } // index reaches top
+                       if ( this.index === this.max ) {
+                               this.setIndex( 0 );
+                       } // index reaches bottom
                        return this.index;
                },
                setIndex: function ( i ) {
-                       if ( i <= this.max - 1 ) { this.index = i; }
+                       if ( i <= this.max - 1 ) {
+                               this.index = i;
+                       }
                        return this.index;
                },
                clear: function () {
@@ -128,7 +134,9 @@
                setTimeout( function () {
                        typeAheadEl.innerHTML = '';
                        var searchScript = document.getElementById( 
'api_opensearch' );
-                       if ( searchScript ) { searchScript.src = false; }
+                       if ( searchScript ) {
+                               searchScript.src = false;
+                       }
                        ssActiveIndex.clear();
                }, 300 );
        }
@@ -163,26 +171,27 @@
                script.id = 'api_opensearch';
 
                var callbackIndex = window.callbackStack.addCallback( 
window.portalOpensearchCallback ),
-               searchQuery = {
-                       action: 'query',
-                       format: 'json',
-                       generator: 'prefixsearch',
-                       prop: 'pageprops|pageimages|pageterms',
-                       redirects: '',
-                       ppprop: 'displaytitle',
-                       piprop: 'thumbnail',
-                       pithumbsize: thumbnailSize,
-                       pilimit: maxSearchResults,
-                       wbptterms: 'description',
-                       gpssearch: string,
-                       gpsnamespace: 0,
-                       gpslimit: maxSearchResults,
-                       callback: 'callbackStack.queue[' + callbackIndex + ']'
-               };
+                       searchQuery = {
+                               action: 'query',
+                               format: 'json',
+                               generator: 'prefixsearch',
+                               prop: 'pageprops|pageimages|pageterms',
+                               redirects: '',
+                               ppprop: 'displaytitle',
+                               piprop: 'thumbnail',
+                               pithumbsize: thumbnailSize,
+                               pilimit: maxSearchResults,
+                               wbptterms: 'description',
+                               gpssearch: string,
+                               gpsnamespace: 0,
+                               gpslimit: maxSearchResults,
+                               callback: 'callbackStack.queue[' + 
callbackIndex + ']'
+                       };
 
                script.src = hostname + serialize( searchQuery );
                docHead.appendChild( script );
        }
+
        // END loadQueryScript
 
        /**
@@ -231,10 +240,10 @@
                         * Indentation is used to express the DOM order of 
template.
                         */
                        var suggestionLink,
-                                       suggestionThumbnail,
-                                       suggestionText,
-                                               suggestionTitle,
-                                               suggestionDescription,
+                               suggestionThumbnail,
+                               suggestionText,
+                               suggestionTitle,
+                               suggestionDescription,
                                page = suggestions[ i ],
                                sanitizedThumbURL = false,
                                descriptionText = '',
@@ -258,7 +267,7 @@
 
                        suggestionDescription = mw.html.element( 'p', { 
'class': 'suggestion-description' }, descriptionText );
 
-                       suggestionTitle = mw.html.element( 'h3', { 'class': 
'suggestion-title' }, new mw.html.Raw( highlightTitle( page.title, searchString 
) ) ) ;
+                       suggestionTitle = mw.html.element( 'h3', { 'class': 
'suggestion-title' }, new mw.html.Raw( highlightTitle( page.title, searchString 
) ) );
 
                        suggestionText = mw.html.element( 'div', { 'class': 
'suggestion-text' }, new mw.html.Raw( suggestionTitle + suggestionDescription ) 
);
 
@@ -286,8 +295,8 @@
         * - Adds 'active' class to an item if missing.
         * - Removes 'active' class from item if present.
         *
-        * @param {Element} item - item to add active class to.
-        * @param {NodeList} collection - sibling items
+        * @param {HTMLElement} item Item to add active class to.
+        * @param {NodeList} collection Sibling items.
         */
 
        function toggleActiveClass( item, collection ) {
@@ -323,6 +332,7 @@
         *  - attaches event listeners on each suggestion item.
         *
         * @param {number} i
+        * @return {Function}
         */
        window.portalOpensearchCallback = function ( i ) {
 
@@ -372,7 +382,7 @@
        function keyboardEvents( event ) {
 
                var e = event || window.event,
-                       keycode =  e.which || e.keyCode;
+                       keycode = e.which || e.keyCode;
 
                if ( !typeAheadEl.firstChild ) {
                        return;
@@ -387,7 +397,7 @@
                                searchSuggestionIndex = 
ssActiveIndex.increment( -1 );
                        }
 
-                       activeItem = ( suggestionItems ) ? suggestionItems[ 
searchSuggestionIndex ] : false ;
+                       activeItem = ( suggestionItems ) ? suggestionItems[ 
searchSuggestionIndex ] : false;
 
                        toggleActiveClass( activeItem, suggestionItems );
 
diff --git a/gulpfile.js b/gulpfile.js
index 11ac713..1c6a8e8 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -3,6 +3,7 @@
 /* globals process */
 /* globals console */
 /* globals JSON */
+/* eslint dot-notation: ["error", { "allowKeywords": false }] */
 var gulp = require( 'gulp' ),
        gulpLoadPlugins = require( 'gulp-load-plugins' ),
        argv = require( 'yargs' ).argv,
@@ -24,6 +25,7 @@
 
 // Help
 gulp.task( 'help', function () {
+       /* eslint-disable no-console */
        console.log();
        console.log( 
'+-------------------------------------------------------------------------------------------------+'
 );
        console.log( '|                                     =====  USAGE =====  
                                        |' );
@@ -45,6 +47,7 @@
        console.log( '| gulp fetch-meta --portal wikipedia.org      - overwrite 
the portal page with source from Meta   |' );
        console.log( 
'+-------------------------------------------------------------------------------------------------+'
 );
        console.log();
+       /* eslint-enable no-console */
 } );
 
 /* Preliminary configuration
@@ -56,10 +59,12 @@
  */
 function requirePortalParam() {
        if ( !portalParam ) {
+               /* eslint-disable no-console */
                console.log( '\x1b[31m' );
                console.log( 'Error: please specify the portal you wish to 
build.' );
                console.log( 'Type gulp help for more information.' );
                console.log( '\x1b[0m' );
+               /* eslint-enable no-console */
                process.exit( 1 );
        }
 }
@@ -263,7 +268,7 @@
        var imgOpt = getConfig().optImage;
 
        return gulp.src( imgOpt.src )
-               .pipe( imagemin( imgOpt.imageminConf.plugins, 
imgOpt.imageminConf.options  ) )
+               .pipe( imagemin( imgOpt.imageminConf.plugins, 
imgOpt.imageminConf.options ) )
                .pipe( gulp.dest( imgOpt.dest ) );
 } );
 
@@ -292,23 +297,21 @@
                devFolder = 'dev/' + portalParam + '/**/*.js';
        }
        gulp.src( [ '*.js', devFolder ] )
-               .pipe( plugins.jshint( '.jshintrc' ) )
-               .pipe( plugins.jshint.reporter( 'default' ) )
-               .pipe( plugins.jshint.reporter( 'fail' ) )
-               .pipe( plugins.jscs() )
-               .pipe( plugins.jscs.reporter() )
-               .pipe( plugins.jscs.reporter( 'fail' ) );
+               .pipe( plugins.eslint( '.eslintrc.json' ) )
+               .pipe( plugins.eslint.format() )
+               .pipe( plugins.eslint.failAfterError() );
 } );
 
 gulp.task( 'validate-postCSS', function () {
        return gulp
                .src( [ 'dev/**/postcss/*.css', '!dev/**/postcss/_*.css' ] )
-               .pipe( plugins.postcss( [
+               .pipe( plugins.postcss(
+                       [
                                postCSSImport(),
                                postCSSNext( { browsers: [ 'last 5 versions', 
'ie 6-8', 'Firefox >= 3.5', 'iOS >= 4', 'Android >= 2.3' ] } ),
                                postCSSReporter( { clearMessages: true, 
throwError: true } )
                        ], { map: { inline: true } }
-                       ) );
+               ) );
 } );
 
 gulp.task( 'lint-css', [ 'validate-postCSS' ], function () {
@@ -333,7 +336,9 @@
        requirePortalParam();
 
        if ( portalParam === 'wikipedia.org' ) {
+               /* eslint-disable no-console */
                console.log( 'Cannot override ' + portalParam + ' portal using 
fetch-meta.' );
+               /* eslint-enable no-console */
                process.exit( 1 );
                return;
        }
@@ -386,4 +391,4 @@
 
 gulp.task( 'test', [ 'lint' ] );
 
-gulp.task( 'default', [ 'lint', 'compile-handlebars', 'sprite', 'postcss', 
'inline-assets', 'clean-prod-js', 'concat-minify-js', 'minify-html', 
'optimize-images',  'copy-translation-files' ] );
+gulp.task( 'default', [ 'lint', 'compile-handlebars', 'sprite', 'postcss', 
'inline-assets', 'clean-prod-js', 'concat-minify-js', 'minify-html', 
'optimize-images', 'copy-translation-files' ] );
diff --git a/hbs-helpers.global.js b/hbs-helpers.global.js
index a8e0e5a..74062b7 100644
--- a/hbs-helpers.global.js
+++ b/hbs-helpers.global.js
@@ -35,9 +35,11 @@
                        if ( whiteList.indexOf( lowercase ) > -1 ) {
                                output += ' ' + Handlebars.escapeExpression( 
lowercase ) + '="' + Handlebars.escapeExpression( this[ attrs ][ attr ] ) + '"';
                        } else {
+                               /* eslint-disable no-console */
                                console.log( '\x1b[31m' );
                                console.log( 'Warning: the attr "' + lowercase 
+ '" was rejected by the printAttrs helper.' );
                                console.log( '\x1b[0m' );
+                               /* eslint-enable no-console */
                        }
                }
        }
diff --git a/package.json b/package.json
index f0799d3..11d32c8 100644
--- a/package.json
+++ b/package.json
@@ -13,15 +13,15 @@
     "casperjs": "git+https://github.com/n1k0/casperjs.git";,
     "deepmerge": "^1.2.0",
     "del": "^2.2.0",
+    "eslint-config-wikimedia": "^0.3.0",
     "gulp": "^3.9.1",
     "gulp-clean-css": "^2.0.13",
     "gulp-compile-handlebars": "^0.6.1",
+    "gulp-eslint": "^3.0.1",
     "gulp-htmlmin": "^3.0.0",
     "gulp-if": "^2.0.0",
     "gulp-imagemin": "^3.0.3",
     "gulp-inline": "^0.1.0",
-    "gulp-jscs": "^4.0.0",
-    "gulp-jshint": "^2.0.0",
     "gulp-load-plugins": "^1.0.0",
     "gulp-postcss": "^6.0.1",
     "gulp-rename": "^1.2.2",

-- 
To view, visit https://gerrit.wikimedia.org/r/325727
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ifbbb2100ee9cfdf4c01793559df5e1ebc139617c
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/portals
Gerrit-Branch: master
Gerrit-Owner: JGirault <[email protected]>
Gerrit-Reviewer: Jdrewniak <[email protected]>
Gerrit-Reviewer: MarcoAurelio <[email protected]>
Gerrit-Reviewer: Mxn <[email protected]>
Gerrit-Reviewer: VolkerE <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to