Use eslint and stylelint, fix all errors (#282)

* Use eslint and stylelint, fix all errors

* Remove jshint, jsbeautify
* Use Object.keys directly since that is available in all major browsers
* Fixes for eslint, stylelint errors
* stylelint is not included in grunt test yet because jquery.uls.mobile.css
  has so many !important and need to figure out whether they are really needed
This commit is contained in:
Santhosh Thottingal
2018-01-04 19:28:35 +05:30
committed by Niklas Laxström
parent ddadf086c5
commit 2a77df6c41
19 changed files with 235 additions and 277 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
src/jquery.uls.data.js

14
.eslintrc.json Normal file
View File

@@ -0,0 +1,14 @@
{
"extends": "wikimedia",
"env": {
"browser": true,
"jquery": true,
"qunit": true
},
"globals": {
"require": false
},
"rules": {
"dot-notation": [ "error", { "allowKeywords": true } ]
}
}

View File

@@ -1,17 +0,0 @@
{
"preserve_newlines": true,
"jslint_happy": true,
"keep_array_indentation": true,
"space_before_conditional": true,
"max_preserve_newlines": 10,
"brace_style": "collapse",
"keep_function_indentation": false,
"break_chained_methods": false,
"eval_code": false,
"unescape_strings": false,
"wrap_line_length": 0,
"space_in_paren": true,
"space_in_square_bracket": true,
"git_happy": true,
"indent_with_tabs": true
}

View File

@@ -1 +0,0 @@
src/jquery.uls.data.js

View File

@@ -1,35 +0,0 @@
{
// Enforcing
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"forin": false,
"immed": true,
"latedef": "nofunc",
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"onevar": true,
"quotmark": "single",
"regexp": false,
"strict": true,
"trailing": true,
"undef": true,
"unused": true,
// Relax
"laxbreak": true,
"multistr": true,
"smarttabs": true,
// Environment
"browser": true,
"predef": [
"_",
"jQuery",
"QUnit"
]
}

3
.stylelintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "stylelint-config-wikimedia"
}

View File

@@ -1,22 +1,35 @@
/*jshint node:true */
'use strict';
module.exports = function ( grunt ) {
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
grunt.loadNpmTasks( 'grunt-eslint' );
grunt.loadNpmTasks( 'grunt-stylelint' );
grunt.loadNpmTasks( 'grunt-contrib-qunit' );
grunt.initConfig( {
jshint: {
options: {
jshintrc: true
eslint: {
all: [
'**/*.js',
'src/jquery.uls.data.js',
'!examples/**',
'!node_modules/**',
'!vendor/**'
]
},
all: ['*.js', 'src/*.js']
stylelint: {
options: {
syntax: 'css'
},
src: [
'**/*.css',
'!node_modules/**'
]
},
qunit: {
all: 'test/index.html'
}
} );
grunt.registerTask( 'lint', 'jshint' );
grunt.registerTask( 'lint', [ 'eslint' ] );
grunt.registerTask( 'test', [ 'lint', 'qunit' ] );
grunt.registerTask( 'default', 'test' );
};

View File

@@ -1,7 +1,7 @@
.uls-trigger {
background: url('../images/icon-language.png') no-repeat left center;
background: url( ../images/icon-language.png ) no-repeat left center;
/* @embed */
background-image: linear-gradient(transparent, transparent), url('../images/icon-language.svg');
background-image: linear-gradient( transparent, transparent ), url( ../images/icon-language.svg );
padding-left: 30px;
}
@@ -65,9 +65,9 @@
}
.uls-search-label {
background: url('../images/search.png') no-repeat center center;
background: url( ../images/search.png ) no-repeat center center;
/* @embed */
background-image: linear-gradient(transparent, transparent), url('../images/search.svg');
background-image: linear-gradient( transparent, transparent ), url( ../images/search.svg );
background-size: 20px;
height: 32px;
width: 44px;
@@ -88,7 +88,7 @@
width: 100%;
/* For the custom clear (X) icon */
padding: 6px 25px 6px 0;
outline: none;
outline: 0;
border: 0;
display: block;
position: absolute;
@@ -110,9 +110,9 @@
}
.uls-languagefilter-clear {
background: url('../images/clear.png') no-repeat left center;
background: url( ../images/clear.png ) no-repeat left center;
/* @embed */
background-image: linear-gradient(transparent, transparent), url('../images/clear.svg');
background-image: linear-gradient( transparent, transparent ), url( ../images/clear.svg );
background-size: 15px;
cursor: pointer;
height: 15px;

View File

@@ -32,15 +32,18 @@
}
.grid .highlight {
background: #ffff99;
background: #ff9;
}
/* The Grid ---------------------- */
.grid .row {
width: 100%;
max-width: none;
min-width: 600px;
margin: 0 auto;
/* Nicolas Gallagher's micro clearfix */
*zoom: 1;
}
.grid .row .row {
@@ -50,30 +53,25 @@
margin: 0 -5px;
}
.grid .column,
.grid .columns {
float: left;
min-height: 1px;
padding: 0 5px;
position: relative;
}
.grid .row.collapse .column,
.grid .row.collapse .columns {
padding: 0;
}
.grid .row .row {
width: auto;
max-width: none;
min-width: 0;
margin: 0 -5px;
}
.grid .row .row.collapse {
margin: 0;
}
.grid .column, .grid .columns {
float: left;
min-height: 1px;
padding: 0 5px;
position: relative;
}
.grid .column.centered, .grid .columns.centered {
.grid .column.centered,
.grid .columns.centered {
float: none;
margin: 0 auto;
}
@@ -238,13 +236,9 @@
right: 83.333%;
}
/* Nicolas Gallagher's micro clearfix */
.grid .row {
*zoom: 1;
}
.grid .row:before, .grid .row:after {
content: "";
.grid .row:before,
.grid .row:after {
content: '';
display: table;
}

View File

@@ -36,6 +36,16 @@
margin: 0;
}
.uls-language-block > ul {
/*
* We don't want any visible bullets in this list. Not by default anyway.
* Using very unspecific selector here to allow other classes to override.
* Bug because overflow: hidden is incompatible with bullets, also render
* the bullets inside the list in case there should be any.
*/
list-style: none none;
}
/*
* Each block should have 16px padding on both sides. But because we already gave
* 16px for the whole menu, we need to remove it for first and last items the blocks.
@@ -53,17 +63,6 @@
padding-right: 0;
}
.uls-language-block > ul {
/*
* We don't want any visible bullets in this list. Not by default anyway.
* Using very unspecific selector here to allow other classes to override.
* Bug because overflow: hidden is incompatible with bullets, also render
* the bullets inside the list in case there should be any.
*/
list-style: none none;
}
.uls-language-block > ul > li {
cursor: pointer;
margin-left: 20px;

View File

@@ -40,7 +40,7 @@
float: none;
}
.uls-mobile [class*="column"] + [class*="column"]:last-child {
.uls-mobile [ class*='column' ] + [ class*='column' ]:last-child {
float: none;
}
@@ -48,7 +48,7 @@
.uls-mobile .uls-mobile .columns:before,
.uls-mobile .column:after,
.columns:after {
content: "";
content: '';
display: table;
}
@@ -201,7 +201,8 @@
.uls-mobile .hide-for-small,
.uls-mobile .hide-for-medium,
.uls-mobile .hide-for-medium-down,
.hide-for-large, .show-for-large-up,
.hide-for-large,
.show-for-large-up,
.show-for-xlarge {
display: block !important;
}

View File

@@ -1,18 +1,18 @@
body {
padding-left: 10%;
padding-right: 10%;
font-family: Arial, Helvetica, sans-serif;
font-family: 'Arial', 'Helvetica', sans-serif;
}
div.navbar {
background-color: #333;
color: #FFFFFF;
color: #fff;
padding: 20px;
}
span.uls-trigger {
float: right;
cursor: pointer;
color: #FFFFFF;
color: #fff;
font-weight: bold;
}

View File

@@ -25,10 +25,13 @@
"Siebrand Mazeland"
],
"devDependencies": {
"eslint-config-wikimedia": "0.5.0",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-jshint": "^1.0.0",
"grunt-contrib-qunit": "^1.2.0"
"grunt-eslint": "20.0.0",
"grunt-stylelint": "0.8.0",
"stylelint": "8.2.0",
"grunt-contrib-qunit": "^1.2.0",
"stylelint-config-wikimedia": "0.4.2"
},
"repository": {
"type": "git",

View File

@@ -1,10 +1,11 @@
var through = require( 'through' );
var through = require( 'through' ); // eslint-disable-line no-implicit-globals
module.exports = function ( file ) {
module.exports = function () {
var data, end, write;
data = '( function ( $ ) {\n\t$.uls = $.uls || {};\n\t$.uls.data = ';
write = function ( buf ) {
return data += buf;
data += buf;
return data;
};
end = function () {
data += '\n} ( jQuery ) );';

View File

@@ -24,7 +24,7 @@
var template, ULS;
// Region numbers in id attributes also appear in the langdb.
/*jshint multistr:true */
// eslint-disable-next-line no-multi-str
template = '<div class="grid uls-menu"> \
<div id="search" class="row uls-search"> \
<div class="uls-search-wrapper"> \
@@ -43,42 +43,20 @@
<div class="row uls-language-list"></div>\
<div class="row" id="uls-settings-block"></div>\
</div>';
/*jshint multistr:false */
/**
* Count the number of keys in an object.
* Works in a cross-browser way.
* @param {Object} The object.
*/
function objectLength ( obj ) {
var count, key;
// Some old browsers don't support Object.keys
if ( Object.keys ) {
return Object.keys( obj ).length;
}
count = 0;
for ( key in obj ) {
if ( Object.prototype.hasOwnProperty.call( obj, key ) ) {
count++;
}
}
return count;
}
/**
* ULS Public class definition
* @param {Element} element
* @param {Object} options
*/
ULS = function ( element, options ) {
var code;
this.$element = $( element );
this.options = $.extend( {}, $.fn.uls.defaults, options );
this.$menu = $( template );
this.languages = this.options.languages;
for ( var code in this.languages ) {
for ( code in this.languages ) {
if ( $.uls.data.languages[ code ] === undefined ) {
// Language is unknown to ULS.
delete this.languages[ code ];
@@ -131,7 +109,7 @@
/**
* Calculate the position of ULS
* Returns an object with top and left properties.
* @returns {Object}
* @return {Object}
*/
position: function () {
var pos,
@@ -149,7 +127,6 @@
left = $( window ).width() / 2 - this.$menu.outerWidth() / 2;
}
return {
top: top,
left: left
@@ -255,7 +232,7 @@
this.$menu.on( 'keydown', $.proxy( this.keypress, this ) );
}
languagesCount = objectLength( this.options.languages );
languagesCount = Object.keys( this.options.languages ).length;
lcd = this.$resultsView.lcd( {
languages: this.languages,
columns: columnsOptions[ this.getMenuWidth() ],
@@ -282,7 +259,7 @@
/**
* On select handler for search results
* @param langCode
* @param {string} langCode
*/
select: function ( langCode ) {
this.hide();
@@ -293,6 +270,7 @@
/**
* On cancel handler for the uls menu
* @param {Event} e
*/
cancel: function ( e ) {
if ( e && ( this.$element.is( e.target ) || $.contains( this.$element[ 0 ], e.target ) ) ) {
@@ -347,7 +325,7 @@
/**
* Get the panel menu width parameter
* @return string
* @return {string}
*/
getMenuWidth: function () {
var languagesCount;
@@ -356,7 +334,7 @@
return this.options.menuWidth;
}
languagesCount = objectLength( this.options.languages );
languagesCount = Object.keys( this.options.languages ).length;
if ( languagesCount < 25 ) {
return 'narrow';

View File

@@ -22,8 +22,8 @@
/**
* Is this language a redirect to another language?
* @param language string Language code
* @return Target language code if it's a redirect or false if it's not
* @param {string} language Language code
* @return {string|boolean} Target language code if it's a redirect or false if it's not
*/
$.uls.data.isRedirect = function ( language ) {
return ( $.uls.data.languages[ language ] !== undefined &&
@@ -32,8 +32,8 @@
/**
* Returns the script of the language.
* @param language string Language code
* @return string
* @param {string} language Language code
* @return {string}
*/
$.uls.data.getScript = function ( language ) {
var target = $.uls.data.isRedirect( language );
@@ -52,8 +52,8 @@
/**
* Returns the regions in which a language is spoken.
* @param language string Language code
* @return array|string 'UNKNOWN'
* @param {string} language Language code
* @return {string|string[]}
*/
$.uls.data.getRegions = function ( language ) {
var target = $.uls.data.isRedirect( language );
@@ -67,8 +67,8 @@
/**
* Returns the autonym of the language.
* @param language string Language code
* @return string
* @param {string} language Language code
* @return {string}
*/
$.uls.data.getAutonym = function ( language ) {
var target = $.uls.data.isRedirect( language );
@@ -82,7 +82,7 @@
/**
* Returns all language codes and corresponding autonyms
* @return array
* @return {string[]}
*/
$.uls.data.getAutonyms = function () {
var language,
@@ -101,8 +101,8 @@
/**
* Returns all languages written in script.
* @param script string
* @return array of strings (languages codes)
* @param {string} script string
* @return {string[]} languages codes
*/
$.uls.data.getLanguagesInScript = function ( script ) {
return $.uls.data.getLanguagesInScripts( [ script ] );
@@ -110,8 +110,8 @@
/**
* Returns all languages written in the given scripts.
* @param scripts array of strings
* @return array of strings (languages codes)
* @param {string[]} scripts
* @return {string[]} languages codes
*/
$.uls.data.getLanguagesInScripts = function ( scripts ) {
var language, i,
@@ -136,8 +136,8 @@
/**
* Returns an associative array of languages in a region,
* grouped by script group.
* @param region string Region code
* @return associative array
* @param {string} region Region code
* @return {object}
*/
$.uls.data.getLanguagesByScriptGroupInRegion = function ( region ) {
return $.uls.data.getLanguagesByScriptGroupInRegions( [ region ] );
@@ -145,7 +145,7 @@
/**
* Get the given list of languages grouped by script.
* @param languages Array of language codes
* @param {string} languages Array of language codes
* @return {Object} Array of languages indexed by script codes
*/
$.uls.data.getLanguagesByScriptGroup = function ( languages ) {
@@ -170,8 +170,8 @@
/**
* Returns an associative array of languages in several regions,
* grouped by script group.
* @param regions array of strings - region codes
* @return associative array
* @param {string[]} regions region codes
* @return {Object}
*/
$.uls.data.getLanguagesByScriptGroupInRegions = function ( regions ) {
var language, i, scriptGroup,
@@ -202,8 +202,8 @@
/**
* Returns the script group of a script or 'Other' if it doesn't
* belong to any group.
* @param script string Script code
* @return string script group name
* @param {string} script Script code
* @return {string} script group name
*/
$.uls.data.getGroupOfScript = function ( script ) {
var scriptGroup;
@@ -219,8 +219,8 @@
/**
* Returns the script group of a language.
* @param language string Language code
* @return string script group name
* @param {string} language Language code
* @return {string} script group name
*/
$.uls.data.getScriptGroupOfLanguage = function ( language ) {
return $.uls.data.getGroupOfScript( $.uls.data.getScript( language ) );
@@ -229,8 +229,9 @@
/**
* A callback for sorting languages by autonym.
* Can be used as an argument to a sort function.
* @param a string Language code
* @param b string Language code
* @param {string} a Language code
* @param {string} b Language code
* @return {number}
*/
$.uls.data.sortByAutonym = function ( a, b ) {
var autonymA = $.uls.data.getAutonym( a ) || a,
@@ -241,8 +242,8 @@
/**
* Check if a language is right-to-left.
* @param language string Language code
* @return boolean
* @param {string} language Language code
* @return {boolean}
*/
$.uls.data.isRtl = function ( language ) {
return $.inArray( $.uls.data.getScript( language ), $.uls.data.rtlscripts ) !== -1;
@@ -250,8 +251,8 @@
/**
* Return the direction of the language
* @param language string Language code
* @return string
* @param {string} language Language code
* @return {string}
*/
$.uls.data.getDir = function ( language ) {
return $.uls.data.isRtl( language ) ? 'rtl' : 'ltr';
@@ -259,8 +260,8 @@
/**
* Returns the languages spoken in a territory.
* @param territory string Territory code
* @return list of language codes
* @param {string} territory Territory code
* @return {string[]} list of language codes
*/
$.uls.data.getLanguagesInTerritory = function ( territory ) {
return $.uls.data.territories[ territory ];
@@ -271,8 +272,8 @@
* If the target option is provided, the language is defined as a redirect.
* Other possible options are script, regions and autonym.
*
* @param code string New language code.
* @param options Object Language properties.
* @param {string} code New language code.
* @param {Object} options Language properties.
*/
$.uls.data.addLanguage = function ( code, options ) {
if ( options.target ) {
@@ -285,8 +286,8 @@
/**
* Removes a language from the langdb in run time.
*
* @param code string Language code to delete.
* @return true if the language was removed, false otherwise.
* @param {string} code Language code to delete.
* @return {boolean} true if the language was removed, false otherwise.
*/
$.uls.data.deleteLanguage = function ( code ) {
if ( $.uls.data.languages[ code ] ) {

View File

@@ -27,6 +27,20 @@
var LanguageFilter, delay;
/**
* Check if a prefix is visually prefix of a string
*
* @param {string} prefix
* @param {string} string
* @return {boolean}
*/
function isVisualPrefix( prefix, string ) {
// Pre-base vowel signs of Indic languages. A vowel sign is called pre-base if
// consonant + vowel becomes [vowel][consonant] when rendered. Eg: ക + െ => കെ
var prebases = 'െേൈൊോൌெேைொோௌେୈୋୌિਿिিেৈোৌෙේෛොෝෞ';
return prebases.indexOf( string[ prefix.length ] ) <= 0;
}
LanguageFilter = function ( element, options ) {
this.$element = $( element );
this.options = $.extend( {}, $.fn.languagefilter.defaults, options );
@@ -213,7 +227,7 @@
* Handler method to be called once search is over.
* Based on search result triggers resultsfound or noresults events
* @param {string} query
* @param {number} resultCount
* @param {string[]} results
* @param {string} [autofillLabel]
*/
resultHandler: function ( query, results, autofillLabel ) {
@@ -284,7 +298,7 @@
},
escapeRegex: function ( value ) {
return value.replace( /[\-\[\]{}()*+?.,\\\^$\|#\s]/g, '\\$&' );
return value.replace( /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&' );
},
/**
@@ -294,6 +308,9 @@
* b) Language autonym 'starts with' search string.
* c) ISO 639 code match with search string.
* d) ISO 15924 code for the script match the search string.
* @param {string} langCode
* @param {string} searchTerm
* @return {boolean}
*/
filter: function ( langCode, searchTerm ) {
// FIXME script is ISO 15924 code. We might need actual name of script.
@@ -343,16 +360,4 @@
$.fn.languagefilter.Constructor = LanguageFilter;
/**
* Check if a prefix is visually prefix of a string
*
* @param {string} prefix
* @param {string} string
*/
function isVisualPrefix( prefix, string ) {
// Pre-base vowel signs of Indic languages. A vowel sign is called pre-base if
// consonant + vowel becomes [vowel][consonant] when rendered. Eg: ക + െ => കെ
var prebases = 'െേൈൊോൌெேைொோௌେୈୋୌિਿिিেৈোৌෙේෛොෝෞ';
return prebases.indexOf( string[ prefix.length ] ) <= 0;
}
}( jQuery ) );

View File

@@ -287,7 +287,6 @@
a.lang = code;
a.dir = $.uls.data.getDir( code );
li.appendChild( a );
if ( this.options.languageDecorator ) {
this.options.languageDecorator( $( a ), code );
@@ -365,6 +364,7 @@
},
noResults: function () {
var $suggestions;
this.$noResults.removeClass( 'hide' );
this.$noResults.siblings( '.uls-lcd-region-section' ).addClass( 'hide' );
@@ -373,7 +373,7 @@
return;
}
var $suggestions = this.buildQuicklist().clone();
$suggestions = this.buildQuicklist().clone();
$suggestions.removeClass( 'hide' ).removeAttr( 'id' );
$suggestions.find( 'h3' )
.data( 'i18n', 'uls-no-results-suggestion-title' )

View File

@@ -13,8 +13,6 @@
*
*/
/*jshint sub:true */
( function ( $ ) {
'use strict';