From 4ec6b0cce19a93a2e9b8aca4b0911539d67b4534 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 30 Jan 2014 18:03:11 -0800 Subject: [PATCH] Set up node-jscs via Grunt (and pass it) * Set up Grunt via package.json (run `npm install` in mediawiki-core) * Add grunt task for node-jscs (NEW) This is a style checker (as opposed to jshint, which is for code quality). There are a few small style-related things that JSHint can check (camelcase, onevar etc.) but those are being deprecated in JSHint v3, people should use more sophisticated tools like node-jscs for this instead. As such this commit removes moves of those options from our jshint configuration. See: http://jshint.com/blog/jshint-3-plans/ * Add grunt task for jshint This will use the same jshint configuration as we use on Jenkins but makes it easier to run locally from the command line by being part of the same `$ grunt test` task list. Also: * Changed jshintignore to use "dir/**"" instead of "/dir" or "dir" because the latter is not compatible with Grunt for some reason. See also https://github.com/gruntjs/grunt-contrib-jshint/issues/126. Examples of coding style rules that were being violated that we can now catch in node-jscs: * Operator "," should stick to preceding expression * Missing space after "if" keyword * Multiple line break * Empty block (in jquery.textSelection and mediawiki.language) Bug: 54218 Change-Id: Ib9d7eab9f0d5cea5fb33f0b9f82e5554897fdfe0 --- .jscsrc | 30 + .jshintignore | 29 +- .jshintrc | 16 +- resources/jquery/jquery.autoEllipsis.js | 2 +- resources/jquery/jquery.byteLimit.js | 1 - resources/jquery/jquery.colorUtil.js | 20 +- resources/jquery/jquery.highlightText.js | 1 - resources/jquery/jquery.localize.js | 4 +- resources/jquery/jquery.placeholder.js | 39 +- .../jquery/jquery.qunit.completenessTest.js | 1 - resources/jquery/jquery.suggestions.js | 4 +- resources/jquery/jquery.tablesorter.js | 123 ++- resources/jquery/jquery.textSelection.js | 310 +++--- .../mediawiki.action.edit.editWarning.js | 1 - .../mediawiki.action/mediawiki.action.edit.js | 10 +- .../mediawiki.action.history.js | 1 - .../mediawiki.action.view.metadata.js | 2 +- .../mediawiki.api/mediawiki.api.category.js | 1 - resources/mediawiki.language/languages/fi.js | 2 +- resources/mediawiki.language/languages/hy.js | 2 +- resources/mediawiki.language/languages/la.js | 6 +- resources/mediawiki.language/languages/os.js | 2 +- resources/mediawiki.language/languages/uk.js | 36 +- .../mediawiki.language/mediawiki.language.js | 2 +- .../mediawiki.page/mediawiki.page.gallery.js | 15 +- .../mediawiki.page.image.pagination.js | 2 +- .../mediawiki.special.block.js | 1 - .../mediawiki.special.javaScriptTest.js | 1 - .../mediawiki.special.preferences.js | 4 +- .../mediawiki.special.upload.js | 3 +- resources/mediawiki/mediawiki.Title.js | 3 - resources/mediawiki/mediawiki.debug.js | 2 - resources/mediawiki/mediawiki.feedback.js | 9 +- resources/mediawiki/mediawiki.jqueryMsg.js | 14 +- skins/common/IEFixes.js | 4 +- skins/common/ajax.js | 13 +- skins/common/config.js | 2 +- skins/common/upload.js | 5 +- skins/common/wikibits.js | 2 +- skins/vector/vector.js | 2 +- tests/frontend/Gruntfile.js | 51 + tests/frontend/package.json | 13 + tests/qunit/data/generateJqueryMsgData.php | 1 - tests/qunit/data/mediawiki.jqueryMsg.data.js | 971 +++++++++--------- .../resources/jquery/jquery.color.test.js | 2 +- .../jquery/jquery.makeCollapsible.test.js | 2 +- .../jquery/jquery.placeholder.test.js | 20 +- .../jquery/jquery.textSelection.test.js | 28 +- .../mediawiki.api/mediawiki.api.test.js | 1 - .../mediawiki/mediawiki.Title.test.js | 49 +- .../mediawiki/mediawiki.jqueryMsg.test.js | 1 - .../resources/mediawiki/mediawiki.test.js | 10 +- 52 files changed, 980 insertions(+), 896 deletions(-) create mode 100644 .jscsrc create mode 100644 tests/frontend/Gruntfile.js create mode 100644 tests/frontend/package.json diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000000..b5481ea418 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,30 @@ +{ + "requireCurlyBraces": ["if", "else", "for", "while", "do"], + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "function"], + "requireParenthesesAroundIIFE": true, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "requireMultipleVarDecl": true, + "disallowEmptyBlocks": true, + "requireSpacesInsideObjectBrackets": "all", + "disallowSpaceAfterObjectKeys": true, + "requireCommaBeforeLineBreak": true, + "disallowLeftStickedOperators": ["?", ">", ">=", "<", "<="], + "disallowRightStickedOperators": ["?", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], + "requireRightStickedOperators": ["!"], + "requireLeftStickedOperators": [","], + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~"], + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + "disallowKeywords": [ "with" ], + "disallowMultipleLineBreaks": true, + "validateLineBreaks": "LF", + "validateQuoteMarks": "'", + "disallowMixedSpacesAndTabs": "smart", + "disallowTrailingWhitespace": true, + "requireLineFeedAtFileEnd": true, + "requireCapitalizedConstructors": true, + "requireDotNotation": true +} diff --git a/.jshintignore b/.jshintignore index a44a4d4476..627f7ab252 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,14 +1,14 @@ # Generated documentation -docs/html/ -docs/js/ -resources/mediawiki.ui/docs +docs/html/** +docs/js/** +resources/mediawiki.ui/docs/** # kss template for mediawiki ui documentation -resources/styleguide-template +resources/styleguide-template/** # third-party libs -extensions/ -node_modules/ +extensions/** +node_modules/** resources/jquery/jquery.appear.js resources/jquery/jquery.async.js resources/jquery/jquery.ba-throttle-debounce.js @@ -26,14 +26,15 @@ resources/jquery/jquery.qunit.js resources/jquery/jquery.validate.js resources/jquery/jquery.xmldom.js resources/jquery.chosen/chosen.jquery.js -resources/jquery.effects/ -resources/jquery.tipsy/ -resources/jquery.ui/ -resources/mediawiki.libs/ -resources/oojs/ -resources/oojs-ui/ -resources/sinonjs/ -resources/moment/ +resources/jquery.effects/** +resources/jquery.tipsy/** +resources/jquery.ui/** +resources/mediawiki.libs/** +resources/moment/** +resources/oojs-ui/** +resources/oojs/** +resources/sinonjs/** +tests/frontend/node_modules/** # github.com/jshint/jshint/issues/729 tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js diff --git a/.jshintrc b/.jshintrc index c4e265a4de..9d6c4d2180 100644 --- a/.jshintrc +++ b/.jshintrc @@ -2,24 +2,20 @@ /* Common */ // Enforcing - "camelcase": true, - "curly": true, "eqeqeq": true, - "immed": true, "latedef": true, - "newcap": true, "noarg": true, - "noempty": true, "nonew": true, - "quotmark": "single", - "trailing": true, "undef": true, "unused": true, - // Legacy - "onevar": true, /* Local */ + // FIXME: Deprecated, handle these with node-jscs instead. + // Handled here because we still have inline overrides in some places. + "camelcase": true, + "nomen": true, + // Enforcing "bitwise": true, "forin": false, @@ -31,8 +27,6 @@ "multistr": true, // Environment "browser": true, - // Legacy - "nomen": true, "predef": [ "mediaWiki", diff --git a/resources/jquery/jquery.autoEllipsis.js b/resources/jquery/jquery.autoEllipsis.js index 49a932a1e6..a473f615a0 100644 --- a/resources/jquery/jquery.autoEllipsis.js +++ b/resources/jquery/jquery.autoEllipsis.js @@ -146,4 +146,4 @@ $.fn.autoEllipsis = function ( options ) { } ); }; -}( jQuery ) ); \ No newline at end of file +}( jQuery ) ); diff --git a/resources/jquery/jquery.byteLimit.js b/resources/jquery/jquery.byteLimit.js index a8c0b06590..b398fdd192 100644 --- a/resources/jquery/jquery.byteLimit.js +++ b/resources/jquery/jquery.byteLimit.js @@ -189,7 +189,6 @@ $el.attr( 'maxlength', elLimit ); } - // Safe base value, used to determine the path between the previous state // and the state that triggered the event handler below - and enforce the // limit approppiately (e.g. don't chop from the end if text was inserted diff --git a/resources/jquery/jquery.colorUtil.js b/resources/jquery/jquery.colorUtil.js index 9c6f9ecbe1..37bf1767ad 100644 --- a/resources/jquery/jquery.colorUtil.js +++ b/resources/jquery/jquery.colorUtil.js @@ -12,7 +12,7 @@ // By Blair Mitchelmore // http://jquery.offput.ca/highlightFade/ // Parse strings looking for color tuples [255,255,255] - getRGB : function ( color ) { + getRGB: function ( color ) { /*jshint boss:true */ var result; @@ -28,7 +28,7 @@ // Look for rgb(num%,num%,num%) if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) { - return [parseFloat(result[1],10)*2.55, parseFloat(result[2],10)*2.55, parseFloat(result[3])*2.55]; + return [parseFloat(result[1],10) * 2.55, parseFloat(result[2],10) * 2.55, parseFloat(result[3]) * 2.55]; } // Look for #a0b1c2 @@ -38,7 +38,7 @@ // Look for #fff if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) { - return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; + return [parseInt(result[1] + result[1],16), parseInt(result[2] + result[2],16), parseInt(result[3] + result[3],16)]; } // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 @@ -170,23 +170,23 @@ if ( t > 1 ) { t -= 1; } - if ( t < 1/6 ) { + if ( t < 1 / 6 ) { return p + (q - p) * 6 * t; } - if ( t < 1/2 ) { + if ( t < 1 / 2 ) { return q; } - if ( t < 2/3 ) { - return p + (q - p) * (2/3 - t) * 6; + if ( t < 2 / 3 ) { + return p + (q - p) * (2 / 3 - t) * 6; } return p; }; q = l < 0.5 ? l * (1 + s) : l + s - l * s; p = 2 * l - q; - r = hue2rgb( p, q, h + 1/3 ); + r = hue2rgb( p, q, h + 1 / 3 ); g = hue2rgb( p, q, h ); - b = hue2rgb( p, q, h - 1/3 ); + b = hue2rgb( p, q, h - 1 / 3 ); } return [r * 255, g * 255, b * 255]; @@ -207,7 +207,7 @@ getColorBrightness: function ( currentColor, mod ) { var rgbArr = $.colorUtil.getRGB( currentColor ), hslArr = $.colorUtil.rgbToHsl(rgbArr[0], rgbArr[1], rgbArr[2] ); - rgbArr = $.colorUtil.hslToRgb(hslArr[0], hslArr[1], hslArr[2]+mod); + rgbArr = $.colorUtil.hslToRgb(hslArr[0], hslArr[1], hslArr[2] + mod); return 'rgb(' + [parseInt( rgbArr[0], 10), parseInt( rgbArr[1], 10 ), parseInt( rgbArr[2], 10 )].join( ',' ) + diff --git a/resources/jquery/jquery.highlightText.js b/resources/jquery/jquery.highlightText.js index cda2765b78..040815128a 100644 --- a/resources/jquery/jquery.highlightText.js +++ b/resources/jquery/jquery.highlightText.js @@ -66,4 +66,3 @@ }; }( jQuery ) ); - diff --git a/resources/jquery/jquery.localize.js b/resources/jquery/jquery.localize.js index e0d9de2bc4..8c8fb5626d 100644 --- a/resources/jquery/jquery.localize.js +++ b/resources/jquery/jquery.localize.js @@ -146,12 +146,12 @@ $.fn.localize = function ( options ) { } ); // HTML, Text for elements which cannot have children e.g. OPTION - $target.find( '[data-msg-text]' ).each( function() { + $target.find( '[data-msg-text]' ).each( function () { var $el = $( this ); $el.text( msg( options, $el.attr( 'data-msg-text' ) ) ); } ); - $target.find( '[data-msg-html]' ).each( function() { + $target.find( '[data-msg-html]' ).each( function () { var $el = $( this ); $el.html( msg( options, $el.attr( 'data-msg-html' ) ) ); } ); diff --git a/resources/jquery/jquery.placeholder.js b/resources/jquery/jquery.placeholder.js index 5020b37a67..6f7ada3166 100644 --- a/resources/jquery/jquery.placeholder.js +++ b/resources/jquery/jquery.placeholder.js @@ -13,7 +13,7 @@ * @version 2.1.0 * @license MIT */ -(function($) { +(function ($) { var isInputSupported = 'placeholder' in document.createElement('input'), isTextareaSupported = 'placeholder' in document.createElement('textarea'), @@ -25,10 +25,10 @@ if (isInputSupported && isTextareaSupported) { - placeholder = prototype.placeholder = function(text) { + placeholder = prototype.placeholder = function (text) { var hasArgs = arguments.length; - if( hasArgs ) { + if (hasArgs) { changePlaceholder.call(this, text); } @@ -39,18 +39,17 @@ } else { - placeholder = prototype.placeholder = function(text) { + placeholder = prototype.placeholder = function (text) { var $this = this, hasArgs = arguments.length; - if(hasArgs) { + if (hasArgs) { changePlaceholder.call(this, text); } - $this .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]') - .filter(function() { + .filter(function () { return !$(this).data('placeholder-enabled'); }) .bind({ @@ -66,7 +65,7 @@ placeholder.textarea = isTextareaSupported; hooks = { - 'get': function(element) { + 'get': function (element) { var $element = $(element), $passwordInput = $element.data('placeholder-password'); if ($passwordInput) { @@ -75,7 +74,7 @@ return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value; }, - 'set': function(element, value) { + 'set': function (element, value) { var $element = $(element), $passwordInput = $element.data('placeholder-password'); if ($passwordInput) { @@ -95,7 +94,7 @@ setPlaceholder.call(element); } } else if ($element.hasClass('placeholder')) { - if(!clearPlaceholder.call(element, true, value)) { + if (!clearPlaceholder.call(element, true, value)) { element.value = value; } } else { @@ -115,20 +114,20 @@ propHooks.value = hooks; } - $(function() { + $(function () { // Look for forms - $(document).delegate('form', 'submit.placeholder', function() { + $(document).delegate('form', 'submit.placeholder', function () { // Clear the placeholder values so they don't get submitted var $inputs = $('.placeholder', this).each(clearPlaceholder); - setTimeout(function() { + setTimeout(function () { $inputs.each(setPlaceholder); }, 10); }); }); // Clear placeholder values upon page reload - $(window).bind('beforeunload.placeholder', function() { - $('.placeholder').each(function() { + $(window).bind('beforeunload.placeholder', function () { + $('.placeholder').each(function () { this.value = ''; }); }); @@ -139,7 +138,7 @@ // Return an object of element attributes var newAttrs = {}, rinlinejQuery = /^jQuery\d+$/; - $.each(elem.attributes, function(i, attr) { + $.each(elem.attributes, function (i, attr) { if (attr.specified && !rinlinejQuery.test(attr.name)) { newAttrs[attr.name] = attr.value; } @@ -162,7 +161,7 @@ } else { input.value = ''; $input.removeClass('placeholder'); - if(input === safeActiveElement()) { + if (input === safeActiveElement()) { input.select(); } } @@ -217,10 +216,10 @@ function changePlaceholder(text) { var hasArgs = arguments.length, $input = this; - if(hasArgs) { - if($input.attr('placeholder') !== text) { + if (hasArgs) { + if ($input.attr('placeholder') !== text) { $input.prop('placeholder', text); - if($input.hasClass('placeholder')) { + if ($input.hasClass('placeholder')) { $input[0].value = text; } } diff --git a/resources/jquery/jquery.qunit.completenessTest.js b/resources/jquery/jquery.qunit.completenessTest.js index 20e6678e94..86fcaea309 100644 --- a/resources/jquery/jquery.qunit.completenessTest.js +++ b/resources/jquery/jquery.qunit.completenessTest.js @@ -79,7 +79,6 @@ isEmptyObject: $.isEmptyObject }; - /** * CompletenessTest * @constructor diff --git a/resources/jquery/jquery.suggestions.js b/resources/jquery/jquery.suggestions.js index f967a1d478..f9a225fd52 100644 --- a/resources/jquery/jquery.suggestions.js +++ b/resources/jquery/jquery.suggestions.js @@ -142,7 +142,7 @@ $.suggestions = { i, expWidth, matchedText, maxWidth, text; // Validate creation using fallback values - switch( property ) { + switch ( property ) { case 'fetch': case 'cancel': case 'special': @@ -281,7 +281,7 @@ $.suggestions = { } // Apply new width for results box, if any if ( expWidth > context.data.$container.width() ) { - maxWidth = context.config.maxExpandFactor*context.data.$textbox.width(); + maxWidth = context.config.maxExpandFactor * context.data.$textbox.width(); context.data.$container.width( Math.min( expWidth, maxWidth ) ); } // autoEllipse the results. Has to be done after changing the width diff --git a/resources/jquery/jquery.tablesorter.js b/resources/jquery/jquery.tablesorter.js index f9ee2680a9..af0d897b97 100644 --- a/resources/jquery/jquery.tablesorter.js +++ b/resources/jquery/jquery.tablesorter.js @@ -68,8 +68,6 @@ */ ( function ( $, mw ) { - /*jshint onevar:false */ - /* Local scope */ var ts, @@ -78,8 +76,9 @@ /* Parser utility functions */ function getParserById( name ) { - var len = parsers.length; - for ( var i = 0; i < len; i++ ) { + var i, + len = parsers.length; + for ( i = 0; i < len; i++ ) { if ( parsers[i].id.toLowerCase() === name.toLowerCase() ) { return parsers[i]; } @@ -228,18 +227,19 @@ } function appendToTable( table, cache ) { - var row = cache.row, + var i, pos, l, j, + row = cache.row, normalized = cache.normalized, totalRows = normalized.length, checkCell = ( normalized[0].length - 1 ), fragment = document.createDocumentFragment(); - for ( var i = 0; i < totalRows; i++ ) { - var pos = normalized[i][checkCell]; + for ( i = 0; i < totalRows; i++ ) { + pos = normalized[i][checkCell]; - var l = row[pos].length; + l = row[pos].length; - for ( var j = 0; j < l; j++ ) { + for ( j = 0; j < l; j++ ) { fragment.appendChild( row[pos][j] ); } @@ -260,11 +260,12 @@ * @param $table jQuery object for a */ function emulateTHeadAndFoot( $table ) { - var $rows = $table.find( '> tbody > tr' ); - if( !$table.get(0).tHead ) { - var $thead = $( '' ); + var $thead, $tfoot, i, len, + $rows = $table.find( '> tbody > tr' ); + if ( !$table.get(0).tHead ) { + $thead = $( '' ); $rows.each( function () { - if ( $(this).children( 'td' ).length > 0 ) { + if ( $(this).children( 'td' ).length ) { // This row contains a ' ); - var len = $rows.length; - for ( var i = len-1; i >= 0; i-- ) { - if( $( $rows[i] ).children( 'td' ).length > 0 ){ + if ( !$table.get(0).tFoot ) { + $tfoot = $( '' ); + len = $rows.length; + for ( i = len - 1; i >= 0; i-- ) { + if ( $( $rows[i] ).children( 'td' ).length ){ break; } $tfoot.prepend( $( $rows[i] )); @@ -424,7 +425,6 @@ return false; } - function uniqueElements( array ) { var uniques = []; $.each( array, function( index, elem ) { @@ -455,14 +455,15 @@ } function multisort( table, sortList, cache ) { - var sortFn = []; - var len = sortList.length; - for ( var i = 0; i < len; i++ ) { + var i, + sortFn = [], + len = sortList.length; + for ( i = 0; i < len; i++ ) { sortFn[i] = ( sortList[i][1] ) ? sortTextDesc : sortText; } cache.normalized.sort( function ( array1, array2 ) { - var col, ret; - for ( var i = 0; i < len; i++ ) { + var i, col, ret; + for ( i = 0; i < len; i++ ) { col = sortList[i][0]; ret = sortFn[i].call( this, array1[col], array2[col] ); if ( ret !== 0 ) { @@ -476,25 +477,27 @@ } function buildTransformTable() { - var digits = '0123456789,.'.split( '' ); - var separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ); - var digitTransformTable = mw.config.get( 'wgDigitTransformTable' ); + var ascii, localised, i, digitClass, + digits = '0123456789,.'.split( '' ), + separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ), + digitTransformTable = mw.config.get( 'wgDigitTransformTable' ); + if ( separatorTransformTable === null || ( separatorTransformTable[0] === '' && digitTransformTable[2] === '' ) ) { ts.transformTable = false; } else { ts.transformTable = {}; // Unpack the transform table - var ascii = separatorTransformTable[0].split( '\t' ).concat( digitTransformTable[0].split( '\t' ) ); - var localised = separatorTransformTable[1].split( '\t' ).concat( digitTransformTable[1].split( '\t' ) ); + ascii = separatorTransformTable[0].split( '\t' ).concat( digitTransformTable[0].split( '\t' ) ); + localised = separatorTransformTable[1].split( '\t' ).concat( digitTransformTable[1].split( '\t' ) ); // Construct regex for number identification - for ( var i = 0; i < ascii.length; i++ ) { + for ( i = 0; i < ascii.length; i++ ) { ts.transformTable[localised[i]] = ascii[i]; digits.push( $.escapeRE( localised[i] ) ); } } - var digitClass = '[' + digits.join( '', digits ) + ']'; + digitClass = '[' + digits.join( '', digits ) + ']'; // We allow a trailing percent sign, which we just strip. This works fine // if percents and regular numbers aren't being mixed. @@ -504,11 +507,13 @@ } function buildDateTable() { - var regex = []; + var i, name, + regex = []; + ts.monthNames = {}; - for ( var i = 0; i < 12; i++ ) { - var name = mw.language.months.names[i].toLowerCase(); + for ( i = 0; i < 12; i++ ) { + name = mw.language.months.names[i].toLowerCase(); ts.monthNames[name] = i + 1; regex.push( $.escapeRE( name ) ); name = mw.language.months.genitive[i].toLowerCase(); @@ -541,7 +546,9 @@ * @param $table jQuery object for a
, so it's not a header row // Stop here return false; @@ -273,11 +274,11 @@ } ); $table.find(' > tbody:first').before( $thead ); } - if( !$table.get(0).tFoot ) { - var $tfoot = $( '
*/ function explodeRowspans( $table ) { - var rowspanCells = $table.find( '> tbody > tr > [rowspan]' ).get(); + var spanningRealCellIndex, rowSpan, colSpan, + cell, i, $tds, $clone, $nextRows, + rowspanCells = $table.find( '> tbody > tr > [rowspan]' ).get(); // Short circuit if ( !rowspanCells.length ) { @@ -552,9 +559,10 @@ // account colspans. We also cache the rowIndex to avoid having to take // cell.parentNode.rowIndex in the sorting function below. $table.find( '> tbody > tr' ).each( function () { - var col = 0; - var l = this.cells.length; - for ( var i = 0; i < l; i++ ) { + var i, + col = 0, + l = this.cells.length; + for ( i = 0; i < l; i++ ) { this.cells[i].realCellIndex = col; this.cells[i].realRowIndex = this.rowIndex; col += this.cells[i].colSpan; @@ -579,7 +587,6 @@ } resortCells(); - var spanningRealCellIndex, rowSpan, colSpan; function filterfunc() { return this.realCellIndex >= spanningRealCellIndex; } @@ -596,15 +603,15 @@ resortCells(); } - var cell = rowspanCells.shift(); + cell = rowspanCells.shift(); rowSpan = cell.rowSpan; colSpan = cell.colSpan; spanningRealCellIndex = cell.realCellIndex; cell.rowSpan = 1; - var $nextRows = $( cell ).parent().nextAll(); - for ( var i = 0; i < rowSpan - 1; i++ ) { - var $tds = $( $nextRows[i].cells ).filter( filterfunc ); - var $clone = $( cell ).clone(); + $nextRows = $( cell ).parent().nextAll(); + for ( i = 0; i < rowSpan - 1; i++ ) { + $tds = $( $nextRows[i].cells ).filter( filterfunc ); + $clone = $( cell ).clone(); $clone[0].realCellIndex = spanningRealCellIndex; if ( $tds.length ) { $tds.each( fixTdCellIndex ); @@ -620,15 +627,17 @@ ts.collationTable = mw.config.get( 'tableSorterCollation' ); ts.collationRegex = null; if ( ts.collationTable ) { - var keys = []; + var key, + keys = []; // Build array of key names - for ( var key in ts.collationTable ) { - if ( ts.collationTable.hasOwnProperty(key) ) { //to be safe + for ( key in ts.collationTable ) { + // Check hasOwn to be safe + if ( ts.collationTable.hasOwnProperty(key) ) { keys.push(key); } } - if (keys.length) { + if ( keys.length ) { ts.collationRegex = new RegExp( '[' + keys.join( '' ) + ']', 'ig' ); } } @@ -714,7 +723,7 @@ construct: function ( $tables, settings ) { return $tables.each( function ( i, table ) { // Declare and cache. - var $headers, cache, config, + var $headers, cache, config, sortCSS, sortMsg, $table = $( table ), firstTime = true; @@ -745,8 +754,8 @@ $.data( table, 'tablesorter', { config: config } ); // Get the CSS class names, could be done else where. - var sortCSS = [ config.cssDesc, config.cssAsc ]; - var sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ]; + sortCSS = [ config.cssDesc, config.cssAsc ]; + sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ]; // Build headers $headers = buildHeaders( table, sortMsg ); @@ -819,15 +828,17 @@ this.order = this.count % 2; this.count++; - var cell = this; + var cell, columns, newSortList, i; + + cell = this; // Get current column index - var columns = table.headerToColumns[ this.headerIndex ]; - var newSortList = $.map( columns, function (c) { + columns = table.headerToColumns[ this.headerIndex ]; + newSortList = $.map( columns, function ( c ) { // jQuery "helpfully" flattens the arrays... return [[c, cell.order]]; }); // Index of first column belonging to this header - var i = columns[0]; + i = columns[0]; if ( !e[config.sortMultiSortKey] ) { // User only wants to sort on one column set @@ -886,7 +897,7 @@ * * @param sortList {Array} (optional) List of sort objects. */ - $table.data( 'tablesorter' ).sort = function( sortList ) { + $table.data( 'tablesorter' ).sort = function ( sortList ) { if ( firstTime ) { setupForFirstSort(); diff --git a/resources/jquery/jquery.textSelection.js b/resources/jquery/jquery.textSelection.js index 2b5a44068d..7262fe6e74 100644 --- a/resources/jquery/jquery.textSelection.js +++ b/resources/jquery/jquery.textSelection.js @@ -2,8 +2,6 @@ * These plugins provide extra functionality for interaction with textareas. */ ( function ( $ ) { - /*jshint noempty:false */ - if ( document.selection && document.selection.createRange ) { // On IE, patch the focus() method to restore the windows' scroll position // (bug 32241) @@ -13,7 +11,7 @@ var $w, state, result; if ( arguments.length === 0 ) { $w = $( window ); - state = {top: $w.scrollTop(), left: $w.scrollLeft()}; + state = { top: $w.scrollTop(), left: $w.scrollLeft() }; result = jqFocus.apply( this, arguments ); window.scrollTo( state.top, state.left ); return result; @@ -73,7 +71,6 @@ el = this.get( 0 ); if ( $(el).is( ':hidden' ) ) { - // Do nothing retval = ''; } else if ( document.selection && document.selection.createRange ) { activateElementOnIE( el ); @@ -143,108 +140,109 @@ } isSample = false; - if ( this.style.display === 'none' ) { - // Do nothing - } else if ( document.selection && document.selection.createRange ) { - // IE + // Do nothing if display none + if ( this.style.display !== 'none' ) { + if ( document.selection && document.selection.createRange ) { + // IE - // Note that IE9 will trigger the next section unless we check this first. - // See bug 35201. + // Note that IE9 will trigger the next section unless we check this first. + // See bug 35201. - activateElementOnIE( this ); - if ( context ) { - context.fn.restoreCursorAndScrollTop(); - } - if ( options.selectionStart !== undefined ) { - $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } ); - } + activateElementOnIE( this ); + if ( context ) { + context.fn.restoreCursorAndScrollTop(); + } + if ( options.selectionStart !== undefined ) { + $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } ); + } - selText = $(this).textSelection( 'getSelection' ); - scrollTop = this.scrollTop; - range = document.selection.createRange(); + selText = $(this).textSelection( 'getSelection' ); + scrollTop = this.scrollTop; + range = document.selection.createRange(); - checkSelectedText(); - insertText = pre + selText + post; - if ( options.splitlines ) { - insertText = doSplitLines( selText, pre, post ); - } - if ( options.ownline && range.moveStart ) { - range2 = document.selection.createRange(); - range2.collapse(); - range2.moveStart( 'character', -1 ); - // FIXME: Which check is correct? - if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) { - insertText = '\n' + insertText; - pre += '\n'; + checkSelectedText(); + insertText = pre + selText + post; + if ( options.splitlines ) { + insertText = doSplitLines( selText, pre, post ); } - range3 = document.selection.createRange(); - range3.collapse( false ); - range3.moveEnd( 'character', 1 ); - if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) { - insertText += '\n'; - post += '\n'; + if ( options.ownline && range.moveStart ) { + range2 = document.selection.createRange(); + range2.collapse(); + range2.moveStart( 'character', -1 ); + // FIXME: Which check is correct? + if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) { + insertText = '\n' + insertText; + pre += '\n'; + } + range3 = document.selection.createRange(); + range3.collapse( false ); + range3.moveEnd( 'character', 1 ); + if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) { + insertText += '\n'; + post += '\n'; + } } - } - range.text = insertText; - if ( isSample && options.selectPeri && range.moveStart ) { - range.moveStart( 'character', - post.length - selText.length ); - range.moveEnd( 'character', - post.length ); - } - range.select(); - // Restore the scroll position - this.scrollTop = scrollTop; - } else if ( this.selectionStart || this.selectionStart === 0 ) { - // Mozilla/Opera - - $(this).focus(); - if ( options.selectionStart !== undefined ) { - $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } ); - } + range.text = insertText; + if ( isSample && options.selectPeri && range.moveStart ) { + range.moveStart( 'character', -post.length - selText.length ); + range.moveEnd( 'character', -post.length ); + } + range.select(); + // Restore the scroll position + this.scrollTop = scrollTop; + } else if ( this.selectionStart || this.selectionStart === 0 ) { + // Mozilla/Opera + + $(this).focus(); + if ( options.selectionStart !== undefined ) { + $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } ); + } - selText = $(this).textSelection( 'getSelection' ); - startPos = this.selectionStart; - endPos = this.selectionEnd; - scrollTop = this.scrollTop; - checkSelectedText(); - if ( options.selectionStart !== undefined - && endPos - startPos !== options.selectionEnd - options.selectionStart ) - { - // This means there is a difference in the selection range returned by browser and what we passed. - // This happens for Chrome in the case of composite characters. Ref bug #30130 - // Set the startPos to the correct position. - startPos = options.selectionStart; - } + selText = $(this).textSelection( 'getSelection' ); + startPos = this.selectionStart; + endPos = this.selectionEnd; + scrollTop = this.scrollTop; + checkSelectedText(); + if ( options.selectionStart !== undefined + && endPos - startPos !== options.selectionEnd - options.selectionStart ) + { + // This means there is a difference in the selection range returned by browser and what we passed. + // This happens for Chrome in the case of composite characters. Ref bug #30130 + // Set the startPos to the correct position. + startPos = options.selectionStart; + } - insertText = pre + selText + post; - if ( options.splitlines ) { - insertText = doSplitLines( selText, pre, post ); - } - if ( options.ownline ) { - if ( startPos !== 0 && this.value.charAt( startPos - 1 ) !== '\n' && this.value.charAt( startPos - 1 ) !== '\r' ) { - insertText = '\n' + insertText; - pre += '\n'; + insertText = pre + selText + post; + if ( options.splitlines ) { + insertText = doSplitLines( selText, pre, post ); } - if ( this.value.charAt( endPos ) !== '\n' && this.value.charAt( endPos ) !== '\r' ) { - insertText += '\n'; - post += '\n'; + if ( options.ownline ) { + if ( startPos !== 0 && this.value.charAt( startPos - 1 ) !== '\n' && this.value.charAt( startPos - 1 ) !== '\r' ) { + insertText = '\n' + insertText; + pre += '\n'; + } + if ( this.value.charAt( endPos ) !== '\n' && this.value.charAt( endPos ) !== '\r' ) { + insertText += '\n'; + post += '\n'; + } + } + this.value = this.value.substring( 0, startPos ) + insertText + + this.value.substring( endPos, this.value.length ); + // Setting this.value scrolls the textarea to the top, restore the scroll position + this.scrollTop = scrollTop; + if ( window.opera ) { + pre = pre.replace( /\r?\n/g, '\r\n' ); + selText = selText.replace( /\r?\n/g, '\r\n' ); + post = post.replace( /\r?\n/g, '\r\n' ); + } + if ( isSample && options.selectPeri && !options.splitlines ) { + this.selectionStart = startPos + pre.length; + this.selectionEnd = startPos + pre.length + selText.length; + } else { + this.selectionStart = startPos + insertText.length; + this.selectionEnd = this.selectionStart; } - } - this.value = this.value.substring( 0, startPos ) + insertText + - this.value.substring( endPos, this.value.length ); - // Setting this.value scrolls the textarea to the top, restore the scroll position - this.scrollTop = scrollTop; - if ( window.opera ) { - pre = pre.replace( /\r?\n/g, '\r\n' ); - selText = selText.replace( /\r?\n/g, '\r\n' ); - post = post.replace( /\r?\n/g, '\r\n' ); - } - if ( isSample && options.selectPeri && !options.splitlines ) { - this.selectionStart = startPos + pre.length; - this.selectionEnd = startPos + pre.length + selText.length; - } else { - this.selectionStart = startPos + insertText.length; - this.selectionEnd = this.selectionStart; } } $(this).trigger( 'encapsulateSelection', [ options.pre, options.peri, options.post, options.ownline, @@ -366,35 +364,36 @@ setSelection: function ( options ) { return this.each( function () { var selection, length, newLines; - if ( $(this).is( ':hidden' ) ) { - // Do nothing - } else if ( this.selectionStart || this.selectionStart === 0 ) { - // Opera 9.0 doesn't allow setting selectionStart past - // selectionEnd; any attempts to do that will be ignored - // Make sure to set them in the right order - if ( options.start > this.selectionEnd ) { - this.selectionEnd = options.end; - this.selectionStart = options.start; - } else { - this.selectionStart = options.start; - this.selectionEnd = options.end; - } - } else if ( document.body.createTextRange ) { - selection = rangeForElementIE( this ); - length = this.value.length; - // IE doesn't count \n when computing the offset, so we won't either - newLines = this.value.match( /\n/g ); - if ( newLines ) { - length = length - newLines.length; + // Do nothing if hidden + if ( !$(this).is( ':hidden' ) ) { + if ( this.selectionStart || this.selectionStart === 0 ) { + // Opera 9.0 doesn't allow setting selectionStart past + // selectionEnd; any attempts to do that will be ignored + // Make sure to set them in the right order + if ( options.start > this.selectionEnd ) { + this.selectionEnd = options.end; + this.selectionStart = options.start; + } else { + this.selectionStart = options.start; + this.selectionEnd = options.end; + } + } else if ( document.body.createTextRange ) { + selection = rangeForElementIE( this ); + length = this.value.length; + // IE doesn't count \n when computing the offset, so we won't either + newLines = this.value.match( /\n/g ); + if ( newLines ) { + length = length - newLines.length; + } + selection.moveStart( 'character', options.start ); + selection.moveEnd( 'character', -length + options.end ); + + // This line can cause an error under certain circumstances (textarea empty, no selection) + // Silence that error + try { + selection.select(); + } catch ( e ) { } } - selection.moveStart( 'character', options.start ); - selection.moveEnd( 'character', -length + options.end ); - - // This line can cause an error under certain circumstances (textarea empty, no selection) - // Silence that error - try { - selection.select(); - } catch ( e ) { } } }); }, @@ -461,40 +460,41 @@ } return this.each(function () { var scroll, range, savedRange, pos, oldScrollTop; - if ( $(this).is( ':hidden' ) ) { - // Do nothing - } else if ( this.selectionStart || this.selectionStart === 0 ) { - // Mozilla - scroll = getCaretScrollPosition( this ); - if ( options.force || scroll < $(this).scrollTop() || - scroll > $(this).scrollTop() + $(this).height() ) { - $(this).scrollTop( scroll ); - } - } else if ( document.selection && document.selection.createRange ) { - // IE / Opera - /* - * IE automatically scrolls the selected text to the - * bottom of the textarea at range.select() time, except - * if it was already in view and the cursor position - * wasn't changed, in which case it does nothing. To - * cover that case, we'll force it to act by moving one - * character back and forth. - */ - range = document.body.createTextRange(); - savedRange = document.selection.createRange(); - pos = $(this).textSelection( 'getCaretPosition' ); - oldScrollTop = this.scrollTop; - range.moveToElementText( this ); - range.collapse(); - range.move( 'character', pos + 1); - range.select(); - if ( this.scrollTop !== oldScrollTop ) { - this.scrollTop += range.offsetTop; - } else if ( options.force ) { - range.move( 'character', -1 ); + // Do nothing if hidden + if ( !$(this).is( ':hidden' ) ) { + if ( this.selectionStart || this.selectionStart === 0 ) { + // Mozilla + scroll = getCaretScrollPosition( this ); + if ( options.force || scroll < $(this).scrollTop() || + scroll > $(this).scrollTop() + $(this).height() ) { + $(this).scrollTop( scroll ); + } + } else if ( document.selection && document.selection.createRange ) { + // IE / Opera + /* + * IE automatically scrolls the selected text to the + * bottom of the textarea at range.select() time, except + * if it was already in view and the cursor position + * wasn't changed, in which case it does nothing. To + * cover that case, we'll force it to act by moving one + * character back and forth. + */ + range = document.body.createTextRange(); + savedRange = document.selection.createRange(); + pos = $(this).textSelection( 'getCaretPosition' ); + oldScrollTop = this.scrollTop; + range.moveToElementText( this ); + range.collapse(); + range.move( 'character', pos + 1); range.select(); + if ( this.scrollTop !== oldScrollTop ) { + this.scrollTop += range.offsetTop; + } else if ( options.force ) { + range.move( 'character', -1 ); + range.select(); + } + savedRange.select(); } - savedRange.select(); } $(this).trigger( 'scrollToPosition' ); } ); diff --git a/resources/mediawiki.action/mediawiki.action.edit.editWarning.js b/resources/mediawiki.action/mediawiki.action.edit.editWarning.js index 2bab5b3056..f8448e60a2 100644 --- a/resources/mediawiki.action/mediawiki.action.edit.editWarning.js +++ b/resources/mediawiki.action/mediawiki.action.edit.editWarning.js @@ -53,4 +53,3 @@ } ); }( mediaWiki, jQuery ) ); - diff --git a/resources/mediawiki.action/mediawiki.action.edit.js b/resources/mediawiki.action/mediawiki.action.edit.js index 299fabdc95..bbffe79a64 100644 --- a/resources/mediawiki.action/mediawiki.action.edit.js +++ b/resources/mediawiki.action/mediawiki.action.edit.js @@ -27,12 +27,12 @@ }; } var $image = $( '' ).attr( { - width : 23, + width: 23, height: 22, - src : b.imageFile, - alt : b.speedTip, - title : b.speedTip, - id : b.imageId || undefined, + src: b.imageFile, + alt: b.speedTip, + title: b.speedTip, + id: b.imageId || undefined, 'class': 'mw-toolbar-editbutton' } ).click( function () { toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText ); diff --git a/resources/mediawiki.action/mediawiki.action.history.js b/resources/mediawiki.action/mediawiki.action.history.js index 500a47a2be..2a02d8711e 100644 --- a/resources/mediawiki.action/mediawiki.action.history.js +++ b/resources/mediawiki.action/mediawiki.action.history.js @@ -70,7 +70,6 @@ jQuery( function ( $ ) { // Set initial state updateDiffRadios(); - // Prettify url output for HistoryAction submissions, // to cover up action=historysubmit construction. diff --git a/resources/mediawiki.action/mediawiki.action.view.metadata.js b/resources/mediawiki.action/mediawiki.action.view.metadata.js index d23a937bac..21f40c5bdf 100644 --- a/resources/mediawiki.action/mediawiki.action.view.metadata.js +++ b/resources/mediawiki.action/mediawiki.action.view.metadata.js @@ -44,4 +44,4 @@ $table.addClass( 'collapsed' ); } ); -}( mediaWiki, jQuery ) ); \ No newline at end of file +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.category.js b/resources/mediawiki.api/mediawiki.api.category.js index 026052c5d7..4321b1b478 100644 --- a/resources/mediawiki.api/mediawiki.api.category.js +++ b/resources/mediawiki.api/mediawiki.api.category.js @@ -84,7 +84,6 @@ .promise( { abort: apiPromise.abort } ); }, - /** * Get the categories that a particular page on the wiki belongs to * @param {mw.Title} title diff --git a/resources/mediawiki.language/languages/fi.js b/resources/mediawiki.language/languages/fi.js index 2410091bf1..2382aae4c0 100644 --- a/resources/mediawiki.language/languages/fi.js +++ b/resources/mediawiki.language/languages/fi.js @@ -34,7 +34,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { break; case 'illative': // Double the last letter and add 'n' - word += word.substr( word.length-1 ) + 'n'; + word += word.substr( word.length - 1 ) + 'n'; break; case 'inessive': word += ( aou ? 'ssa' : 'ssä' ); diff --git a/resources/mediawiki.language/languages/hy.js b/resources/mediawiki.language/languages/hy.js index d1ed041bd1..ae16f247d9 100644 --- a/resources/mediawiki.language/languages/hy.js +++ b/resources/mediawiki.language/languages/hy.js @@ -15,7 +15,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { switch ( form ) { case 'genitive': // Õ½Õ¥Õ¼Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ¬Õ¸Õ¾ if ( word.substr( -1 ) === 'Õ¡' ) { - word = word.substr( 0, word.length -1 ) + 'Õ¡ÕµÕ«'; + word = word.substr( 0, word.length - 1 ) + 'Õ¡ÕµÕ«'; } else if ( word.substr( -1 ) === 'Õ¸' ) { word = word.substr( 0, word.length - 1 ) + 'Õ¸ÕµÕ«'; } else if ( word.substr( -4 ) === 'գիրք' ) { diff --git a/resources/mediawiki.language/languages/la.js b/resources/mediawiki.language/languages/la.js index 7fc171df9f..04b7d0a22b 100644 --- a/resources/mediawiki.language/languages/la.js +++ b/resources/mediawiki.language/languages/la.js @@ -19,7 +19,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { word = word.replace( /tio$/i,'tionis' ); // 3rd declension singular (partly) word = word.replace( /ns$/i, 'ntis' ); word = word.replace( /as$/i, 'atis' ); - word = word.replace( /es$/i ,'ei' ); // 5th declension singular + word = word.replace( /es$/i, 'ei' ); // 5th declension singular break; case 'accusative': // only a few declensions, and even for those mostly the singular only @@ -31,7 +31,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { word = word.replace( /tio$/i,'tionem' ); // 3rd declension singular (partly) word = word.replace( /ns$/i, 'ntem' ); word = word.replace( /as$/i, 'atem'); - word = word.replace( /es$/i ,'em' ); // 5th declension singular + word = word.replace( /es$/i, 'em' ); // 5th declension singular break; case 'ablative': // only a few declensions, and even for those mostly the singular only @@ -43,7 +43,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { word = word.replace( /tio$/i,'tione' ); // 3rd declension singular (partly) word = word.replace( /ns$/i, 'nte' ); word = word.replace( /as$/i, 'ate'); - word = word.replace( /es$/i ,'e' ); // 5th declension singular + word = word.replace( /es$/i, 'e' ); // 5th declension singular break; } return word; diff --git a/resources/mediawiki.language/languages/os.js b/resources/mediawiki.language/languages/os.js index 4b508346c4..bdf59beac4 100644 --- a/resources/mediawiki.language/languages/os.js +++ b/resources/mediawiki.language/languages/os.js @@ -30,7 +30,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) { // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic. // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы. else if ( word.match( /у$/i ) ) { - if ( ! word.substring( word.length-2, word.length-1 ).match( /[аæеёиоыэюя]$/i ) ) { + if ( !word.substring( word.length - 2, word.length - 1 ).match( /[аæеёиоыэюя]$/i ) ) { jot = 'й'; } } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) { diff --git a/resources/mediawiki.language/languages/uk.js b/resources/mediawiki.language/languages/uk.js index 9b63382138..69f7ec540c 100644 --- a/resources/mediawiki.language/languages/uk.js +++ b/resources/mediawiki.language/languages/uk.js @@ -3,33 +3,33 @@ */ mediaWiki.language.convertGrammar = function ( word, form ) { - /*jshint noempty:false */ var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' ); if ( grammarForms && grammarForms[form] ) { return grammarForms[form][word]; } switch ( form ) { case 'genitive': // родовий відмінок - if ( ( word.substr( word.length - 4 ) === 'вікі' ) || ( word.substr( word.length - 4 ) === 'Вікі' ) ) { - } else if ( word.substr( word.length - 1 ) === 'ь' ) { - word = word.substr(0, word.length - 1 ) + 'я'; - } else if ( word.substr( word.length - 2 ) === 'ія' ) { - word = word.substr(0, word.length - 2 ) + 'ії'; - } else if ( word.substr( word.length - 2 ) === 'ка' ) { - word = word.substr(0, word.length - 2 ) + 'ки'; - } else if ( word.substr( word.length - 2 ) === 'ти' ) { - word = word.substr(0, word.length - 2 ) + 'тей'; - } else if ( word.substr( word.length - 2 ) === 'ды' ) { - word = word.substr(0, word.length - 2 ) + 'дов'; - } else if ( word.substr( word.length - 3 ) === 'ник' ) { - word = word.substr(0, word.length - 3 ) + 'ника'; + if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) { + if ( word.substr( word.length - 1 ) === 'ь' ) { + word = word.substr(0, word.length - 1 ) + 'я'; + } else if ( word.substr( word.length - 2 ) === 'ія' ) { + word = word.substr(0, word.length - 2 ) + 'ії'; + } else if ( word.substr( word.length - 2 ) === 'ка' ) { + word = word.substr(0, word.length - 2 ) + 'ки'; + } else if ( word.substr( word.length - 2 ) === 'ти' ) { + word = word.substr(0, word.length - 2 ) + 'тей'; + } else if ( word.substr( word.length - 2 ) === 'ды' ) { + word = word.substr(0, word.length - 2 ) + 'дов'; + } else if ( word.substr( word.length - 3 ) === 'ник' ) { + word = word.substr(0, word.length - 3 ) + 'ника'; + } } break; case 'accusative': // знахідний відмінок - if ( ( word.substr( word.length - 4 ) === 'вікі' ) || ( word.substr( word.length - 4 ) === 'Вікі' ) ) { - } - else if ( word.substr( word.length - 2 ) === 'ія' ) { - word = word.substr(0, word.length - 2 ) + 'ію'; + if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) { + if ( word.substr( word.length - 2 ) === 'ія' ) { + word = word.substr(0, word.length - 2 ) + 'ію'; + } } break; } diff --git a/resources/mediawiki.language/mediawiki.language.js b/resources/mediawiki.language/mediawiki.language.js index 87018f6d60..a0b556914d 100644 --- a/resources/mediawiki.language/mediawiki.language.js +++ b/resources/mediawiki.language/mediawiki.language.js @@ -96,7 +96,7 @@ $.extend( mw.language, { */ preConvertPlural: function ( forms, count ) { while ( forms.length < count ) { - forms.push( forms[ forms.length-1 ] ); + forms.push( forms[ forms.length - 1 ] ); } return forms; }, diff --git a/resources/mediawiki.page/mediawiki.page.gallery.js b/resources/mediawiki.page/mediawiki.page.gallery.js index 64efbb9ed1..f92d372663 100644 --- a/resources/mediawiki.page/mediawiki.page.gallery.js +++ b/resources/mediawiki.page/mediawiki.page.gallery.js @@ -66,11 +66,12 @@ imgHeight = 0; } - rows[rows.length-1][rows[rows.length-1].length] = { + rows[rows.length - 1][rows[rows.length - 1].length] = { $elm: $this, width: $this.outerWidth(), imgWidth: imgWidth, - aspect: imgWidth / imgHeight, // XXX: can divide by 0 ever happen? + // XXX: can divide by 0 ever happen? + aspect: imgWidth / imgHeight, captionWidth: $this.children().children( 'div.gallerytextwrapper' ).width(), height: imgHeight }; @@ -136,7 +137,7 @@ // Also on the off chance there is a bug in this // code, would prevent accidentally expanding to // be 10 billion pixels wide. - mw.log( 'mw.page.gallery: Cannot fit row, aspect is ' + preferredHeight/curRowHeight ); + mw.log( 'mw.page.gallery: Cannot fit row, aspect is ' + preferredHeight / curRowHeight ); if ( i === rows.length - 1 ) { // If its the last row, and we can't fit it, // don't make the entire row huge. @@ -159,7 +160,12 @@ } if ( preferredHeight < 5 ) { // Well something clearly went wrong... - mw.log( {maxWidth: maxWidth, combinedPadding: combinedPadding, combinedAspect: combinedAspect, wantedWidth: wantedWidth } ); + mw.log( { + maxWidth: maxWidth, + combinedPadding: combinedPadding, + combinedAspect: combinedAspect, + wantedWidth: wantedWidth + } ); mw.log( 'mw.page.gallery: [BUG!] Fitting row ' + i + ' to too small a size: ' + preferredHeight ); // Skip this row. continue; @@ -182,7 +188,6 @@ imageElm = $imageElm.length ? $imageElm[0] : null; $caption = $outerDiv.find( 'div.gallerytextwrapper' ); - // Since we are going to re-adjust the height, the vertical // centering margins need to be reset. $imageDiv.children( 'div' ).css( 'margin', '0px auto' ); diff --git a/resources/mediawiki.page/mediawiki.page.image.pagination.js b/resources/mediawiki.page/mediawiki.page.image.pagination.js index 8a4d526993..50301bd658 100644 --- a/resources/mediawiki.page/mediawiki.page.image.pagination.js +++ b/resources/mediawiki.page/mediawiki.page.image.pagination.js @@ -90,4 +90,4 @@ } } } ); -}( mediaWiki, jQuery ) ); \ No newline at end of file +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.special/mediawiki.special.block.js b/resources/mediawiki.special/mediawiki.special.block.js index b8bcf177da..8dedb9b686 100644 --- a/resources/mediawiki.special/mediawiki.special.block.js +++ b/resources/mediawiki.special/mediawiki.special.block.js @@ -43,4 +43,3 @@ } } ); }( mediaWiki, jQuery ) ); - diff --git a/resources/mediawiki.special/mediawiki.special.javaScriptTest.js b/resources/mediawiki.special/mediawiki.special.javaScriptTest.js index 2c7421bf15..38f256cc26 100644 --- a/resources/mediawiki.special/mediawiki.special.javaScriptTest.js +++ b/resources/mediawiki.special/mediawiki.special.javaScriptTest.js @@ -34,4 +34,3 @@ } ); }( mediaWiki, jQuery ) ); - diff --git a/resources/mediawiki.special/mediawiki.special.preferences.js b/resources/mediawiki.special/mediawiki.special.preferences.js index 23d783777e..2cd27af991 100644 --- a/resources/mediawiki.special/mediawiki.special.preferences.js +++ b/resources/mediawiki.special/mediawiki.special.preferences.js @@ -128,7 +128,7 @@ jQuery( function ( $ ) { // make the selected tab visible. hash = window.location.hash; if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) { - switchPrefTab( hash.replace( '#mw-prefsection-' , '' ) ); + switchPrefTab( hash.replace( '#mw-prefsection-', '' ) ); } // In browsers that support the onhashchange event we will not bind click @@ -140,7 +140,7 @@ jQuery( function ( $ ) { if ( 'onhashchange' in window && ( document.documentMode === undefined || document.documentMode >= 8 ) ) { - $( window ).on( 'hashchange' , function () { + $( window ).on( 'hashchange', function () { var hash = window.location.hash; if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) { switchPrefTab( hash.replace( '#mw-prefsection-', '' ) ); diff --git a/resources/mediawiki.special/mediawiki.special.upload.js b/resources/mediawiki.special/mediawiki.special.upload.js index 4ee3de3b9c..8a5ff59398 100644 --- a/resources/mediawiki.special/mediawiki.special.upload.js +++ b/resources/mediawiki.special/mediawiki.special.upload.js @@ -140,7 +140,7 @@ }; img.src = dataURL; }, mw.config.get( 'wgFileCanRotate' ) ? function ( data ) { - /*jshint camelcase: false, nomen: false */ + /*jshint camelcase:false, nomen:false */ try { meta = mw.libs.jpegmeta( data, file.fileName ); meta._binary_data = null; @@ -263,7 +263,6 @@ return true; } - /** * Initialization */ diff --git a/resources/mediawiki/mediawiki.Title.js b/resources/mediawiki/mediawiki.Title.js index 32c3f1e2ff..8a7aec23f4 100644 --- a/resources/mediawiki/mediawiki.Title.js +++ b/resources/mediawiki/mediawiki.Title.js @@ -179,7 +179,6 @@ .replace( rUnderscoreTrim, '' ); } - // Reject illegal characters if ( title.match( rInvalid ) ) { return false; @@ -271,7 +270,6 @@ }; }() ); - /* Static members */ /** @@ -575,7 +573,6 @@ */ Title.prototype.toString = Title.prototype.getPrefixedDb; - /** * @alias #getPrefixedText * @method diff --git a/resources/mediawiki/mediawiki.debug.js b/resources/mediawiki/mediawiki.debug.js index b6cc2b76fa..1b183d9e3d 100644 --- a/resources/mediawiki/mediawiki.debug.js +++ b/resources/mediawiki/mediawiki.debug.js @@ -238,7 +238,6 @@ $( '' ).appendTo( $table ); $( '' ).css( 'width', 350 ).appendTo( $table ); - entryTypeText = function ( entryType ) { switch ( entryType ) { case 'log': @@ -297,7 +296,6 @@ .appendTo( $table ); } - return $table; }, diff --git a/resources/mediawiki/mediawiki.feedback.js b/resources/mediawiki/mediawiki.feedback.js index 6dd4f88d7a..90a6425913 100644 --- a/resources/mediawiki/mediawiki.feedback.js +++ b/resources/mediawiki/mediawiki.feedback.js @@ -163,9 +163,12 @@ * The section of the dialog to show. */ display: function ( s ) { - this.$dialog.dialog( { buttons:{} } ); // hide the buttons - this.$dialog.find( '.feedback-mode' ).hide(); // hide everything - this.$dialog.find( '.feedback-' + s ).show(); // show the desired div + // Hide the buttons + this.$dialog.dialog( { buttons: {} } ); + // Hide everything + this.$dialog.find( '.feedback-mode' ).hide(); + // Show the desired div + this.$dialog.find( '.feedback-' + s ).show(); }, /** diff --git a/resources/mediawiki/mediawiki.jqueryMsg.js b/resources/mediawiki/mediawiki.jqueryMsg.js index 85669fb69a..3a6869e7bd 100644 --- a/resources/mediawiki/mediawiki.jqueryMsg.js +++ b/resources/mediawiki/mediawiki.jqueryMsg.js @@ -14,18 +14,18 @@ var oldParser, slice = Array.prototype.slice, parserDefaults = { - magic : { - 'SITENAME' : mw.config.get( 'wgSiteName' ) + magic: { + 'SITENAME': mw.config.get( 'wgSiteName' ) }, // This is a whitelist based on, but simpler than, Sanitizer.php. // Self-closing tags are not currently supported. - allowedHtmlElements : [ + allowedHtmlElements: [ 'b', 'i' ], // Key tag name, value allowed attributes for that tag. // See Sanitizer::setupAttributeWhitelist - allowedHtmlCommonAttributes : [ + allowedHtmlCommonAttributes: [ // HTML 'id', 'class', @@ -41,9 +41,9 @@ // Attributes allowed for specific elements. // Key is element name in lower case // Value is array of allowed attributes for that element - allowedHtmlAttributesByElement : {}, - messages : mw.messages, - language : mw.language, + allowedHtmlAttributesByElement: {}, + messages: mw.messages, + language: mw.language, // Same meaning as in mediawiki.js. // diff --git a/skins/common/IEFixes.js b/skins/common/IEFixes.js index e35fcd1a85..03f133ef88 100644 --- a/skins/common/IEFixes.js +++ b/skins/common/IEFixes.js @@ -91,7 +91,7 @@ relativeforfloats = window.relativeforfloats = function () { setrelative = window.setrelative = function ( nodes ) { var i = 0; while ( i < nodes.length ) { - if( ( ( nodes[i].style.float && nodes[i].style.float !== ( 'none' ) || + if ( ( ( nodes[i].style.float && nodes[i].style.float !== ( 'none' ) || ( nodes[i].align && nodes[i].align !== ( 'none' ) ) ) && ( !nodes[i].style.position || nodes[i].style.position !== 'relative' ) ) ) { @@ -135,7 +135,7 @@ window.onbeforeprint = function () { } }; -window.onafterprint = function() { +window.onafterprint = function () { for ( var i = 0; i < expandedURLs.length; i++ ) { if ( expandedURLs[i] ) { expandedURLs[i].removeNode( true ); diff --git a/skins/common/ajax.js b/skins/common/ajax.js index ca74b384b0..c017e3ca0f 100644 --- a/skins/common/ajax.js +++ b/skins/common/ajax.js @@ -5,7 +5,7 @@ * http://www.modernmethod.com/sajax/ */ -/*jshint camelcase:false, onevar:false */ +/*jshint camelcase:false */ /*global alert */ ( function ( mw ) { @@ -89,9 +89,7 @@ function createXhr() { * with id = showFoo */ function doAjaxRequest( func_name, args, target ) { - var i, x; - var uri; - var post_data; + var i, x, uri, post_data; uri = mw.util.wikiScript() + '?action=ajax'; if ( window.sajax_request_type === 'GET' ) { if ( uri.indexOf( '?' ) === -1 ) { @@ -146,7 +144,7 @@ function doAjaxRequest( func_name, args, target ) { } else if ( typeof target === 'object' ) { if ( target.tagName === 'INPUT' ) { if ( x.status === 200 ) { - target.value= x.responseText; + target.value = x.responseText; } //else alert( 'Error: ' + x.status + ' ' + x.statusText + ' (' + x.responseText + ')' ); } else { @@ -173,8 +171,9 @@ function doAjaxRequest( func_name, args, target ) { * @return {boolean} Whether the browser supports AJAX */ function wfSupportsAjax() { - var request = createXhr(); - var supportsAjax = request ? true : false; + var request = createXhr(), + supportsAjax = request ? true : false; + request = undefined; return supportsAjax; } diff --git a/skins/common/config.js b/skins/common/config.js index fb8edc1f9a..2886e08e86 100644 --- a/skins/common/config.js +++ b/skins/common/config.js @@ -98,7 +98,7 @@ // Show/Hide memcached servers when needed $( 'input[name$="config_wgMainCacheType"]' ).change( function () { var $memc = $( '#config-memcachewrapper' ); - if( $( 'input[name$="config_wgMainCacheType"]:checked' ).val() === 'memcached' ) { + if ( $( 'input[name$="config_wgMainCacheType"]:checked' ).val() === 'memcached' ) { $memc.show( 'slow' ); } else { $memc.hide( 'slow' ); diff --git a/skins/common/upload.js b/skins/common/upload.js index d639f63a14..7933cafb70 100644 --- a/skins/common/upload.js +++ b/skins/common/upload.js @@ -85,7 +85,6 @@ function uploadSetup() { wpLicenseTbody.insertBefore( row, wpLicenseRow.nextSibling ); } - // fillDestFile setup uploadSourceIds = mw.config.get( 'wgUploadSourceIds' ); len = uploadSourceIds.length; @@ -98,7 +97,7 @@ function uploadSetup() { } wgUploadWarningObj = window.wgUploadWarningObj = { - responseCache: { '' : ' ' }, + responseCache: { '': ' ' }, nameToCheck: '', typing: false, delay: 500, // ms @@ -303,7 +302,7 @@ window.toggleFilenameFiller = function () { wgUploadLicenseObj = window.wgUploadLicenseObj = { - responseCache: { '' : '' }, + responseCache: { '': '' }, fetchPreview: function ( license ) { var cached, title; diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js index f0aa943059..df5682ebaa 100644 --- a/skins/common/wikibits.js +++ b/skins/common/wikibits.js @@ -240,7 +240,7 @@ win.importStylesheet = function ( page ) { return win.importStylesheetURI( uri ); }; -win.importStylesheetURI = function( url, media ) { +win.importStylesheetURI = function ( url, media ) { var l = document.createElement( 'link' ); l.rel = 'stylesheet'; l.href = url; diff --git a/skins/vector/vector.js b/skins/vector/vector.js index 8420431445..0bc114a4bf 100644 --- a/skins/vector/vector.js +++ b/skins/vector/vector.js @@ -8,7 +8,7 @@ jQuery( function ( $ ) { .attr( 'tabindex', '0' ) // For accessibility, show the menu when the h3 is clicked (bug 24298/46486) .on( 'click keypress', function ( e ) { - if( e.type === 'click' || e.which === 13 ) { + if ( e.type === 'click' || e.which === 13 ) { $el.toggleClass( 'menuForceShow' ); e.preventDefault(); } diff --git a/tests/frontend/Gruntfile.js b/tests/frontend/Gruntfile.js new file mode 100644 index 0000000000..a8aad4153d --- /dev/null +++ b/tests/frontend/Gruntfile.js @@ -0,0 +1,51 @@ +/*! + * Grunt file + */ + +/*jshint node:true */ +module.exports = function ( grunt ) { + grunt.loadNpmTasks( 'grunt-contrib-jshint' ); + grunt.loadNpmTasks( 'grunt-contrib-watch' ); + grunt.loadNpmTasks( 'grunt-jscs-checker' ); + + grunt.file.setBase( __dirname + '/../..' ); + + grunt.initConfig( { + pkg: grunt.file.readJSON( __dirname + '/package.json' ), + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: [ '*.js', '{includes,languages,resources,skins,tests}/**/*.js' ] + }, + jscs: { + // Known issues: + // - https://github.com/mdevils/node-jscs/issues/277 + // - https://github.com/mdevils/node-jscs/issues/278 + all: [ + '<%= jshint.all %>', + // Auto-generated file with JSON (double quotes) + '!tests/qunit/data/mediawiki.jqueryMsg.data.js' + + // Exclude all files ignored by jshint + ].concat( grunt.file.read( '.jshintignore' ).split( '\n' ).reduce( function ( patterns, pattern ) { + // Filter out empty lines + if ( pattern.length && pattern[0] !== '#' ) { + patterns.push( '!' + pattern ); + } + return patterns; + }, [] ) ) + }, + watch: { + files: [ + '.{jshintrc,jscs.json,jshintignore,csslintrc}', + '<%= jshint.all %>' + ], + tasks: ['test'] + } + } ); + + grunt.registerTask( 'lint', ['jshint', 'jscs'] ); + grunt.registerTask( 'test', ['lint'] ); + grunt.registerTask( 'default', ['test'] ); +}; diff --git a/tests/frontend/package.json b/tests/frontend/package.json new file mode 100644 index 0000000000..5eb5c0a455 --- /dev/null +++ b/tests/frontend/package.json @@ -0,0 +1,13 @@ +{ + "name": "mediawiki", + "version": "0.0.0", + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "grunt": "0.4.2", + "grunt-contrib-jshint": "0.8.0", + "grunt-contrib-watch": "0.5.3", + "grunt-jscs-checker": "0.4.0" + } +} diff --git a/tests/qunit/data/generateJqueryMsgData.php b/tests/qunit/data/generateJqueryMsgData.php index 12e5a2dca0..461ab87d0b 100644 --- a/tests/qunit/data/generateJqueryMsgData.php +++ b/tests/qunit/data/generateJqueryMsgData.php @@ -135,7 +135,6 @@ class GenerateJqueryMsgData extends Maintenance { . '// Last generated with ' . basename( __FILE__ ) . ' at ' . gmdate( 'r' ) . "\n" // This file will contain unquoted JSON strings as javascript native object literals, // flip the quotemark convention for this file. - . "/*jshint quotmark: double */\n" . "\n" . 'mediaWiki.libs.phpParserData = ' . FormatJson::encode( $phpParserData, true ) . ";\n"; diff --git a/tests/qunit/data/mediawiki.jqueryMsg.data.js b/tests/qunit/data/mediawiki.jqueryMsg.data.js index 776ee24f03..4ab5f1468b 100644 --- a/tests/qunit/data/mediawiki.jqueryMsg.data.js +++ b/tests/qunit/data/mediawiki.jqueryMsg.data.js @@ -1,492 +1,491 @@ // This file stores the output from the PHP parser for various messages, arguments, // languages, and parser modes. Intended for use by a unit test framework by looping // through the object and comparing its parser return value with the 'result' property. -// Last generated with generateJqueryMsgData.php at Sat, 03 Nov 2012 21:32:01 +0000 -/*jshint quotmark: double */ +// Last generated with generateJqueryMsgData.php at Thu, 30 Jan 2014 04:04:41 +0000 mediaWiki.libs.phpParserData = { - "messages": { - "en_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", - "en_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", - "fr_undelete_short": "Restaurer $1 modification{{PLURAL:$1||s}}", - "fr_category-subcat-count": "Cette cat\u00e9gorie comprend {{PLURAL:$2|la sous-cat\u00e9gorie|$2 sous-cat\u00e9gories, dont {{PLURAL:$1|celle|les $1}}}} ci-dessous.", - "ar_undelete_short": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 {{PLURAL:$1|\u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f|\u062a\u0639\u062f\u064a\u0644\u064a\u0646|$1 \u062a\u0639\u062f\u064a\u0644\u0627\u062a|$1 \u062a\u0639\u062f\u064a\u0644|$1 \u062a\u0639\u062f\u064a\u0644\u0627}}", - "ar_category-subcat-count": "{{PLURAL:$2|\u0644\u0627 \u062a\u0635\u0627\u0646\u064a\u0641 \u0641\u0631\u0639\u064a\u0629 \u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a \u0627\u0644\u062a\u0627\u0644\u064a \u0641\u0642\u0637.|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 {{PLURAL:$1||\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a|\u0647\u0630\u064a\u0646 \u0627\u0644\u062a\u0635\u0646\u064a\u0641\u064a\u0646 \u0627\u0644\u0641\u0631\u0639\u064a\u064a\u0646|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0627\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u0629|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0646\u064a\u0641\u0627 \u0641\u0631\u0639\u064a\u0627|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0646\u064a\u0641 \u0641\u0631\u0639\u064a}}\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a $2.}}", - "jp_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", - "jp_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", - "zh_undelete_short": "\u6062\u590d$1\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "zh_category-subcat-count": "{{PLURAL:$2|\u672c\u5206\u7c7b\u53ea\u6709\u4e0b\u5217\u4e00\u4e2a\u5b50\u5206\u7c7b\u3002|\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u5217$1\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171$2\u4e2a\u5b50\u5206\u7c7b\u3002}}" - }, - "tests": [ - { - "name": "en undelete_short 0", - "key": "en_undelete_short", - "args": [ - 0 - ], - "result": "Undelete 0 edits", - "lang": "en" - }, - { - "name": "en undelete_short 1", - "key": "en_undelete_short", - "args": [ - 1 - ], - "result": "Undelete one edit", - "lang": "en" - }, - { - "name": "en undelete_short 2", - "key": "en_undelete_short", - "args": [ - 2 - ], - "result": "Undelete 2 edits", - "lang": "en" - }, - { - "name": "en undelete_short 5", - "key": "en_undelete_short", - "args": [ - 5 - ], - "result": "Undelete 5 edits", - "lang": "en" - }, - { - "name": "en undelete_short 21", - "key": "en_undelete_short", - "args": [ - 21 - ], - "result": "Undelete 21 edits", - "lang": "en" - }, - { - "name": "en undelete_short 101", - "key": "en_undelete_short", - "args": [ - 101 - ], - "result": "Undelete 101 edits", - "lang": "en" - }, - { - "name": "en category-subcat-count 0,10", - "key": "en_category-subcat-count", - "args": [ - 0, - 10 - ], - "result": "This category has the following 0 subcategories, out of 10 total.", - "lang": "en" - }, - { - "name": "en category-subcat-count 1,1", - "key": "en_category-subcat-count", - "args": [ - 1, - 1 - ], - "result": "This category has only the following subcategory.", - "lang": "en" - }, - { - "name": "en category-subcat-count 1,2", - "key": "en_category-subcat-count", - "args": [ - 1, - 2 - ], - "result": "This category has the following subcategory, out of 2 total.", - "lang": "en" - }, - { - "name": "en category-subcat-count 3,30", - "key": "en_category-subcat-count", - "args": [ - 3, - 30 - ], - "result": "This category has the following 3 subcategories, out of 30 total.", - "lang": "en" - }, - { - "name": "fr undelete_short 0", - "key": "fr_undelete_short", - "args": [ - 0 - ], - "result": "Restaurer 0 modification", - "lang": "fr" - }, - { - "name": "fr undelete_short 1", - "key": "fr_undelete_short", - "args": [ - 1 - ], - "result": "Restaurer 1 modification", - "lang": "fr" - }, - { - "name": "fr undelete_short 2", - "key": "fr_undelete_short", - "args": [ - 2 - ], - "result": "Restaurer 2 modifications", - "lang": "fr" - }, - { - "name": "fr undelete_short 5", - "key": "fr_undelete_short", - "args": [ - 5 - ], - "result": "Restaurer 5 modifications", - "lang": "fr" - }, - { - "name": "fr undelete_short 21", - "key": "fr_undelete_short", - "args": [ - 21 - ], - "result": "Restaurer 21 modifications", - "lang": "fr" - }, - { - "name": "fr undelete_short 101", - "key": "fr_undelete_short", - "args": [ - 101 - ], - "result": "Restaurer 101 modifications", - "lang": "fr" - }, - { - "name": "fr category-subcat-count 0,10", - "key": "fr_category-subcat-count", - "args": [ - 0, - 10 - ], - "result": "Cette cat\u00e9gorie comprend 10 sous-cat\u00e9gories, dont celle ci-dessous.", - "lang": "fr" - }, - { - "name": "fr category-subcat-count 1,1", - "key": "fr_category-subcat-count", - "args": [ - 1, - 1 - ], - "result": "Cette cat\u00e9gorie comprend la sous-cat\u00e9gorie ci-dessous.", - "lang": "fr" - }, - { - "name": "fr category-subcat-count 1,2", - "key": "fr_category-subcat-count", - "args": [ - 1, - 2 - ], - "result": "Cette cat\u00e9gorie comprend 2 sous-cat\u00e9gories, dont celle ci-dessous.", - "lang": "fr" - }, - { - "name": "fr category-subcat-count 3,30", - "key": "fr_category-subcat-count", - "args": [ - 3, - 30 - ], - "result": "Cette cat\u00e9gorie comprend 30 sous-cat\u00e9gories, dont les 3 ci-dessous.", - "lang": "fr" - }, - { - "name": "ar undelete_short 0", - "key": "ar_undelete_short", - "args": [ - 0 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f", - "lang": "ar" - }, - { - "name": "ar undelete_short 1", - "key": "ar_undelete_short", - "args": [ - 1 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644\u064a\u0646", - "lang": "ar" - }, - { - "name": "ar undelete_short 2", - "key": "ar_undelete_short", - "args": [ - 2 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 2 \u062a\u0639\u062f\u064a\u0644\u0627\u062a", - "lang": "ar" - }, - { - "name": "ar undelete_short 5", - "key": "ar_undelete_short", - "args": [ - 5 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 5 \u062a\u0639\u062f\u064a\u0644", - "lang": "ar" - }, - { - "name": "ar undelete_short 21", - "key": "ar_undelete_short", - "args": [ - 21 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 21 \u062a\u0639\u062f\u064a\u0644\u0627", - "lang": "ar" - }, - { - "name": "ar undelete_short 101", - "key": "ar_undelete_short", - "args": [ - 101 - ], - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 101 \u062a\u0639\u062f\u064a\u0644\u0627", - "lang": "ar" - }, - { - "name": "ar category-subcat-count 0,10", - "key": "ar_category-subcat-count", - "args": [ - 0, - 10 - ], - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 10.", - "lang": "ar" - }, - { - "name": "ar category-subcat-count 1,1", - "key": "ar_category-subcat-count", - "args": [ - 1, - 1 - ], - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a \u0627\u0644\u062a\u0627\u0644\u064a \u0641\u0642\u0637.", - "lang": "ar" - }, - { - "name": "ar category-subcat-count 1,2", - "key": "ar_category-subcat-count", - "args": [ - 1, - 2 - ], - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 2.", - "lang": "ar" - }, - { - "name": "ar category-subcat-count 3,30", - "key": "ar_category-subcat-count", - "args": [ - 3, - 30 - ], - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0647\u0630\u0647 \u0627\u06443 \u062a\u0635\u0627\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u0629\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 30.", - "lang": "ar" - }, - { - "name": "jp undelete_short 0", - "key": "jp_undelete_short", - "args": [ - 0 - ], - "result": "Undelete 0 edits", - "lang": "jp" - }, - { - "name": "jp undelete_short 1", - "key": "jp_undelete_short", - "args": [ - 1 - ], - "result": "Undelete one edit", - "lang": "jp" - }, - { - "name": "jp undelete_short 2", - "key": "jp_undelete_short", - "args": [ - 2 - ], - "result": "Undelete 2 edits", - "lang": "jp" - }, - { - "name": "jp undelete_short 5", - "key": "jp_undelete_short", - "args": [ - 5 - ], - "result": "Undelete 5 edits", - "lang": "jp" - }, - { - "name": "jp undelete_short 21", - "key": "jp_undelete_short", - "args": [ - 21 - ], - "result": "Undelete 21 edits", - "lang": "jp" - }, - { - "name": "jp undelete_short 101", - "key": "jp_undelete_short", - "args": [ - 101 - ], - "result": "Undelete 101 edits", - "lang": "jp" - }, - { - "name": "jp category-subcat-count 0,10", - "key": "jp_category-subcat-count", - "args": [ - 0, - 10 - ], - "result": "This category has the following 0 subcategories, out of 10 total.", - "lang": "jp" - }, - { - "name": "jp category-subcat-count 1,1", - "key": "jp_category-subcat-count", - "args": [ - 1, - 1 - ], - "result": "This category has only the following subcategory.", - "lang": "jp" - }, - { - "name": "jp category-subcat-count 1,2", - "key": "jp_category-subcat-count", - "args": [ - 1, - 2 - ], - "result": "This category has the following subcategory, out of 2 total.", - "lang": "jp" - }, - { - "name": "jp category-subcat-count 3,30", - "key": "jp_category-subcat-count", - "args": [ - 3, - 30 - ], - "result": "This category has the following 3 subcategories, out of 30 total.", - "lang": "jp" - }, - { - "name": "zh undelete_short 0", - "key": "zh_undelete_short", - "args": [ - 0 - ], - "result": "\u6062\u590d0\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh undelete_short 1", - "key": "zh_undelete_short", - "args": [ - 1 - ], - "result": "\u6062\u590d1\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh undelete_short 2", - "key": "zh_undelete_short", - "args": [ - 2 - ], - "result": "\u6062\u590d2\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh undelete_short 5", - "key": "zh_undelete_short", - "args": [ - 5 - ], - "result": "\u6062\u590d5\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh undelete_short 21", - "key": "zh_undelete_short", - "args": [ - 21 - ], - "result": "\u6062\u590d21\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh undelete_short 101", - "key": "zh_undelete_short", - "args": [ - 101 - ], - "result": "\u6062\u590d101\u4e2a\u88ab\u5220\u9664\u7684\u7f16\u8f91", - "lang": "zh" - }, - { - "name": "zh category-subcat-count 0,10", - "key": "zh_category-subcat-count", - "args": [ - 0, - 10 - ], - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52170\u4e2a\u5b50\u5206\u7c7b\uff0c\u517110\u4e2a\u5b50\u5206\u7c7b\u3002", - "lang": "zh" - }, - { - "name": "zh category-subcat-count 1,1", - "key": "zh_category-subcat-count", - "args": [ - 1, - 1 - ], - "result": "\u672c\u5206\u7c7b\u53ea\u6709\u4e0b\u5217\u4e00\u4e2a\u5b50\u5206\u7c7b\u3002", - "lang": "zh" - }, - { - "name": "zh category-subcat-count 1,2", - "key": "zh_category-subcat-count", - "args": [ - 1, - 2 - ], - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52171\u4e2a\u5b50\u5206\u7c7b\uff0c\u51712\u4e2a\u5b50\u5206\u7c7b\u3002", - "lang": "zh" - }, - { - "name": "zh category-subcat-count 3,30", - "key": "zh_category-subcat-count", - "args": [ - 3, - 30 - ], - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52173\u4e2a\u5b50\u5206\u7c7b\uff0c\u517130\u4e2a\u5b50\u5206\u7c7b\u3002", - "lang": "zh" - } - ] + "messages": { + "en_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", + "en_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", + "fr_undelete_short": "Restaurer $1 modification{{PLURAL:$1||s}}", + "fr_category-subcat-count": "Cette cat\u00e9gorie comprend {{PLURAL:$2|la sous-cat\u00e9gorie|$2 sous-cat\u00e9gories, dont {{PLURAL:$1|celle|les $1}}}} ci-dessous.", + "ar_undelete_short": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 {{PLURAL:$1||\u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f|\u062a\u0639\u062f\u064a\u0644\u064a\u0646|$1 \u062a\u0639\u062f\u064a\u0644\u0627\u062a|$1 \u062a\u0639\u062f\u064a\u0644\u0627\u064b|$1 \u062a\u0639\u062f\u064a\u0644}}", + "ar_category-subcat-count": "{{PLURAL:$2|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a \u0627\u0644\u062a\u0627\u0644\u064a|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a {{PLURAL:$1||\u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a|\u062a\u0635\u0646\u064a\u0641\u064a\u0646 \u0641\u0631\u0639\u064a\u064a\u0646|$1 \u062a\u0635\u0646\u064a\u0641\u0627\u062a \u0641\u0631\u0639\u064a\u0629}}\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a $2.}}", + "jp_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", + "jp_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", + "zh_undelete_short": "\u8fd8\u539f{{PLURAL:$1|$1\u4e2a\u7f16\u8f91}}", + "zh_category-subcat-count": "{{PLURAL:$2|\u672c\u5206\u7c7b\u53ea\u6709\u4ee5\u4e0b\u5b50\u5206\u7c7b\u3002|\u672c\u5206\u7c7b\u6709\u4ee5\u4e0b$1\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u6709$2\u4e2a\u5b50\u5206\u7c7b\u3002}}" + }, + "tests": [ + { + "name": "en undelete_short 0", + "key": "en_undelete_short", + "args": [ + 0 + ], + "result": "Undelete 0 edits", + "lang": "en" + }, + { + "name": "en undelete_short 1", + "key": "en_undelete_short", + "args": [ + 1 + ], + "result": "Undelete one edit", + "lang": "en" + }, + { + "name": "en undelete_short 2", + "key": "en_undelete_short", + "args": [ + 2 + ], + "result": "Undelete 2 edits", + "lang": "en" + }, + { + "name": "en undelete_short 5", + "key": "en_undelete_short", + "args": [ + 5 + ], + "result": "Undelete 5 edits", + "lang": "en" + }, + { + "name": "en undelete_short 21", + "key": "en_undelete_short", + "args": [ + 21 + ], + "result": "Undelete 21 edits", + "lang": "en" + }, + { + "name": "en undelete_short 101", + "key": "en_undelete_short", + "args": [ + 101 + ], + "result": "Undelete 101 edits", + "lang": "en" + }, + { + "name": "en category-subcat-count 0,10", + "key": "en_category-subcat-count", + "args": [ + 0, + 10 + ], + "result": "This category has the following 0 subcategories, out of 10 total.", + "lang": "en" + }, + { + "name": "en category-subcat-count 1,1", + "key": "en_category-subcat-count", + "args": [ + 1, + 1 + ], + "result": "This category has only the following subcategory.", + "lang": "en" + }, + { + "name": "en category-subcat-count 1,2", + "key": "en_category-subcat-count", + "args": [ + 1, + 2 + ], + "result": "This category has the following subcategory, out of 2 total.", + "lang": "en" + }, + { + "name": "en category-subcat-count 3,30", + "key": "en_category-subcat-count", + "args": [ + 3, + 30 + ], + "result": "This category has the following 3 subcategories, out of 30 total.", + "lang": "en" + }, + { + "name": "fr undelete_short 0", + "key": "fr_undelete_short", + "args": [ + 0 + ], + "result": "Restaurer 0 modification", + "lang": "fr" + }, + { + "name": "fr undelete_short 1", + "key": "fr_undelete_short", + "args": [ + 1 + ], + "result": "Restaurer 1 modification", + "lang": "fr" + }, + { + "name": "fr undelete_short 2", + "key": "fr_undelete_short", + "args": [ + 2 + ], + "result": "Restaurer 2 modifications", + "lang": "fr" + }, + { + "name": "fr undelete_short 5", + "key": "fr_undelete_short", + "args": [ + 5 + ], + "result": "Restaurer 5 modifications", + "lang": "fr" + }, + { + "name": "fr undelete_short 21", + "key": "fr_undelete_short", + "args": [ + 21 + ], + "result": "Restaurer 21 modifications", + "lang": "fr" + }, + { + "name": "fr undelete_short 101", + "key": "fr_undelete_short", + "args": [ + 101 + ], + "result": "Restaurer 101 modifications", + "lang": "fr" + }, + { + "name": "fr category-subcat-count 0,10", + "key": "fr_category-subcat-count", + "args": [ + 0, + 10 + ], + "result": "Cette cat\u00e9gorie comprend 10 sous-cat\u00e9gories, dont celle ci-dessous.", + "lang": "fr" + }, + { + "name": "fr category-subcat-count 1,1", + "key": "fr_category-subcat-count", + "args": [ + 1, + 1 + ], + "result": "Cette cat\u00e9gorie comprend la sous-cat\u00e9gorie ci-dessous.", + "lang": "fr" + }, + { + "name": "fr category-subcat-count 1,2", + "key": "fr_category-subcat-count", + "args": [ + 1, + 2 + ], + "result": "Cette cat\u00e9gorie comprend 2 sous-cat\u00e9gories, dont celle ci-dessous.", + "lang": "fr" + }, + { + "name": "fr category-subcat-count 3,30", + "key": "fr_category-subcat-count", + "args": [ + 3, + 30 + ], + "result": "Cette cat\u00e9gorie comprend 30 sous-cat\u00e9gories, dont les 3 ci-dessous.", + "lang": "fr" + }, + { + "name": "ar undelete_short 0", + "key": "ar_undelete_short", + "args": [ + 0 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 ", + "lang": "ar" + }, + { + "name": "ar undelete_short 1", + "key": "ar_undelete_short", + "args": [ + 1 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f", + "lang": "ar" + }, + { + "name": "ar undelete_short 2", + "key": "ar_undelete_short", + "args": [ + 2 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644\u064a\u0646", + "lang": "ar" + }, + { + "name": "ar undelete_short 5", + "key": "ar_undelete_short", + "args": [ + 5 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 5 \u062a\u0639\u062f\u064a\u0644\u0627\u062a", + "lang": "ar" + }, + { + "name": "ar undelete_short 21", + "key": "ar_undelete_short", + "args": [ + 21 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 21 \u062a\u0639\u062f\u064a\u0644\u0627\u064b", + "lang": "ar" + }, + { + "name": "ar undelete_short 101", + "key": "ar_undelete_short", + "args": [ + 101 + ], + "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 101 \u062a\u0639\u062f\u064a\u0644", + "lang": "ar" + }, + { + "name": "ar category-subcat-count 0,10", + "key": "ar_category-subcat-count", + "args": [ + 0, + 10 + ], + "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a \u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 10.", + "lang": "ar" + }, + { + "name": "ar category-subcat-count 1,1", + "key": "ar_category-subcat-count", + "args": [ + 1, + 1 + ], + "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 1.", + "lang": "ar" + }, + { + "name": "ar category-subcat-count 1,2", + "key": "ar_category-subcat-count", + "args": [ + 1, + 2 + ], + "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 2.", + "lang": "ar" + }, + { + "name": "ar category-subcat-count 3,30", + "key": "ar_category-subcat-count", + "args": [ + 3, + 30 + ], + "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u064a\u062d\u0648\u064a 3 \u062a\u0635\u0646\u064a\u0641\u0627\u062a \u0641\u0631\u0639\u064a\u0629\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 30.", + "lang": "ar" + }, + { + "name": "jp undelete_short 0", + "key": "jp_undelete_short", + "args": [ + 0 + ], + "result": "Undelete 0 edits", + "lang": "jp" + }, + { + "name": "jp undelete_short 1", + "key": "jp_undelete_short", + "args": [ + 1 + ], + "result": "Undelete one edit", + "lang": "jp" + }, + { + "name": "jp undelete_short 2", + "key": "jp_undelete_short", + "args": [ + 2 + ], + "result": "Undelete 2 edits", + "lang": "jp" + }, + { + "name": "jp undelete_short 5", + "key": "jp_undelete_short", + "args": [ + 5 + ], + "result": "Undelete 5 edits", + "lang": "jp" + }, + { + "name": "jp undelete_short 21", + "key": "jp_undelete_short", + "args": [ + 21 + ], + "result": "Undelete 21 edits", + "lang": "jp" + }, + { + "name": "jp undelete_short 101", + "key": "jp_undelete_short", + "args": [ + 101 + ], + "result": "Undelete 101 edits", + "lang": "jp" + }, + { + "name": "jp category-subcat-count 0,10", + "key": "jp_category-subcat-count", + "args": [ + 0, + 10 + ], + "result": "This category has the following 0 subcategories, out of 10 total.", + "lang": "jp" + }, + { + "name": "jp category-subcat-count 1,1", + "key": "jp_category-subcat-count", + "args": [ + 1, + 1 + ], + "result": "This category has only the following subcategory.", + "lang": "jp" + }, + { + "name": "jp category-subcat-count 1,2", + "key": "jp_category-subcat-count", + "args": [ + 1, + 2 + ], + "result": "This category has the following subcategory, out of 2 total.", + "lang": "jp" + }, + { + "name": "jp category-subcat-count 3,30", + "key": "jp_category-subcat-count", + "args": [ + 3, + 30 + ], + "result": "This category has the following 3 subcategories, out of 30 total.", + "lang": "jp" + }, + { + "name": "zh undelete_short 0", + "key": "zh_undelete_short", + "args": [ + 0 + ], + "result": "\u8fd8\u539f0\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh undelete_short 1", + "key": "zh_undelete_short", + "args": [ + 1 + ], + "result": "\u8fd8\u539f1\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh undelete_short 2", + "key": "zh_undelete_short", + "args": [ + 2 + ], + "result": "\u8fd8\u539f2\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh undelete_short 5", + "key": "zh_undelete_short", + "args": [ + 5 + ], + "result": "\u8fd8\u539f5\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh undelete_short 21", + "key": "zh_undelete_short", + "args": [ + 21 + ], + "result": "\u8fd8\u539f21\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh undelete_short 101", + "key": "zh_undelete_short", + "args": [ + 101 + ], + "result": "\u8fd8\u539f101\u4e2a\u7f16\u8f91", + "lang": "zh" + }, + { + "name": "zh category-subcat-count 0,10", + "key": "zh_category-subcat-count", + "args": [ + 0, + 10 + ], + "result": "\u672c\u5206\u7c7b\u6709\u4ee5\u4e0b0\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u670910\u4e2a\u5b50\u5206\u7c7b\u3002", + "lang": "zh" + }, + { + "name": "zh category-subcat-count 1,1", + "key": "zh_category-subcat-count", + "args": [ + 1, + 1 + ], + "result": "\u672c\u5206\u7c7b\u53ea\u6709\u4ee5\u4e0b\u5b50\u5206\u7c7b\u3002", + "lang": "zh" + }, + { + "name": "zh category-subcat-count 1,2", + "key": "zh_category-subcat-count", + "args": [ + 1, + 2 + ], + "result": "\u672c\u5206\u7c7b\u6709\u4ee5\u4e0b1\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u67092\u4e2a\u5b50\u5206\u7c7b\u3002", + "lang": "zh" + }, + { + "name": "zh category-subcat-count 3,30", + "key": "zh_category-subcat-count", + "args": [ + 3, + 30 + ], + "result": "\u672c\u5206\u7c7b\u6709\u4ee5\u4e0b3\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u670930\u4e2a\u5b50\u5206\u7c7b\u3002", + "lang": "zh" + } + ] }; diff --git a/tests/qunit/suites/resources/jquery/jquery.color.test.js b/tests/qunit/suites/resources/jquery/jquery.color.test.js index b644a3ceba..839c5d5072 100644 --- a/tests/qunit/suites/resources/jquery/jquery.color.test.js +++ b/tests/qunit/suites/resources/jquery/jquery.color.test.js @@ -4,7 +4,7 @@ QUnit.asyncTest( 'animate', 3, function ( assert ) { var $canvas = $( '
' ).css( 'background-color', '#fff' ); - $canvas.animate( { backgroundColor: '#000' }, 4 ).promise().then( function() { + $canvas.animate( { backgroundColor: '#000' }, 4 ).promise().then( function () { var endColors = $.colorUtil.getRGB( $canvas.css( 'background-color' ) ); assert.strictEqual( endColors[0], 0 ); assert.strictEqual( endColors[1], 0 ); diff --git a/tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js b/tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js index bfb857d7ce..e6a6124843 100644 --- a/tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js +++ b/tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js @@ -269,7 +269,7 @@ $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' ); } ); - QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)' , 2, function ( assert ) { + QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)', 2, function ( assert ) { var $collapsible = prepareCollapsible( '
' + '
' + diff --git a/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js b/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js index ca0ea6708c..bbea8297e6 100644 --- a/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js +++ b/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js @@ -1,8 +1,8 @@ -(function($) { +(function ($) { QUnit.module('jquery.placeholder', QUnit.newMwEnvironment()); - QUnit.test('caches results of feature tests', 2, function(assert) { + QUnit.test('caches results of feature tests', 2, function (assert) { assert.strictEqual(typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input'); assert.strictEqual(typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea'); }); @@ -20,7 +20,7 @@ '' + '' + '', - testElement = function($el, assert) { + testElement = function ($el, assert) { var el = $el[0], placeholder = el.getAttribute('placeholder'); @@ -67,32 +67,32 @@ $el.placeholder(placeholder); }; - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#input-type-text'), assert); }); - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#input-type-search'), assert); }); - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#input-type-email'), assert); }); - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#input-type-url'), assert); }); - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#input-type-tel'), assert); }); - QUnit.test('emulates placeholder for ', 13, function(assert) { + QUnit.test('emulates placeholder for ', 13, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); var selector = '#input-type-password', @@ -137,7 +137,7 @@ }); - QUnit.test('emulates placeholder for ', 22, function(assert) { + QUnit.test('emulates placeholder for ', 22, function (assert) { $('
').html(html).appendTo($('#qunit-fixture')); testElement($('#textarea'), assert); }); diff --git a/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js b/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js index 5fe239448f..25d9f736ea 100644 --- a/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js +++ b/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js @@ -32,29 +32,33 @@ }, opt.after ); QUnit.test( opt.description, function ( assert ) { - /*jshint onevar: false */ - var tests = 1; + var $textarea, start, end, options, text, + tests = 1; if ( opt.after.selected !== null ) { tests++; } QUnit.expect( tests ); - var $textarea = $( '