Merge "build: Enable selector-list-comma-newline-after stylelint rule"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 23 Feb 2017 17:06:52 +0000 (17:06 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 23 Feb 2017 17:06:52 +0000 (17:06 +0000)
124 files changed:
.eslintrc.json
.stylelintrc
.travis.yml
Gruntfile.js
HISTORY
RELEASE-NOTES-1.29
includes/DefaultSettings.php
includes/EditPage.php
includes/WebRequest.php
includes/actions/RollbackAction.php
includes/api/ApiAuthManagerHelper.php
includes/api/ApiMain.php
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/qqq.json
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/collation/Collation.php
includes/installer/i18n/bg.json
includes/installer/i18n/mk.json
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/encasing/Blob.php
includes/libs/rdbms/field/Field.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/user/User.php
includes/utils/AutoloadGenerator.php
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/et.json
languages/i18n/fi.json
languages/i18n/gl.json
languages/i18n/ko.json
languages/i18n/mg.json
languages/i18n/oc.json
languages/i18n/pnb.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ta.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesCa.php
resources/src/jquery/jquery.qunit.completenessTest.js
resources/src/mediawiki.action/mediawiki.action.view.filepage.css
resources/src/mediawiki.legacy/commonPrint.css
resources/src/mediawiki.legacy/oldshared.css
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.less/mediawiki.mixins.less
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less
resources/src/mediawiki.ui/components/inputs.less
resources/src/mediawiki.widgets.datetime/CalendarWidget.less
resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less
resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less
resources/src/mediawiki/api.js
resources/src/mediawiki/htmlform/styles.css
resources/src/mediawiki/page/gallery-slideshow.js
tests/parser/parserTests.txt
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/includes/utils/ClassCollectorTest.php [new file with mode: 0644]
tests/phpunit/structure/AutoLoaderTest.php
tests/qunit/.eslintrc.json [new file with mode: 0644]
tests/qunit/data/generateJqueryMsgData.php
tests/qunit/data/mediawiki.jqueryMsg.data.js
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
tests/qunit/suites/resources/jquery/jquery.byteLength.test.js
tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js
tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
tests/qunit/suites/resources/jquery/jquery.hidpi.test.js
tests/qunit/suites/resources/jquery/jquery.highlightText.test.js
tests/qunit/suites/resources/jquery/jquery.localize.test.js
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js
tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.edit.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.messages.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.upload.test.js
tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.RegExp.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.experiments.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.html.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.toc.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.viewport.test.js
tests/qunit/suites/resources/startup.test.js

index 98d0f10..64b5ea7 100644 (file)
@@ -2,8 +2,7 @@
        "extends": "wikimedia",
        "env": {
                "browser": true,
-               "jquery": true,
-               "qunit": true
+               "jquery": true
        },
        "globals": {
                "require": false,
index 704b0cb..5a7b29f 100644 (file)
@@ -3,10 +3,7 @@
        "rules": {
                "declaration-no-important": null,
 
-               "indentation": null,
-
                "no-descending-specificity": null,
-               "no-duplicate-selectors": null,
 
                "selector-no-id": null,
                "selector-pseudo-element-colon-notation": null,
index 9738605..ec7bac3 100644 (file)
@@ -7,6 +7,12 @@
 # complement that setup by testing MediaWiki on travis
 #
 language: php
+# Using HHVM-3.6+ requires Trusty (Travis default: precise)
+# https://docs.travis-ci.com/user/languages/php#HHVM-versions
+# https://github.com/travis-ci/travis-ci/issues/7368
+sudo: required
+group: edge
+dist: trusty
 
 matrix:
   fast_finish: true
@@ -16,7 +22,7 @@ matrix:
     - env: dbtype=postgres
       php: 5.5
     - env: dbtype=mysql
-      php: hhvm
+      php: hhvm-3.12
     - env: dbtype=mysql
       php: 7
 
@@ -44,7 +50,7 @@ before_script:
       --pass travis
       --dbtype "$dbtype"
       --dbname traviswiki
-      --dbuser travis
+      --dbuser root
       --dbpass ""
       --scriptpath "/w"
 
index 191286a..0e1c8cb 100644 (file)
@@ -24,12 +24,13 @@ module.exports = function ( grunt ) {
                        all: [
                                '**/*.js',
                                '!docs/**',
-                               '!tests/**',
                                '!node_modules/**',
                                '!resources/lib/**',
                                '!resources/src/jquery.tipsy/**',
                                '!resources/src/jquery/jquery.farbtastic.js',
                                '!resources/src/mediawiki.libs/**',
+                               // Third-party code of PHPUnit coverage report
+                               '!tests/coverage/**',
                                '!vendor/**',
                                // Explicitly say "**/*.js" here in case of symlinks
                                '!extensions/**/*.js',
diff --git a/HISTORY b/HISTORY
index a90d672..7f365ac 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -673,7 +673,7 @@ The following PHP extensions are strongly recommended:
 * ApiMain::addFormat() was removed (deprecated in 1.21).
 * ApiMain::getFormats() was removed (deprecated in 1.21).
 * ApiPageSet::finishPageSetGeneration() was removed (deprecated in 1.21).
-* ApiCreateAccount is deprecated, and will be removed soon.
+* ApiCreateAccount was removed.
 
 === Languages updated in 1.27 ===
 
index 13406d6..a1ce9d9 100644 (file)
@@ -32,6 +32,7 @@ production.
   new features that rely on the schema changes to the user_groups table. This
   feature flag will likely be removed before 1.29 is released.
 * (T158474) "Unknown user" has been added to $wgReservedUsernames.
+* (T156983) $wgRateLimitsExcludedIPs now accepts CIDR ranges as well as single IPs.
 
 === New features in 1.29 ===
 * (T5233) A cookie can now be set when a user is autoblocked, to track that user
@@ -60,6 +61,7 @@ production.
 * Updated QUnit from v1.22.0 to v1.23.1.
 * Updated cssjanus from v1.1.2 to 1.1.3.
 * Updated psr/log from v1.0.0 to v1.0.2.
+* Update Moment.js from v2.8.4 to v2.15.0.
 
 ==== New external libraries ====
 
index 791d024..c64f550 100644 (file)
@@ -5682,7 +5682,7 @@ $wgRateLimits = [
 ];
 
 /**
- * Array of IPs which should be excluded from rate limits.
+ * Array of IPs / CIDR ranges which should be excluded from rate limits.
  * This may be useful for whitelisting NAT gateways for conferences, etc.
  */
 $wgRateLimitsExcludedIPs = [];
index 34062c0..a45c889 100644 (file)
@@ -1256,7 +1256,7 @@ class EditPage {
                $revision = $this->mArticle->getRevisionFetched();
                if ( $revision === null ) {
                        if ( !$this->contentModel ) {
-                               $this->contentModel = $this->getTitle()->getContentModel();
+                               throw new RuntimeException( 'EditPage contentModel was false' );
                        }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
 
@@ -1300,7 +1300,7 @@ class EditPage {
 
                if ( $content === false || $content === null ) {
                        if ( !$this->contentModel ) {
-                               $this->contentModel = $this->getTitle()->getContentModel();
+                               throw new RuntimeException( 'EditPage contentModel was false' );
                        }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
 
index 3bbdc3f..78d7444 100644 (file)
@@ -408,7 +408,7 @@ class WebRequest {
         * @since 1.28
         * @param string $name
         * @param string|null $default Optional default
-        * @return string
+        * @return string|null
         */
        public function getRawVal( $name, $default = null ) {
                $name = strtr( $name, '.', '_' ); // See comment in self::getGPCVal()
@@ -432,7 +432,7 @@ class WebRequest {
         *
         * @param string $name
         * @param string $default Optional default (or null)
-        * @return string
+        * @return string|null
         */
        public function getVal( $name, $default = null ) {
                $val = $this->getGPCVal( $this->data, $name, $default );
@@ -482,7 +482,7 @@ class WebRequest {
         *
         * @param string $name
         * @param array $default Optional default (or null)
-        * @return array
+        * @return array|null
         */
        public function getArray( $name, $default = null ) {
                $val = $this->getGPCVal( $this->data, $name, $default );
index aa2858d..9d336e4 100644 (file)
@@ -41,6 +41,7 @@ class RollbackAction extends FormlessAction {
         * - confirm-rollback-button
         * - rollbackfailed
         * - rollback-missingparam
+        * - rollback-success-notify
         */
 
        /**
@@ -123,8 +124,13 @@ class RollbackAction extends FormlessAction {
 
                $old = Linker::revUserTools( $current );
                $new = Linker::revUserTools( $target );
-               $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )
-                       ->parseAsBlock() );
+               $this->getOutput()->addHTML(
+                       $this->msg( 'rollback-success' )
+                               ->rawParams( $old, $new )
+                               ->params( $current->getUserText( Revision::FOR_THIS_USER, $user ) )
+                               ->params( $target->getUserText( Revision::FOR_THIS_USER, $user ) )
+                               ->parseAsBlock()
+               );
 
                if ( $user->getBoolOption( 'watchrollback' ) ) {
                        $user->addWatch( $this->page->getTitle(), User::IGNORE_USER_RIGHTS );
index 5327d7a..d037c36 100644 (file)
@@ -208,6 +208,7 @@ class ApiAuthManagerHelper {
                        $res->status === AuthenticationResponse::RESTART
                ) {
                        $this->formatMessage( $ret, 'message', $res->message );
+                       $ret['messagecode'] = ApiMessage::create( $res->message )->getApiCode();
                }
 
                if ( $res->status === AuthenticationResponse::FAIL ||
index 59227d9..9e00830 100644 (file)
@@ -1116,7 +1116,9 @@ class ApiMain extends ApiBase {
                                )
                        );
                } else {
-                       if ( $config->get( 'ShowExceptionDetails' ) ) {
+                       if ( $config->get( 'ShowExceptionDetails' ) &&
+                               ( !$e instanceof DBError || $config->get( 'ShowDBErrorBacktrace' ) )
+                       ) {
                                $result->addContentValue(
                                        $path,
                                        'trace',
index cde3797..7b2bcfd 100644 (file)
        "apiwarn-tokens-origin": "Tokens may not be obtained when the same-origin policy is not applied.",
        "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>: the limit is $2.",
        "apiwarn-truncatedresult": "This result was truncated because it would otherwise be larger than the limit of $1 bytes.",
-       "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "Unrecognized {{PLURAL:$3|value|values}} for parameter <var>$1</var>: $2.",
        "apiwarn-unsupportedarray": "Parameter <var>$1</var> uses unsupported PHP array syntax.",
        "apiwarn-urlparamwidth": "Ignoring width value set in <var>$1urlparam</var> ($2) in favor of width value derived from <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index e9bb40e..1773279 100644 (file)
        "apihelp-query+deletedrevs-example-mode3-main": "Lister les 50 premières révisions supprimées dans l’espace de noms principal (mode 3)",
        "apihelp-query+deletedrevs-example-mode3-talk": "Lister les 50 premières pages supprimées dans l’espace de noms {{ns:talk}} (mode 3).",
        "apihelp-query+disabled-description": "Ce module de requête a été désactivé.",
-       "apihelp-query+duplicatefiles-description": "Lister tous les fichiers qui sont des doublons des fichiers donnés d’après leurs valeurs de hachage.",
+       "apihelp-query+duplicatefiles-description": "Lister d’après leurs valeurs de hachage, tous les fichiers qui sont des doublons de fichiers donnés.",
        "apihelp-query+duplicatefiles-param-limit": "Combien de fichiers dupliqués à renvoyer.",
        "apihelp-query+duplicatefiles-param-dir": "La direction dans laquelle lister.",
        "apihelp-query+duplicatefiles-param-localonly": "Rechercher les fichiers uniquement dans le référentiel local.",
        "apihelp-query+embeddedin-example-generator": "Obtenir des informations sur les pages incluant <kbd>Template:Stub</kbd>.",
        "apihelp-query+extlinks-description": "Renvoyer toutes les URLs externes (non interwikis) des pages données.",
        "apihelp-query+extlinks-param-limit": "Combien de liens renvoyer.",
-       "apihelp-query+extlinks-param-protocol": "Protocole de l’URL. Si vide et <var>$1query</var> est positionné, le protocole est <kbd>http</kbd>. Laisser à la fois ceci et <var>$1query</var> vide pour lister tous les liens externes.",
+       "apihelp-query+extlinks-param-protocol": "Protocole de l’URL. Si vide et <var>$1query</var> est positionné, le protocole est <kbd>http</kbd>. Laisser à la fois ceci et <var>$1query</var> vides pour lister tous les liens externes.",
        "apihelp-query+extlinks-param-query": "Rechercher une chaîne sans protocole. Utile pour vérifier si une certaine page contient une certaine URL externe.",
        "apihelp-query+extlinks-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
        "apihelp-query+extlinks-example-simple": "Obtenir une liste des liens externes de <kbd>Main Page</kbd>.",
        "apihelp-query+exturlusage-paramvalue-prop-title": "Ajoute le titre et l’ID de l’espace de noms de la page.",
        "apihelp-query+exturlusage-paramvalue-prop-url": "Ajoute l’URL utilisée dans la page.",
        "apihelp-query+exturlusage-param-protocol": "Protocole de l’URL. Si vide et que <var>$1query</var>  est rempli, le protocole est <kbd>http</kbd>. Le laisser avec <var>$1query</var>  vide pour lister tous les liens externes.",
-       "apihelp-query+exturlusage-param-query": "Rechercher une chaîne sans protocole. Voyez [[Special:LinkSearch]]. Le laisser vide liste tous les liens externes.",
+       "apihelp-query+exturlusage-param-query": "Rechercher une chaîne sans protocole. Voyez [[Special:LinkSearch]]. Le laisser vide pour lister tous les liens externes.",
        "apihelp-query+exturlusage-param-namespace": "Les espaces de nom à énumérer.",
        "apihelp-query+exturlusage-param-limit": "Combien de pages renvoyer.",
        "apihelp-query+exturlusage-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
        "apihelp-query+filearchive-paramvalue-prop-bitdepth": "Ajoute la profondeur de bit de la version.",
        "apihelp-query+filearchive-paramvalue-prop-archivename": "Ajoute le nom de fichier de la version d’archive pour les versions autres que la dernière.",
        "apihelp-query+filearchive-example-simple": "Afficher une liste de tous les fichiers supprimés",
-       "apihelp-query+filerepoinfo-description": "Renvoyer les méta-informations sur les référentiels d’image configurés dans le wiki.",
+       "apihelp-query+filerepoinfo-description": "Renvoyer les méta-informations sur les référentiels d’images configurés dans le wiki.",
        "apihelp-query+filerepoinfo-param-prop": "Quelles propriétés du référentiel récupérer (il peut y en avoir plus de disponibles sur certains wikis) :\n;apiurl:URL de l’API du référentiel - utile pour obtenir les infos de l’image depuis l’hôte.\n;name:La clé du référentiel - utilisé par ex. dans les valeurs de retour de <var>[[mw:Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> et [[Special:ApiHelp/query+imageinfo|imageinfo]].\n;displayname:Le nom lisible du wiki référentiel.\n;rooturl:URL racine des chemins d’image.\n;local:Si ce référentiel est le référentiel local ou non.",
        "apihelp-query+filerepoinfo-example-simple": "Obtenir des informations sur les référentiels de fichier.",
        "apihelp-query+fileusage-description": "Trouver toutes les pages qui utilisent les fichiers donnés.",
        "apihelp-query+imageinfo-paramvalue-prop-parsedcomment": "Analyser le commentaire de la version.",
        "apihelp-query+imageinfo-paramvalue-prop-canonicaltitle": "Ajoute le titre canonique du fichier.",
        "apihelp-query+imageinfo-paramvalue-prop-url": "Fournit l’URL du fichier et de la page de description.",
-       "apihelp-query+imageinfo-paramvalue-prop-size": "Ajoute la taille du fichier en octets et sa hauteur, largeur et compteur de page (le cas échéant).",
+       "apihelp-query+imageinfo-paramvalue-prop-size": "Ajoute la taille du fichier en octets et sa hauteur, sa largeur et le compteur de page (le cas échéant).",
        "apihelp-query+imageinfo-paramvalue-prop-dimensions": "Alias pour la taille.",
        "apihelp-query+imageinfo-paramvalue-prop-sha1": "Ajoute le hachage SH1-1 du fichier.",
        "apihelp-query+imageinfo-paramvalue-prop-mime": "Ajoute le type MIME du fichier.",
        "apiwarn-tokens-origin": "Les jetons ne peuvent pas être obtenus quand la politique de même origine n’est pas appliquée.",
        "apiwarn-toomanyvalues": "Trop de valeurs fournies pour le paramètre <var>$1</var>: la limite est $2.",
        "apiwarn-truncatedresult": "Ce résultat a été tronqué parce que sinon, il dépasserait la limite de $1 octets.",
-       "apiwarn-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> a été rendu obsolète. Si, pour une raison quelconque, vous avez besoin de spécifier explicitement l’heure courante sans la recalculer du côté client, utilisez <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> a été rendu obsolète. Si, pour une raison quelconque, vous avez besoin de spécifier explicitement l’heure courante sans la recalculer du côté client, utilisez <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Valeur non reconnue|Valeurs non reconnues}} pour le paramètre <var>$1</var> : $2.",
        "apiwarn-unsupportedarray": "Le paramètre <var>$1</var> utilise une syntaxe PHP de tableau non prise en charge.",
        "apiwarn-urlparamwidth": "Valeur de la largeur définie dans <var>$1urlparam</var> ($2) ignorée en faveur de la largeur calculée à partir de <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index 0865424..f8e3f05 100644 (file)
        "apierror-reauthenticate": "Non se autentificou recentemente nesta sesión. Por favor, volva a autentificarse.",
        "apierror-revwrongpage": "r$1 non é unha revisión de $2.",
        "apierror-searchdisabled": "A busca <var>$1</var> está desactivada.",
+       "apierror-sectionreplacefailed": "Non se puido combinar a sección actualizada.",
+       "apierror-sectionsnotsupported": "As seccións non son compatibles co modelo de contido $1.",
        "apierror-sectionsnotsupported-what": "As seccións non son compatibles con $1.",
        "apierror-show": "Parámetro incorrecto - non se poden proporcionar valores mutuamente excluíntes.",
+       "apierror-siteinfo-includealldenied": "Non se pode ver a información de tódolos servidores a menos que <var>$wgShowHostNames</var> teña valor verdadeiro.",
        "apierror-sizediffdisabled": "A diferenza de tamaño está deshabilitada no modo Miser.",
        "apierror-spamdetected": "A súa edición foi rexeitada por conter un fragmento de publicidade: <code>$1</code>.",
        "apierror-specialpage-cantexecute": "Non ten permiso para ver os resultados desta páxina especial.",
        "apierror-unknownformat": "Formato descoñecido \"$1\".",
        "apierror-unrecognizedparams": "{{PLURAL:$2|Parámetro non recoñecido|Parámetros non recoñecidos}}: $1.",
        "apierror-unrecognizedvalue": "Valor non recoñecido para o parámetro <var>$1</var>: $2.",
+       "apierror-urlparamnormal": "Non se puideron normalizar os parámetros de imaxe de $1.",
+       "apierror-writeapidenied": "Non ten permiso para editar este wiki a través da API.",
+       "apiwarn-alldeletedrevisions-performance": "Para ter un mellor rendemento á hora de xerar títulos, estableza <kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "Non se puido analizar <var>$1urlparam</var> para $2. Só se usará a anchura e a altura.",
        "apiwarn-deprecation-httpsexpected": "Utilizouse HTTP cando esperábase HTTPS.",
        "apiwarn-deprecation-parameter": "O parámetro <var>$1</var> está obsoleto.",
        "apiwarn-invalidcategory": "\"$1\" non é unha categoría.",
index 03e6ded..682f9fc 100644 (file)
@@ -46,6 +46,7 @@
        "apihelp-block-param-allowusertalk": "לאפשר למשתמש לערוך את דף השיחה שלו או שלה (תלוי ב־<var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
        "apihelp-block-param-reblock": "אם המשתמש כבר חסום, לדרוס את החסימה הנוכחית.",
        "apihelp-block-param-watchuser": "לעקוב אחרי דף המשתמש ודף השיחה של המשתמש או של כתובת ה־IP.",
+       "apihelp-block-param-tags": "תגי שינוי שיחולו על העיול ביומן החסימה.",
        "apihelp-block-example-ip-simple": "חסימת כתובת ה־IP‏ <kbd>192.0.2.5</kbd> לשלושה ימים עם הסיבה <kbd>First strike</kbd>.",
        "apihelp-block-example-user-complex": "חסימת המשתמש <kbd>Vandal</kbd> ללא הגבלת זמן עם הסיבה <kbd>Vandalism</kbd>, ומניעת יצירת חשבונות חדשים ושליחת דוא\"ל.",
        "apihelp-changeauthenticationdata-description": "שינוי נתוני אימות עבור המשתמש הנוכחי.",
@@ -89,7 +90,7 @@
        "apihelp-delete-param-title": "כותרת העמוד למחיקה. לא ניתן להשתמש בשילוב עם <var>$1pageid</var>.",
        "apihelp-delete-param-pageid": "מס׳ הזיהוי של העמוד למחיקה. לא ניתן להשתמש בשילוב עם <var>$1title</var>.",
        "apihelp-delete-param-reason": "סיבת המחיקה. אם לא הוגדרה, תתווסף סיבה שנוצרה אוטומטית.",
-       "apihelp-delete-param-tags": "×\9cשנ×\95ת ×\90ת ×\94ת×\92×\99×\9d ×\9b×\93י שיחולו על העיול ביומן המחיקה.",
+       "apihelp-delete-param-tags": "ת×\92×\99 ×©×\99× ×\95י שיחולו על העיול ביומן המחיקה.",
        "apihelp-delete-param-watch": "הוספת העמוד לרשימת המעקב של המשתמש הנוכחי.",
        "apihelp-delete-param-watchlist": "הוספה או הסרה של הדף ללא תנאי מרשימת המעקב של המשתמש הנוכחי, להשתמש בהעדפות או לא לשנות את המעקב.",
        "apihelp-delete-param-unwatch": "הסרת הדף מרשימת המעקב של של המשתמש הנוכחי.",
        "apihelp-import-param-templates": "ליבוא בין אתרי ויקי: לייבא גם את כל התבניות המוכללות.",
        "apihelp-import-param-namespace": "לייבא למרחב השם הזה. לא ניתן להשתמש בזה יחד עם <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "לייבא בתור תת־משנה של הדף הזה. לא ניתן להשתמש בזה יחד עם <var>$1namespace</var>.",
+       "apihelp-import-param-tags": "תגי שינוי שיחולו על העיול ביומן הייבוא ולגרסה הריקה בדפים המיובאים.",
        "apihelp-import-example-import": "לייבא את [[meta:Help:ParserFunctions]] למרחב השם 100 עם היסטוריה מלאה.",
        "apihelp-linkaccount-description": "קישור חשבון של ספק צד־שלישי למשתמש הנוכחי.",
        "apihelp-linkaccount-example-link": "תחילת תהליך הקישור לחשבון מ־<kbd>Example</kbd>.",
        "apihelp-managetags-param-tag": "תג ליצירה, מחיקה, הפעלה או כיבוי. ליצירת תג, התג לא צריך להיות קיים. למחיקת תג, התג צריך להיות קיים. להפעלת תג, התג צריך להתקיים ולא להיות בשימוש של הרחבה. לכיבוי תג, התג צריך להיות קיים ומוגדר ידנית.",
        "apihelp-managetags-param-reason": "סיבה אופציונלית ליצירה, מחיקה, הפעלה או כיבוי של תג.",
        "apihelp-managetags-param-ignorewarnings": "האם להתעלם מכל האזהרות שמופיעות תוך כדי הפעולה.",
+       "apihelp-managetags-param-tags": "תגי השינוי שיחולו על העיול ביומן ניהול התגים.",
        "apihelp-managetags-example-create": "יצירת תג בשם <kbd>spam</kbd> עם הסיבה <kbd>For use in edit patrolling</kbd>",
        "apihelp-managetags-example-delete": "מחיקת התג <kbd>vandlaism</kbd> עם הסיבה <kbd>Misspelt</kbd>",
        "apihelp-managetags-example-activate": "הפעלת התג <kbd>spam</kbd> עם הסיבה <kbd>For use in edit patrolling</kbd>",
        "apihelp-move-param-unwatch": "הסרת הדף וההפניה מרשימת המעקב של המשתמש הנוכחי.",
        "apihelp-move-param-watchlist": "הוספה או הסרה של הדף ללא תנאי מרשימת המעקב של המשתמש הנוכחי, להשתמש בהעדפות או לא לשנות את המעקב.",
        "apihelp-move-param-ignorewarnings": "להתעלם מכל האזהרות.",
+       "apihelp-move-param-tags": "תגי שינוי שיחולו על העיול ביומן ההעברות ולגרסה הריקה בדף היעד.",
        "apihelp-move-example-move": "העברת <kbd>Badtitle</kbd> ל־<kbd>Goodtitle</kbd> בלי להשאיר הפניה.",
        "apihelp-opensearch-description": "חיפוש בוויקי בפרוטוקול OpenSearch.",
        "apihelp-opensearch-param-search": "מחרוזת לחיפוש.",
        "apihelp-query+usercontribs-param-end": "באיזה חותם־הזמן לסיים",
        "apihelp-query+usercontribs-param-user": "עבור אילו משתמשים לאחזר תרומות. לא יכול לשמש עם <var>$1userids</var> או <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-userprefix": "אחזור תרומות עבור כל המשתמשים שהשמות שלהם מתחילים בערך הזה. לא יכול לשמש עם <var>$1user</var> או <var>$1userids</var>.",
+       "apihelp-query+usercontribs-param-userids": "מזהי המשתמשים לאחזור תרומות.  לא יכול לשמש עם  <var>$1user</var> או <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-namespace": "לרשום רק תרומות במרחבי השם האלה.",
        "apihelp-query+usercontribs-param-prop": "לכלול פריטי מידע נוספים:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "הוספת מזהה הדף ומזהה הגרסה.",
        "apihelp-query+userinfo-paramvalue-prop-blockinfo": "מתייג אם המשתמש הנוכחי נחסם, על־ידי מי ומאיזו סיבה.",
        "apihelp-query+userinfo-paramvalue-prop-hasmsg": "הוספת התג <samp>messages</samp> אם למשתמש הנוכחי יש הודעות ממתינות.",
        "apihelp-query+userinfo-paramvalue-prop-groups": "רשימת כל הקבוצות שהמשתמש שייך אליהן.",
+       "apihelp-query+userinfo-paramvalue-prop-groupmemberships": "לרשום קבוצות שהמשתמש הנוכחי משויך אליהן במפורש, כולל תאריך תפוגה לחברות בכל קבוצה.",
        "apihelp-query+userinfo-paramvalue-prop-implicitgroups": "רשימת כל הקבוצות שהמשתמש שייך אליהן באופן אוטומטי.",
        "apihelp-query+userinfo-paramvalue-prop-rights": "רשימת כל ההרשאות שיש למשתמש הזה.",
        "apihelp-query+userinfo-paramvalue-prop-changeablegroups": "רשימת הקבוצות שהמשתמש הנוכחי יכול להוסיף אליהן ולגרוע מהן.",
        "apihelp-query+users-param-prop": "אילו חלקי מידע לקבל:",
        "apihelp-query+users-paramvalue-prop-blockinfo": "מתייג אם המשתמש חסום, על־ידי מי, ומאיזו סיבה.",
        "apihelp-query+users-paramvalue-prop-groups": "רשימת כל הקבוצות שהמשתמש שייך אליהן.",
+       "apihelp-query+users-paramvalue-prop-groupmemberships": "לרשום קבוצות שכל משתמש משויך אליהן במפורש, כולל תאריך תפוגה לחברות בכל קבוצה.",
        "apihelp-query+users-paramvalue-prop-implicitgroups": "רשימת כל הקבוצות שהמשתמש חבר בהן אוטומטית.",
        "apihelp-query+users-paramvalue-prop-rights": "רשימת כל ההרשאות שיש למשתמש.",
        "apihelp-query+users-paramvalue-prop-editcount": "הוספת מניין העריכות של המשתמש.",
        "apihelp-setpagelanguage-description": "שנה את השפה של דף",
        "apihelp-setpagelanguage-description-disabled": "שינוי השפה של דף לא מורשה בוויקי זה.\n\nהפעל את <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> על מנת להשתמש בפעולה זו",
        "apihelp-setpagelanguage-param-title": "כותרת הדף שאת שפתו ברצונך לשנות. לא אפשרי להשתמש באפשרות עם <var>$1pageid</var>.",
+       "apihelp-setpagelanguage-param-reason": "הסיבה לשינוי.",
        "apihelp-setpagelanguage-param-tags": "אילו תגי שינוי להחיל על העיול ביומן שמתבצע כתוצאה מהפעולה הזאת.",
+       "apihelp-setpagelanguage-example-language": "שינוי השפה של <kbd>Main Page</kbd> לבסקית.",
+       "apihelp-setpagelanguage-example-default": "שינוי השפה של הדף בעל המזהה 123 לשפה הרגילה של הוויקי.",
        "apihelp-stashedit-description": "הכנת עריכה במטמון משותף.\n\nזה מיועד לשימוש דרך AJAX מתוך ערך כדי לשפר את הביצועים של שמירת הדף.",
        "apihelp-stashedit-param-title": "כותרת הדף הנערך.",
        "apihelp-stashedit-param-section": "מספר הפסקה. <kbd>0</kbd> עבור הפסקה הראשונה, <kbd>new</kbd> עבור פסקה חדשה.",
        "apierror-integeroutofrange-abovemax": "<var>$1</var> אינו יכול להיות גדול מ־$2 (עכשיו מוגדר $3) עבור משתמשים.",
        "apierror-integeroutofrange-belowminimum": "<var>$1</var> אינו יכול להיות גדול מ־$2 (עכשיו מוגדר $3).",
        "apierror-invalidcategory": "שם הקטגוריה שהזנת אינו תקין.",
+       "apierror-invalidexpiry": "זמן תפוגה בלתי־תקין \"$1\".",
        "apierror-invalid-file-key": "לא מפתח קובץ תקין.",
        "apierror-invalidtitle": "כותרת רעה \"$1\".",
        "apierror-invaliduser": "שם משתמש בלתי־תקין \"$1\".",
        "apierror-upload-filekeyneeded": "חובה לספק <var>filekey</var> כאשר <var>offset</var> אינו אפס.",
        "apierror-upload-filekeynotallowed": "לא ניתן לספק <var>filekey</var> כאשר <var>offset</var> הוא 0.",
        "apierror-upload-missingresult": "אין תוצאות בנתוני מצב.",
+       "apierror-writeapidenied": "אין לך הרשאה לערוך את הוויקי הזה דרך ה־API.",
+       "apiwarn-alldeletedrevisions-performance": "לביצועים טובים יותר בעת יצירת כותרת, יש להשתמש ב־<kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "לא היה אפשר לפענח את <var>$1urlparam</var> עבור $2. משתמשים רק ב־width ו־height.",
+       "apiwarn-badutf8": "הערך הערך שהועבר ל־<var>$1</var> מכיל נתונים בלתי־תקינים או בלתי־מנורמלים. נתונים טקסט אמורים להיות תקינים, מנורמלי NFC ללא תווי בקרה C0 למעט HT (\\t)‏, LF (\\n), ו־CR (\\r).",
+       "apiwarn-checktoken-percentencoding": "נא לבדוק שסימנים כמו \"+\" באסימון מקודדים עם אחוזים בצורה נכונה ב־URL.",
+       "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> הוצהר בתור מיושן. נא להשתמש ב־ <kbd>prop=deletedrevisions</kbd> או ב־<kbd>list=alldeletedrevisions</kbd> במקום זה.",
+       "apiwarn-deprecation-expandtemplates-prop": "מכיוון שלא ניתנו ערכים לפרמטר <var>prop</var>, תסדיר מיושן ישמש לפלט. התסדיר הזה מיושן, ובעתיד יינתן ערך בררת מחדל לפרמטר <var>prop</var>, כך שתמיד ישמש התסדיר החדש.",
+       "apiwarn-deprecation-httpsexpected": "משמש HTTP כשהיה צפוי HTTPS.",
+       "apiwarn-deprecation-login-botpw": "כניסה לחשבון עיקרי (main-account) דרך <kbd>action=login</kbd> מיושנת ועלולה להפסיק לעבוד ללא אזהרה נוספת. כדי להמשיך להיכנס עם <kbd>action=login</kbd>, ר' [[Special:BotPasswords]]. כדי להמשיך באופן מאובטח באמצעות חשבון עיקרי, ר' <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-token": "אחזור אסימון דרך <kbd>action=login</kbd> מיושן. נא להשתמש ב־<kbd>action=query&meta=tokens&type=login</kbd> במקום זה.",
+       "apiwarn-deprecation-parameter": "הפרמטר <var>$1</var> מיושן.",
+       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> מיושן מאז מדיה־ויקי 1.28. יש להשתמש ב־<kbd>prop=headhtml</kbd> בעת יצירת מסמכי HTML חדשים, או ב־<kbd>prop=modules|jsconfigvars</kbd> בעת עדכון מסמך בצד הלקוח.",
+       "apiwarn-deprecation-purge-get": "שימוש ב־<kbd>action=purge</kbd> דרך GET מיושן. יש להשתמש ב־POST במקום זה.",
+       "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> מיושן. יש להשתמש ב־<kbd>$2</kbd> במקום זה.",
+       "apiwarn-difftohidden": "לא היה אפשר לעשות השוואה עם גרסה $1: התוכן מוסתר.",
+       "apiwarn-errorprinterfailed": "מדפיס השגיאות לא עבד. ינסה שוב ללא פרמטרים.",
+       "apiwarn-errorprinterfailed-ex": "מדפיס השגיאות לא עבד (ינסה שוב ללא פרמטרים): $1",
        "apiwarn-invalidcategory": "\"$1\" אינה קטגוריה.",
        "apiwarn-invalidtitle": "\"$1\" אינה כותרת תקינה.",
+       "apiwarn-invalidxmlstylesheetext": "לגיליון הסגנונות אמור להיות הסיומת <code dir=\"ltr\">.xsl</code>.",
+       "apiwarn-invalidxmlstylesheet": "ניתן גיליון סגנונות שאינו תקין או אינו קיים.",
+       "apiwarn-invalidxmlstylesheetns": "גיליון הסגנונות אמור להיות במרחב השם {{ns:MediaWiki}}.",
+       "apiwarn-moduleswithoutvars": "המאפיין <kbd>modules</kbd> לא הוגדר, אבל לא <kbd>jsconfigvars</kbd> או <kbd>encodedjsconfigvars</kbd>. משתני הגדרות נחוצים בשביל שימוש נכון במודולים.",
        "apiwarn-notfile": "\"$1\" אינו קובץ.",
+       "apiwarn-nothumb-noimagehandler": "לא היה אפשר ליצור תמונה ממוזערת כי לקובץ $1 לא משויך מטפל תמונה.",
+       "apiwarn-parse-nocontentmodel": "לא ניתן <var>title</var> או <var>contentmodel</var>, נניח שזה $1.",
+       "apiwarn-parse-titlewithouttext": "<var>title</var> שימש ללא <var>text</var>, והתבקשו מאפייני דף מפוענח. האם התכוונת להשתמש ב־<var>page</var> במקום <var>title</var>?",
+       "apiwarn-redirectsandrevids": "פתרון הפניות לא יכול לשמש יחד עם הפרמטר <var>revids</var>. הפניות ש־<var>revids</var> מצביע אליהן לא נפתרו.",
+       "apiwarn-tokennotallowed": "הפעולה \"$1\" אינה מותרת למשתמש הנוכחי.",
+       "apiwarn-tokens-origin": "לא ניתן לקבל אסימונים כשמדיניות המקור הזהה אינה חלה.",
+       "apiwarn-toomanyvalues": "יותר מדי ערכים סופקו לפרמטר <var>$1</var>: המגבלה היא $2.",
+       "apiwarn-truncatedresult": "התוצאה נחתכה כי אחרת היא הייתה ארוכה מהמגבלה של $1 בתים.",
+       "apiwarn-unclearnowtimestamp": "העברת \"$2\" בתור פרמטר חותם־זמן <var>$1</var> הוצהרה בתור מיושנת. אם מסיבה כלשהי אתם צריכים להגדיר במפורש את הזמן הנוכחי ללא חישובו בצד הלקוח, יש להשתמש ב־<kbd>now</kbd>.",
+       "apiwarn-unrecognizedvalues": "לפרמטר <var>$1</var> היתנ ג{{PLURAL:$3|ניתן ערך בלתי־ידוע|ניתנו ערכים בלתי־ידועים}}: $2.",
+       "apiwarn-unsupportedarray": "הפרמטר <var>$1</var> משתמש בתחביר מערכים שאינו נתמך ב־PHP.",
+       "apiwarn-urlparamwidth": "התעלמות מרוחב (width) שהוגדר ב־<var>$1urlparam</var> (ערך: $2) לטובת רוחב שנגזר מ־<var>$1urlwidth</var>/<var>$1urlheight</var> (ערך: $3).",
+       "apiwarn-validationfailed-badchars": "תווים בלתי־תקינים במפתח (מותרים רק <code>a-z</code>‏, <code>A-Z</code>‏, <code>0-9</code>‏, <code>_</code>, ו־<code>-</code>).",
        "apiwarn-validationfailed-badpref": "לא העדפה תקינה.",
        "apiwarn-validationfailed-cannotset": "לא יכולה להיות מוגדרת על־ידי המודול הזה.",
        "apiwarn-validationfailed-keytoolong": "המפתח ארוך מדי (מותר לכתוב לא יותר מ־$1 בתים).",
        "apiwarn-wgDebugAPI": "<strong>אזהרת אבטחה</strong>: <var dir=\"ltr\">$wgDebugAPI</var> מופעל.",
        "api-feed-error-title": "שגיאה ($1)",
        "api-usage-docref": "ר' $1 לשימוש ב־API.",
+       "api-usage-mailinglist-ref": "עשו מינוי לרשימת התפוצה mediawiki-api-announce בכתובת &lt;https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce&gt; בשביל הודעות על התיישנות API ושינויים שוברים.",
        "api-exception-trace": "$1 בקובץ $2 (שורה $3)\n$4",
        "api-credits-header": "קרדיטים",
        "api-credits": "מפתחי ה־API:\n* רואן קטאו (מפתח מוביל 2007–2009)\n* ויקטור וסילייב\n* בריאן טונג מין\n* סאם ריד\n* יורי אסטרחן (יוצר, מפתח מוביל מספטמבר 2006 עד ספטמבר 2007)\n* בראד יורש (מפתח מוביל מאז 2013)\n\nאנא שלחו הערות, הצעות ושאלות לכתובת mediawiki-api@lists.wikimedia.org או כתבו דיווח באג באתר https://phabricator.wikimedia.org."
index 297f7ed..c3ccad6 100644 (file)
        "apiwarn-deprecation-parse-headitems": "{{doc-apierror}}",
        "apiwarn-deprecation-purge-get": "{{doc-apierror}}",
        "apiwarn-deprecation-withreplacement": "{{doc-apierror}}\n\nParameters:\n* $1 - Query string fragment that is deprecated, e.g. \"action=tokens\".\n* $2 - Query string fragment to use instead, e.g. \"action=tokens\".",
-       "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
+       "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n\n\"r\" is short for \"revision\". You may translate it.",
        "apiwarn-errorprinterfailed": "{{doc-apierror}}",
        "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
        "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
index 93137f4..e3dba0b 100644 (file)
        "apiwarn-tokens-origin": "Токени не можна отримати, поки не застосована політика одного походження.",
        "apiwarn-toomanyvalues": "Надто багато значень задано для параметра <var>$1</var>: ліміт становить $2.",
        "apiwarn-truncatedresult": "Цей результат було скорочено, оскільки інакше він перевищив би ліміт у $1 байтів.",
-       "apiwarn-unclearnowtimestamp": "Вказування «$2» для параметра мітки часу <var>$1</var> є застарілим. Якщо з якоїсь причини Вам треба чітко вказати поточний час без вираховування його з боку клієнта, використайте <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Вказування «$2» для параметра мітки часу <var>$1</var> є застарілим. Якщо з якоїсь причини Вам треба чітко вказати поточний час без вираховування його з боку клієнта, використайте <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Нерозпізнане|Нерозпізнані}} значення для параметра <var>$1</var>: $2.",
        "apiwarn-unsupportedarray": "Параметр <var>$1</var> використовує непідтримуваний синтаксис PHP-масиву.",
        "apiwarn-urlparamwidth": "Ігнорування значення ширини, встановленого в <var>$1urlparam</var> ($2) на користь значення ширини, запозиченого із <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index 07c1741..36251d4 100644 (file)
        "apiwarn-tokennotallowed": "操作“$1”不允许当前用户使用。",
        "apiwarn-toomanyvalues": "参数<var>$1</var>指定了太多的值:上限为$2。",
        "apiwarn-truncatedresult": "此结果被缩短,否则其将大于$1字节的限制。",
-       "apiwarn-unclearnowtimestamp": "为时间戳参数<var>$1</var>传递“$2”已被弃用。如因某些原因您需要明确指定当前时间而不计算客户端,请使用<kbd>now<kbd>。",
+       "apiwarn-unclearnowtimestamp": "为时间戳参数<var>$1</var>传递“$2”已被弃用。如因某些原因您需要明确指定当前时间而不计算客户端,请使用<kbd>now</kbd>。",
        "apiwarn-unrecognizedvalues": "参数<var>$1</var>有无法识别的{{PLURAL:$3|值}}:$2。",
        "apiwarn-unsupportedarray": "参数<var>$1</var>使用未受支持的PHP数组语法。",
        "apiwarn-validationfailed-badchars": "关键词中的字符无效(只允许<code>a-z</code>、<code>A-Z</code>、<code>0-9</code>、<code>_</code>和<code>-</code>)。",
index 7659d6c..d67bc7e 100644 (file)
@@ -67,7 +67,7 @@ abstract class Collation {
                                return new CollationFa;
                        default:
                                $match = [];
-                               if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
+                               if ( preg_match( '/^uca-([A-Za-z@=-]+)$/', $collationName, $match ) ) {
                                        return new IcuCollation( $match[1] );
                                }
 
index 5c2b320..b950420 100644 (file)
@@ -65,6 +65,7 @@
        "config-apc": "[http://www.php.net/apc APC] е инсталиран",
        "config-apcu": "[http://www.php.net/apc APC] е инсталиран",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] е инсталиран",
+       "config-no-cache-apcu": "<strong>Внимание:</strong> [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] и [http://www.iis.net/download/WinCacheForPhp WinCache] не могат да бъдат открити.\nКеширането на обекти не е активирано.",
        "config-mod-security": "<strong>Предупреждение:</strong> [http://modsecurity.org/ mod_security]/mod_security2 е включено на вашия уеб сървър. Много от обичайните му конфигурации пораждат проблеми с МедияУики и друг софтуер, който позволява публикуване на произволно съдържание.\nАко е възможно, моля изключете го. В противен случай се обърнете към [http://modsecurity.org/documentation/ документацията на mod_security] или се свържете с поддръжката на хостинга си, ако се сблъскате със случайни грешки.",
        "config-diff3-bad": "GNU diff3 не беше намерен.",
        "config-git": "Налична е системата за контрол на версиите Git: <code>$1</code>.",
@@ -84,6 +85,7 @@
        "config-db-host": "Хост на базата от данни:",
        "config-db-host-help": "Ако базата от данни е на друг сървър, в кутията се въвежда името на хоста или IP адреса.\n\nАко се използва споделен уеб хостинг, доставчикът на услугата би трябвало да е предоставил в документацията си коректния хост.\n\nАко инсталацията протича на Windows-сървър и се използва MySQL, използването на \"localhost\" може да е неприемливо. В такива случаи се използва \"127.0.0.1\" за локален IP адрес.\n\nПри използване на PostgreSQL, това поле се оставя празно, за свързване чрез Unix socket.",
        "config-db-host-oracle": "TNS на базата данни:",
+       "config-db-host-oracle-help": "Въведете валидно [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name]; файлът tnsnames.ora трябва да бъде видим за инсталацията.<br />Ако използвате клиентска библиотека версия 10g или по-нова можете да използвате метода [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
        "config-db-wiki-settings": "Идентифициране на това уики",
        "config-db-name": "Име на базата от данни:",
        "config-db-name-help": "Избира се име, което да идентифицира уикито.\nТо не трябва да съдържа интервали.\n\nАко се използва споделен хостинг, доставчикът на услугата би трябвало да е предоставил или име на базата от данни, която да бъде използвана, или да позволява създаването на бази от данни чрез контролния панел.",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-myisam-dep": "'''Предупреждение''': Избрана е MyISAM като система за складиране в MySQL, която не се препоръчва за използване с МедияУики, защото:\n* почти не поддържа паралелност заради заключване на таблиците\n* е по-податлива на повреди в сравнение с други системи\n* кодът на МедияУики не винаги поддържа MyISAM коректно\n\nАко инсталацията на MySQL поддържа InnoDB, силно е препоръчително да се използва тя.\nАко инсталацията на MySQL не поддържа InnoDB, вероятно е време за обновяване.",
+       "config-mysql-only-myisam-dep": "<strong>Внимание:</strong> MyISAM e единственият наличен на тази машина тип на таблиците за MySQL и не е препоръчителен за употреба при МедияУики защото:\n* има слаба поддръжка на конкурентност на заявките, поради закючването на таблиците\n* е много по-податлив на грешки в базите от данни от другите типове таблици\n* кодът на МедияУики не винаги работи с MyISAM както трябва\n\nВашият MySQL не поддържа InnoDB, така че може би е дошло време за актуализиране.",
        "config-mysql-engine-help": "'''InnoDB''' почти винаги е най-добрата възможност заради навременната си поддръжка.\n\n'''MyISAM''' може да е по-бърза при инсталации с един потребител или само за четене.\nБазите от данни MyISAM се повреждат по-често от InnoDB.",
        "config-mysql-charset": "Набор от символи в базата от данни:",
        "config-mysql-binary": "Бинарен",
        "config-mysql-utf8": "UTF-8",
        "config-mysql-charset-help": "В '''бинарен режим''' МедияУики съхранява текстовете в UTF-8 в бинарни полета в базата от данни.\nТова е по-ефективно от UTF-8 режима на MySQL и позволява използването на пълния набор от символи в Уникод.\n\nВ '''UTF-8 режим''' MySQL ще знае в кой набор от символи са данните от уикито и ще може да ги показва и променя по подходящ начин, но няма да позволява складиране на символи извън [https://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Основния многоезичен набор].",
        "config-mssql-auth": "Тип на удостоверяването:",
+       "config-mssql-install-auth": "Изберете начин за удостоверяване, който ще бъде използван за връзка с базата от данни по време на инсталацията.\nАко изберете \"{{int:config-mssql-windowsauth}}\", ще се използват идентификационните данни на потребителя под който работи уеб сървъра.",
+       "config-mssql-web-auth": "Изберете начина за удостоверяване, който ще се използва от уеб сървъра за връзка със сървъра за бази от данни по време на нормалните операции на уикито.\nАко изберете \"{{int:config-mssql-windowsauth}}\", ще се използват идентификационните данни на потребителя под който работи уеб сървъра.",
        "config-mssql-sqlauth": "Удостоверяване чрез SQL Server",
        "config-mssql-windowsauth": "Удостоверяване чрез Windows",
        "config-site-name": "Име на уикито:",
index f34849b..70ef27a 100644 (file)
        "config-profile-help": "Викијата функционираат најдобро кога имаат што повеќе уредници.\nВо МедијаВики лесно се проверуваат скорешните промени, и лесно се исправа (технички: „враќа“) штетата направена од неупатени или злонамерни корисници.\n\nМногумина имаат најдено најразлични полезни примени за МедијаВики, но понекогаш не е лесно да убедите некого во предностите на вики-концептот.\nЗначи имате избор.\n\n'''{{int:config-profile-wiki}}''' — модел според кој секој може да уредува, дури и без најавување.\nАко имате вики со '''задолжително отворање на сметка''', тогаш добивате повеќе контрола, но ова може даги одврати спонтаните учесници.\n\n'''{{int:config-profile-fishbowl}}''' — може да уредуваат само уредници што имаат добиено дозвола за тоа, но јавноста може да ги гледа страниците, вклучувајќи ја нивната историја.\n'''{{int:config-profile-private}}''' — страниците се видливи и уредливи само за овластени корисници.\n\nПо воспоставката имате на избор и посложени кориснички права и поставки. Погледајте во [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights прирачникот].",
        "config-license": "Авторски права и лиценца:",
        "config-license-none": "Без подножје за лиценца",
-       "config-license-cc-by-sa": "Криејтив комонс НаведиИзвор СподелиПодИстиУслови",
-       "config-license-cc-by": "Криејтив комонс НаведиИзвор",
-       "config-license-cc-by-nc-sa": "Криејтив комонс НаведиИзвор-Некомерцијално-СподелиПодИстиУслови",
+       "config-license-cc-by-sa": "Криејтив комонс Наведи извор-Сподели под исти услови",
+       "config-license-cc-by": "Криејтив комонс Наведи извор",
+       "config-license-cc-by-nc-sa": "Криејтив комонс Наведи извор-Сподели под исти услови",
        "config-license-cc-0": "Криејтив комонс Нула (јавна сопственост)",
        "config-license-gfdl": "ГНУ-ова лиценца за слободна документација 1.3 или понова",
        "config-license-pd": "Јавна сопственост",
index 9d800a2..1c5c77e 100644 (file)
@@ -3467,4 +3467,4 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 }
 
-class_alias( 'Database', 'DatabaseBase' );
+class_alias( Database::class, 'DatabaseBase' );
index d394692..db5b7e5 100644 (file)
@@ -18,4 +18,4 @@ class Blob implements IBlob {
        }
 }
 
-class_alias( 'Wikimedia\Rdbms\Blob', 'Blob' );
+class_alias( Blob::class, 'Blob' );
index 7a25f03..7918f36 100644 (file)
@@ -32,4 +32,4 @@ interface Field {
        function isNullable();
 }
 
-class_alias( 'Wikimedia\Rdbms\Field', 'Field' );
+class_alias( Field::class, 'Field' );
index 71e5939..6d2bc0d 100644 (file)
@@ -461,13 +461,28 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * @param array $localFileRefs List of files
         */
        protected function saveFileDependencies( ResourceLoaderContext $context, $localFileRefs ) {
-               // Normalise array
-               $localFileRefs = array_values( array_unique( $localFileRefs ) );
-               sort( $localFileRefs );
 
                try {
+                       // Related bugs and performance considerations:
+                       // 1. Don't needlessly change the database value with the same list in a
+                       //    different order or with duplicates.
+                       // 2. Use relative paths to avoid ghost entries when $IP changes. (T111481)
+                       // 3. Don't needlessly replace the database with the same value
+                       //    just because $IP changed (e.g. when upgrading a wiki).
+                       // 4. Don't create an endless replace loop on every request for this
+                       //    module when '../' is used anywhere. Even though both are expanded
+                       //    (one expanded by getFileDependencies from the DB, the other is
+                       //    still raw as originally read by RL), the latter has not
+                       //    been normalized yet.
+
+                       // Normalise
+                       $localFileRefs = array_values( array_unique( $localFileRefs ) );
+                       sort( $localFileRefs );
+                       $localPaths = self::getRelativePaths( $localFileRefs );
+
+                       $storedPaths = self::getRelativePaths( $this->getFileDependencies( $context ) );
                        // If the list has been modified since last time we cached it, update the cache
-                       if ( $localFileRefs !== $this->getFileDependencies( $context ) ) {
+                       if ( $localPaths !== $storedPaths ) {
                                $vary = $context->getSkin() . '|' . $context->getLanguage();
                                $cache = ObjectCache::getLocalClusterInstance();
                                $key = $cache->makeKey( __METHOD__, $this->getName(), $vary );
@@ -476,8 +491,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
                                        return; // T124649; avoid write slams
                                }
 
-                               // Use relative paths to avoid ghost entries when $IP changes (T111481)
-                               $deps = FormatJson::encode( self::getRelativePaths( $localFileRefs ) );
+                               $deps = FormatJson::encode( $localPaths );
                                $dbw = wfGetDB( DB_MASTER );
                                $dbw->upsert( 'module_deps',
                                        [
index 14d6e05..e8574f4 100644 (file)
@@ -357,6 +357,11 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        }
                }
 
+               if ( !$wikiModules ) {
+                       // Nothing to preload
+                       return;
+               }
+
                $pageNames = array_keys( $allPages );
                sort( $pageNames );
                $hash = sha1( implode( '|', $pageNames ) );
index d0a2f92..1b32503 100644 (file)
@@ -1862,7 +1862,7 @@ class User implements IDBAccessObject {
         */
        public function isPingLimitable() {
                global $wgRateLimitsExcludedIPs;
-               if ( in_array( $this->getRequest()->getIP(), $wgRateLimitsExcludedIPs ) ) {
+               if ( IP::isInRanges( $this->getRequest()->getIP(), $wgRateLimitsExcludedIPs ) ) {
                        // No other good way currently to disable rate limits
                        // for specific IPs. :P
                        // But this is a crappy hack and should die.
index 0bfd4a2..55e228a 100644 (file)
@@ -291,15 +291,6 @@ EOD;
                foreach ( glob( $this->basepath . '/*.php' ) as $file ) {
                        $this->readFile( $file );
                }
-
-               // Legacy aliases (1.28)
-               $this->forceClassPath( 'DatabaseBase',
-                       $this->basepath . '/includes/libs/rdbms/database/Database.php' );
-               // Legacy aliases (1.29)
-               $this->forceClassPath( 'Blob',
-                       $this->basepath . '/includes/libs/rdbms/encasing/Blob.php' );
-               $this->forceClassPath( 'Field',
-                       $this->basepath . '/includes/libs/rdbms/field/Field.php' );
        }
 }
 
@@ -328,6 +319,11 @@ class ClassCollector {
         */
        protected $tokens;
 
+       /**
+        * @var array Class alias with target/name fields
+        */
+       protected $alias;
+
        /**
         * @var string $code PHP code (including <?php) to detect class names from
         * @return array List of FQCN detected within the tokens
@@ -336,6 +332,7 @@ class ClassCollector {
                $this->namespace = '';
                $this->classes = [];
                $this->startToken = null;
+               $this->alias = null;
                $this->tokens = [];
 
                foreach ( token_get_all( $code ) as $token ) {
@@ -358,6 +355,8 @@ class ClassCollector {
                if ( is_string( $token ) ) {
                        return;
                }
+               // Note: When changing class name discovery logic,
+               // AutoLoaderTest.php may also need to be updated.
                switch ( $token[0] ) {
                case T_NAMESPACE:
                case T_CLASS:
@@ -365,6 +364,12 @@ class ClassCollector {
                case T_TRAIT:
                case T_DOUBLE_COLON:
                        $this->startToken = $token;
+                       break;
+               case T_STRING:
+                       if ( $token[1] === 'class_alias' ) {
+                               $this->startToken = $token;
+                               $this->alias = [];
+                       }
                }
        }
 
@@ -388,6 +393,49 @@ class ClassCollector {
                        }
                        break;
 
+               case T_STRING:
+                       if ( $this->alias !== null ) {
+                               // Flow 1 - Two string literals:
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_CONSTANT_ENCAPSED_STRING 'TargetClass'
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               // Flow 2 - Use of ::class syntax for first parameter
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_STRING TargetClass
+                               // - T_DOUBLE_COLON ::
+                               // - T_CLASS class
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               if ( $token === '(' ) {
+                                       // Start of a function call to class_alias()
+                                       $this->alias = [ 'target' => false, 'name' => false ];
+                               } elseif ( $token === ',' ) {
+                                       // Record that we're past the first parameter
+                                       if ( $this->alias['target'] === false ) {
+                                               $this->alias['target'] = true;
+                                       }
+                               } elseif ( is_array( $token ) && $token[0] === T_CONSTANT_ENCAPSED_STRING ) {
+                                       if ( $this->alias['target'] === true ) {
+                                               // We already saw a first argument, this must be the second.
+                                               // Strip quotes from the string literal.
+                                               $this->alias['name'] = substr( $token[1], 1, -1 );
+                                       }
+                               } elseif ( $token === ')' ) {
+                                       // End of function call
+                                       $this->classes[] = $this->alias['name'];
+                                       $this->alias = null;
+                                       $this->startToken = null;
+                               }
+                       }
+                       break;
+
                case T_CLASS:
                case T_INTERFACE:
                case T_TRAIT:
index 2e71999..996af71 100644 (file)
        "rev-deleted-text-unhide": "Гэтая вэрсія старонкі была <strong>выдаленая</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-suppressed-text-unhide": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-deleted-text-view": "Гэтая вэрсія старонкі была <strong>выдаленая</strong>.\nВы можаце праглядзець яе; падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
-       "rev-suppressed-text-view": "Гэтая вэрсія старонкі была '''схаваная'''.\nВы можаце яе праглядзець; падрабязнасьці могуць быць знойдзеныя ў  [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
+       "rev-suppressed-text-view": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nВы можаце яе праглядзець; падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
        "rev-deleted-no-diff": "Вы ня можаце праглядаць гэтую розьніцу паміж вэрсіямі, таму што адна з вэрсіяў была '''выдаленая'''.\nМагчыма, падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
        "rev-suppressed-no-diff": "Вы ня можаце праглядзець гэтую розьніцу, таму што адна з вэрсіяў была '''выдаленая'''.",
        "rev-deleted-unhide-diff": "Адна з вэрсіяў гэтай старонкі была '''выдаленая'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].\nВы можаце праглядзець [$1 розьніцу паміж вэрсіямі], калі жадаеце.",
        "authmanager-authn-no-local-user": "Пададзеныя ўліковыя зьвесткі не зьвязаныя зь ніводным удзельнікам гэтай вікі.",
        "authmanager-authn-autocreate-failed": "Аўтаматычнае стварэньне лякальнага рахунку не атрымалася: $1",
        "authmanager-change-not-supported": "Пададзеныя ўліковыя зьвесткі ня могуць быць зьмененыя, бо яны ня будуць выкарыстаныя.",
+       "authmanager-create-disabled": "Стварэньне рахункаў адключанае.",
        "authmanager-realname-label": "Сапраўднае імя",
        "authmanager-provider-temporarypassword": "Часовы пароль",
        "changecredentials": "Зьмена ўліковых зьвестак",
index c378228..5abee6a 100644 (file)
        "activeusers-intro": "Гэта пералік удзельнікаў, якія нешта рабілі за апошнія $1 {{PLURAL:$1|дзень|дзён}}.",
        "activeusers-count": "$1 {{PLURAL:$1|дзеянне|дзеянні|дзеянняў}} за апошні{{PLURAL:$3| дзень|я $3 дні|я $3 дзён}}",
        "activeusers-from": "Паказ, пачынаючы з:",
-       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да групаў:",
+       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да груп:",
        "activeusers-noresult": "Няма такіх удзельнікаў.",
        "activeusers-submit": "Паказаць актыўных удзельнікаў",
        "listgrouprights": "Дазволы для груп удзельнікаў",
index dafddd5..0f96934 100644 (file)
        "continue-editing": "Продължаване към полето за редактиране",
        "previewconflict": "Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.",
        "session_fail_preview": "За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия.\n\nМоже би сте излезли от системата. <strong>Моля, уверете се, че сте влезли в профила си и опитайте отново.</strong>\nАко все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново, също така проверете дали браузърът ви позволява бисквитки от този сайт.",
-       "session_fail_preview_html": "'''За съжаление редакцията ви не беше записана поради изтичането на сесията ви.'''\n\n''Тъй като {{SITENAME}} приема обикновен HTML, предварителният преглед е скрит като предпазна мярка срещу атаки чрез Джаваскрипт.''\n\n'''Опитайте отново. Ако все още не сработва, пробвайте да [[Special:UserLogout|излезете]] и влезете отново.'''",
+       "session_fail_preview_html": "За съжаление редакцията ви не беше записана поради изтичането на сесията ви.\n\n<em>Тъй като {{SITENAME}} приема обикновен HTML, предварителният преглед е скрит като предпазна мярка срещу атаки чрез JavaScript.</em>\n\n<strong>Ако това е обикновен опит за редактиране, моля опитайте отново.</strong>\nАко все още не сработва, пробвайте да [[Special:UserLogout|излезете]] и влезете отново, и се уверете, че браузъра ви приема бисквитки от този сайт.",
        "token_suffix_mismatch": "'''Редакцията ви беше отхвърлена, защото браузърът ви е развалил пунктуационните знаци в редакционната отметка. Евентуалното съхранение би унищожило съдържанието на страницата. Понякога това се случва при използването на грешно работещи анонимни междинни сървъри.'''",
        "edit_form_incomplete": "'''Някои части от формуляра за редактиране не достигнаха до сървъра; проверете дали редакциите ви са непокътнати и опитайте отново.'''",
        "editing": "Редактиране на „$1“",
index aeff6e5..2fb3622 100644 (file)
        "apisandbox-results": "ফলাফল",
        "apisandbox-sending-request": "API অনুরোধ পাঠানো হচ্ছে...",
        "apisandbox-loading-results": "API ফলাফল গ্রহণ করা হচ্ছে...",
+       "apisandbox-results-error": "এপিআই কুয়েরির প্রতিক্রিয়া লোড করার সময় একটি ত্রুটি ঘটেছে: $1।",
        "apisandbox-request-selectformat-label": "অনুরোধ উপাত্ত এভাবে দেখান:",
        "apisandbox-request-format-url-label": "URL কোয়েরি স্ট্রিং",
        "apisandbox-request-url-label": "অনুরোধের URL:",
        "undeletehistorynoadmin": "এই পাতাটি মুছে ফেলা হয়েছে। মুছে ফেলার কারণ নিচের সারাংশে দেখানো হল। সেই সাথে মুছে ফেলার আগে যেসমস্ত ব্যবহারকারী পাতাটি সম্পাদনা করেছেন, তাদের সম্পর্কেও বিস্তারিত দেখানো হল। এই মুছে ফেলা সংশোধনগুলির বিষয়বস্তু  কেবল প্রশাসকদের কাছে লভ্য।",
        "undelete-revision": "$3-এর করা $1 সংশোধন ($4 তারিখে, $5 সময়ের) মুছে ফেলা হয়েছে:",
        "undeleterevision-missing": "সংশোধনটি অবৈধ কিংবা হারানো গেছে। আপনি হয়ত অচল সংযোগে ক্লিক করেছেন, কিংবা সংশোধনটি হয়ত বাতিল করে পাতাটি পূর্বাবস্থায় নেওয়া হয়েছে, অথবা সংশোধনটি আর্কাইভ থেকে মুছে ফেলা হয়েছে।",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|একটি সংশোধন|$1টি সংশোধন}} পুনরুদ্ধার করা যাবে না, কারণ {{PLURAL:$1|এটির|এগুলির}} <code>rev_id</code> ইতিমধ্যেই ব্যবহৃত হয়েছে।",
        "undelete-nodiff": "পূর্বের কোন সংশোধন খুঁজে পাওয়া যায়নি।",
        "undeletebtn": "পুনরুদ্ধার",
        "undeletelink": "দেখুন/পুনর্বহাল করুন",
        "proxyblockreason": "আপনার আইপি ঠিকানাকে বাধা দেয়া হয়েছে কারণ এটি একটি উন্মুক্ত প্রক্সি। অনুগ্রহ করে আপনার ইন্টারনেট সেবা প্রদানকারী কোম্পানির সাথে কারিগরি সহায়তার ব্যাপারে যোগাযোগ করুন এবং এই গুরুত্বপূর্ণ নিরাপত্তা সমস্যার ব্যাপারে তাদেরকে অবহিত করুন।",
        "sorbsreason": "আপনার আইপি ঠিকানাটি {{SITENAME}}-এর ব্যবহার করা DNSBL-এ উন্মুক্ত প্রক্সি হিসেবে তালিকাভুক্ত আছে।",
        "sorbs_create_account_reason": "আপনার আইপি ঠিকানাটি {{SITENAME}}-এর ব্যবহার করা DNSBL-এ উন্মুক্ত প্রক্সি হিসেবে তালিকাভুক্ত আছে। আপনি কোন অ্যাকাউন্ট সৃষ্টি করতে পারবেন না।",
+       "softblockrangesreason": "বেনামী অবদান আপনার আইপি ঠিকানা থেকে অনুমোদিত নয় ($1)। দয়া করে প্রবেশ করুন।",
        "xffblockreason": "X-Forwarded-For হেডারে থাকা আইপি ঠিকানাটি ব্লক করা হয়েছে, হয় এটি আপনার নিজের অথবা আপনার ব্যবহৃত প্রক্সি সার্ভারের আইপি ঠিকানা। ব্লক করার কারণ হল: $1",
        "cant-see-hidden-user": "আপনি যে ব্যবহারকারীকে ব্লক বা লুকিয়ে রাখতে চাচ্ছেন তাকে আগে থেকেই ব্লক বা লুকিয়ে রাখা হয়েছে। এছাড়া আপনার Hideuser অধিকার নেই, তাই আপনি ব্যবহারকারীর অবস্থা পরিবর্তন করতে পারবেন না।",
        "ipbblocked": "আপনি অন্য কোন ব্যবহারকরীকে ব্লক বা আনব্লক করতে পারবেন না, কারণ আপনি নিজেই ব্লক রয়েছেন",
        "cant-move-category-page": "আপনার বিষয়শ্রেণী পাতা স্থানান্তরের অনুমতি নেই।",
        "cant-move-to-category-page": "আপনার পাতাটিকে বিষয়শ্রেণী পাতায় স্থানান্তরের অনুমতি নেই।",
        "cant-move-subpages": "আপনার উপপাতা স্থানান্তরের অনুমতি নেই।",
+       "namespace-nosubpages": "\"$1\" নামস্থান উপপাতার অনুমতি দেয় না।",
        "newtitle": "নতুন শিরোনাম:",
        "move-watch": "এই পাতাটি নজরে রাখুন",
        "movepagebtn": "পাতা স্থানান্তর করুন",
        "movelogpagetext": "সরানো পাতাগুলির একটি তালিকা নিচে দেয়া হল।",
        "movesubpage": "{{PLURAL:$1|উপপাতা|উপপাতাসমূহ}}",
        "movesubpagetext": "এই পাতার $1টি {{PLURAL:$1|উপপাতা}} রয়েছে যেগুলো নিচে দেখানো হচ্ছে।",
+       "movesubpagetalktext": "সংশ্লিষ্ট আলাপ পাতার $1টি {{PLURAL:$1|উপপাতা}} রয়েছে যেগুলো নিচে দেখানো হচ্ছে।",
        "movenosubpage": "এই পাতাটির কোনো উপপাতা নেই।",
        "movereason": "কারণ:",
        "revertmove": "পূর্বাবস্থায় ফেরত নেওয়া হোক",
        "tags-delete-reason": "কারণ:",
        "tags-delete-submit": "অপরিবর্তনীয় এই ট্যাগ অপসারন করো",
        "tags-delete-not-found": "\"$1\" ট্যাগ বিদ্যমান নয়।",
+       "tags-delete-too-many-uses": "\"$1\" ট্যাগটি $2টিরও অধিক {{PLURAL:$2|সংশোধনে}} প্রয়োগ করা হয়েছে, যার অর্থ এটি অপসারণ করা যাবে না।",
        "tags-delete-no-permission": "আপনার পরিবর্তন ট্যাগ মুছে ফেলার অনুমতি নেই।",
        "tags-activate-title": "সক্রিয় ট্যাগ",
        "tags-activate-question": "আপনি ট্যাগ \"$1\" সক্রিয় করতে চলেছেন।",
        "tags-deactivate-reason": "কারণ:",
        "tags-deactivate-not-allowed": "ট্যাগ \"$1\" নিষ্ক্রিয় করা সম্ভব নয়।",
        "tags-deactivate-submit": "নিষ্ক্রিয়",
+       "tags-apply-no-permission": "আপনার পরিবর্তনসহ আপনার ট্যাগ পরিবর্তন প্রয়োগ করার অনুমতি নেই।",
+       "tags-apply-not-allowed-one": "\"$1\" ট্যাগটি ম্যানুয়ালি প্রয়োগ করা যাবে না।",
+       "tags-apply-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি প্রয়োগ করা যাবে না: $1",
+       "tags-update-no-permission": "স্বতন্ত্র সংশোধন বা লগের ভুক্তি থেকে আপনার ট্যাগ পরিবর্তন যোগ বা বাতিল করার অনুমতি নেই।",
+       "tags-update-add-not-allowed-one": "\"$1\" ট্যাগটি ম্যানুয়ালি যোগ করা যাবে না।",
+       "tags-update-add-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি যোগ করা যাবে না: $1",
+       "tags-update-remove-not-allowed-one": "\"$1\" ট্যাগটি বাতিল করা যাবে না।",
+       "tags-update-remove-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি বাতিল করা যাবে না: $1",
        "tags-edit-title": "ট্যাগ সম্পাদনা করুন",
        "tags-edit-manage-link": "ট্যাগ পরিচালনা করুন",
        "tags-edit-revision-selected": "[[:$2]] পাতার {{PLURAL:$1|নির্বাচিত সংশোধন|নির্বাচিত সংশোধনসমূহ}}:",
        "tags-edit-logentry-selected": "{{PLURAL:$1|নির্বাচিত লগ ইভেন্ট}}:",
+       "tags-edit-logentry-legend": "{{PLURAL:$1|এই লগের ভুক্তি|$1টি লগের ভুক্তি}} থেকে ট্যাগ যোগ বা বাতিল করুন",
        "tags-edit-existing-tags": "বিদ্যমান ট্যাগ:",
        "tags-edit-existing-tags-none": "<em>কোনটি নয়</em>",
        "tags-edit-new-tags": "নতুন ট্যাগ:",
        "tags-edit-chosen-placeholder": "কিছু ট্যাগ নির্বাচন করুন",
        "tags-edit-chosen-no-results": "কোন ট্যাগ মিল পাওয়া যায়নি",
        "tags-edit-reason": "কারণ:",
-       "tags-edit-revision-submit": "Apply changes to {{PLURAL:$1|এই সংশোধনে|$1 সংশোধনসমূহে}} পরিবর্তন প্রয়োগ করুন",
+       "tags-edit-revision-submit": "{{PLURAL:$1|এই সংশোধনে|$1টি সংশোধনে}} পরিবর্তন প্রয়োগ করুন",
+       "tags-edit-logentry-submit": "{{PLURAL:$1|এই লগের ভুক্তিতে|$1টি লগের ভুক্তিতে}} পরিবর্তন প্রয়োগ করুন",
        "tags-edit-success": "পরিবর্তন প্রয়োগ করা হয়েছে।",
        "tags-edit-failure": "পরিবর্তন প্রয়োগ করা যায়নি: $1",
        "tags-edit-nooldid-title": "লক্ষ্য সংশোধন অবৈধ",
        "htmlform-date-placeholder": "বববব-মম-দদ",
        "htmlform-time-placeholder": "ঘঘ:মম:সস",
        "htmlform-datetime-placeholder": "বববব-মম-দদ ঘঘ:মম:সস",
+       "htmlform-date-invalid": "প্রদানকৃত মানটি স্বীকৃত তারিখ নয়। বববব-মম-দদ বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-time-invalid": "প্রদানকৃত মানটি স্বীকৃত সময় নয়। ঘঘ:মম:সস বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-datetime-invalid": "প্রদানকৃত মানটি স্বীকৃত তারিখ ও সময় নয়। বববব-মম-দদ ঘঘ:মম:সস বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-date-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ $1-এর অনেক আগের।",
+       "htmlform-date-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ $1-এর অনেক পরের।",
+       "htmlform-time-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত সময় $1-এর অনেক আগের।",
+       "htmlform-time-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত সময় $1-এর অনেক পরের।",
+       "htmlform-datetime-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ ও সময় $1-এর অনেক আগের।",
+       "htmlform-datetime-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ ও সময় $1-এর অনেক পরের।",
        "htmlform-title-badnamespace": "[[:$1]] \"{{ns:$2}}\" নামস্থানে খুঁজে পাওয়া যায়নি।",
        "htmlform-title-not-creatable": "\"$1\" সৃষ্টিযোগ্য পাতার শিরোনাম নয়",
        "htmlform-title-not-exists": "$1-এর অস্তিত্ব নেই।",
        "logentry-upload-overwrite": "$1 $3-এর একটি নতুন সংস্করণ {{GENDER:$2|আপলোড করেছেন}}",
        "logentry-upload-revert": "$1 $3 {{GENDER:$2|আপলোড করেছেন}}",
        "log-name-managetags": "ট্যাগ ব্যবস্থাপনা লগ",
-       "logentry-managetags-create": "$1 \"$4\" ট্যাগ {{GENDER:$2|তৈরি করেছে}}",
+       "logentry-managetags-create": "$1 \"$4\" ট্যাগটি {{GENDER:$2|তৈরি করেছেন}}",
        "logentry-managetags-delete": "$1 \"$4\" ট্যাগটি {{GENDER:$2|অপসারণ করেছেন}} ($5টি {{PLURAL:$5|সংস্করণ বা লগ ভুক্তি|সংস্করণ ও/বা লগ ভুক্তি}} সরানো হয়েছে)",
+       "logentry-managetags-deactivate": "$1 \"$4\" ট্যাগটি ব্যবহারকারী ও বট দ্বারা ব্যবহারের জন্য {{GENDER:$2|নিষ্ক্রিয়}} করেছেন",
        "log-name-tag": "ট্যাগ লগ",
        "rightsnone": "(কিছু নাই)",
        "revdelete-summary": "সম্পাদনা সারাংশ",
index fed7683..351ac32 100644 (file)
        "invalid-content-data": "Ugyldig indholdsdata",
        "content-not-allowed-here": "\"$1\" indhold er ikke tilladt på siden [[$2]]",
        "editwarning-warning": "Hvis du forlader siden nu, risikerer du at miste alle ændringer, som du har lavet.\nDenne advarsel kan slås fra under \"{{int:prefs-editing}}\" i dine indstillinger.",
+       "editpage-invalidcontentmodel-title": "Indholdsmodellen er ikke understøttet",
        "editpage-notsupportedcontentformat-title": "Indholdsformatet understøttes ikke",
        "editpage-notsupportedcontentformat-text": "Indholdsformatet $1 understøttes ikke af indholdsmodellen $2",
        "content-model-wikitext": "wikitekst",
        "content-model-css": "CSS",
        "content-json-empty-object": "Tomt objekt",
        "content-json-empty-array": "Tomt array",
+       "deprecated-self-close-category": "Sider, der bruger ugyldige, selvlukkende HTML-tags",
        "duplicate-args-category": "Sider der bruger samme argument mere end en gang i en skabelon",
        "duplicate-args-category-desc": "Siden indeholder en skabelon hvor et argument er brugt mere end en gang, som <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> eller <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Advarsel: Der er for mange beregningstunge oversætter-funktionskald på denne side.\n\nDer bør være færre end {{PLURAL:$2|$2 kald}}, lige nu er der {{PLURAL:$1|$1 kald}}.",
        "search-interwiki-caption": "Søsterprojekter",
        "search-interwiki-default": "Resultater fra $1:",
        "search-interwiki-more": "(mere)",
+       "search-interwiki-more-results": "flere resultater",
        "search-relatedarticle": "Relateret",
        "searchrelated": "relateret",
        "searchall": "alle",
        "youremail": "Din e-mailadresse:",
        "username": "{{GENDER:$1|Brugernavn}}:",
        "prefs-memberingroups": "{{GENDER:$2|Medlem}} af {{PLURAL:$1|gruppen|grupperne}}:",
+       "group-membership-link-with-expiry": "$1 (indtil $2)",
        "prefs-registration": "Registreringstidspunkt:",
        "yourrealname": "Dit rigtige navn:",
        "yourlanguage": "Sprog:",
        "userrights-user-editname": "Skriv et brugernavn:",
        "editusergroup": "Indlæs brugergrupper",
        "editinguser": "Ændrer brugerrettigheder for {{GENDER:$1|brugeren}} <strong>[[User:$1|$1]]</strong> $2",
-       "userrights-editusergroup": "Redigér brugergrupper",
+       "userrights-editusergroup": "Redigér {{GENDER:$1|brugergrupper}}",
        "saveusergroups": "Gem {{GENDER:$1|brugergrupper}}",
        "userrights-groupsmember": "Medlem af:",
        "userrights-groupsmember-auto": "Implicit medlem af:",
        "userrights-nodatabase": "Databasen $1 eksisterer ikke lokalt.",
        "userrights-changeable-col": "Redigerbare grupper",
        "userrights-unchangeable-col": "Uredigerbare grupper",
+       "userrights-expiry-current": "Udløber $1",
+       "userrights-expiry-none": "Udløber ikke",
        "userrights-conflict": "Konflikt i ændringer af brugerrettigheder!\nVær venlig at gennemse og bekræft dine ændringer.",
        "group": "Gruppe:",
        "group-user": "Brugere",
        "booksources-search": "Søg",
        "booksources-text": "Dette er en liste med henvisninger til Internetsider, som sælger nye og brugte bøger. Der kan der også findes yderligere informationer om bøgerne. {{SITENAME}} er ikke forbundet med nogen af dem.",
        "booksources-invalid-isbn": "Det angivne ISBN-nummer ser forkert ud. Tjek med kilden om det er skrevet korrekt.",
+       "magiclink-tracking-rfc": "Sider, der bruger automatiske RFC-henvisninger‎",
+       "magiclink-tracking-pmid": "Sider, der bruger automatiske PMID-henvisninger‎",
        "magiclink-tracking-isbn": "Sider, der bruger automatiske ISBN-henvisninger",
        "specialloguserlabel": "Udført af:",
        "speciallogtitlelabel": "Mål (titel eller {{ns:user}}:brugernavn for bruger):",
        "exif-compression-6": "JPEG (gammel)",
        "exif-copyrighted-true": "Ophavsretligt beskyttet",
        "exif-copyrighted-false": "Status for ophavsret er ikke angivet",
+       "exif-photometricinterpretation-1": "Sort-hvid (sort er 0)",
        "exif-unknowndate": "Ukendt dato",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Horisontalt spejlet",
        "logentry-upload-revert": "$1 {{GENDER:$2|lagde}} $3 op",
        "rightsnone": "(-)",
        "revdelete-summary": "redigeringsbeskrivelse",
+       "rightslogentry-temporary-group": "$1 (midlertidig, indtil $2)",
        "feedback-adding": "Tilføjer kommentar til side...",
        "feedback-back": "Tilbage",
        "feedback-bugcheck": "Skønt! Men tjek venligst, at det ikke er en af de [$1 kendte fejl].",
index b96f8be..ea83241 100644 (file)
        "permissionserrorstext-withaction": "Du bist aus {{PLURAL:$1|dem folgenden Grund|den folgenden Gründen}} nicht berechtigt, $2:",
        "contentmodelediterror": "Du kannst diese Version nicht bearbeiten, da das Inhaltsmodell <code>$1</code> vom aktuellen Inhaltsmodell der Seite <code>$2</code> abweicht.",
        "recreate-moveddeleted-warn": "<strong>Achtung: Du erstellst eine Seite, die bereits früher gelöscht wurde.</strong>\n\nBitte prüfe sorgfältig, ob die erneute Seitenerstellung den Richtlinien entspricht.\nZu deiner Information folgt das Lösch- und Verschiebungs-Logbuch mit der Begründung für die vorhergehende Löschung:",
-       "moveddeleted-notice": "Diese Seite wurde gelöscht. Zur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
-       "moveddeleted-notice-recent": "Leider wurde diese Seite kürzlich gelöscht (innerhalb der letzten 24 Stunden).\nZur Information wird das Lösch- und Verschiebungs-Logbuch für die Seite unten angezeigt.",
+       "moveddeleted-notice": "Diese Seite wurde gelöscht.\nZur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
+       "moveddeleted-notice-recent": "Diese Seite wurde kürzlich gelöscht (innerhalb der letzten 24 Stunden).\nZur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
        "log-fulllog": "Alle Logbucheinträge ansehen",
        "edit-hook-aborted": "Die Bearbeitung wurde ohne Erklärung durch eine Schnittstelle abgebrochen.",
        "edit-gone-missing": "Die Seite konnte nicht aktualisiert werden.\nSie wurde anscheinend gelöscht.",
index 2b6ff4c..733f3f7 100644 (file)
        "missingsummary": "'''DİQET:''' Şıma jû xulasa nênuşte.\nEke şıma \"{{int:savearticle}}\" reyna bıtıknê, vırnayışê şıma bê xulasa qeyd beno.",
        "missingcommenttext": "Cêr de jû fıkır bınusên, şıma rê zehmet.",
        "missingcommentheader": "'''Diqet:''' Şıma seba nê fıkrvaci yew mewzu/sernuşte nênuşt.\nEke şıma reyna \"{{int:savearticle}}\" bıtıknê, vırnayışê şıa bê mewzu/sernuşte do qeyd bo.",
-       "summary-preview": "Verqaytê xulasa:",
+       "summary-preview": "Verasayışê xulasa:",
        "subject-preview": "Verqaytê mewzu:",
        "previewerrortext": "Verasayışê vırnayışê şıma de yew xeta veciya miyan.",
        "blockedtitle": "Karber blokekerdeo",
index 3d6e462..4632b32 100644 (file)
        "deleting-backlinks-warning": "<strong>Προσοχή:</strong>  [[Special:WhatLinksHere/{{FULLPAGENAME}}|Άλλες σελίδες]] συνδέουν ή ενσωματώνουν τη σελίδα που πρόκειται να διαγράψετε.",
        "rollback": "Επαναφορά επεξεργασιών",
        "rollbacklink": "αναστροφή",
-       "rollbacklinkcount": "Î\95Ï\80αναÏ\86οÏ\81ά $1 {{PLURAL:$1|επεξεργασίας|επεξεργασιών}}",
-       "rollbacklinkcount-morethan": "εÏ\80αναÏ\86οÏ\81ά περισσότερων από $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}",
+       "rollbacklinkcount": "Î\91ναÏ\83Ï\84Ï\81οÏ\86ή $1 {{PLURAL:$1|επεξεργασίας|επεξεργασιών}}",
+       "rollbacklinkcount-morethan": "αναÏ\83Ï\84Ï\81οÏ\86ή περισσότερων από $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}",
        "rollbackfailed": "Η επαναφορά απέτυχε.",
        "cantrollback": "Δεν είναι δυνατή η αναίρεση αυτής της αλλαγής, πρόκειται για την αρχική ενέργεια δημιουργίας της σελίδας.",
        "alreadyrolled": "Αδύνατον να αναιρεθεί η τελευταία αλλαγή της σελίδας [[:$1]] από το χρήστη ([[User:$2|$2]] ([[User talk:$2|Συζήτηση]]){{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]), διότι κάποιος έχει ήδη αναιρέσει την αλλαγή ή έχει αλλάξει εκ νέου τη σελίδα.\n\nΤελευταία αλλαγή από το χρήστη ([[User:$3|$3]] ([[User talk:$3|Συζήτηση]]){{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
index 53eceed..8de97e9 100644 (file)
        "editcomment": "The edit summary was: <em>$1</em>.",
        "revertpage": "Reverted edits by [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) to last revision by [[User:$1|$1]]",
        "revertpage-nouser": "Reverted edits by a hidden user to last revision by {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Reverted edits by $1;\nchanged back to last revision by $2.",
+       "rollback-success": "Reverted edits by {{GENDER:$3|$1}};\nchanged back to last revision by {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Reverted edits by $1;\nchanged back to last revision by $2. [$3 Show changes]",
        "sessionfailure-title": "Session failure",
        "sessionfailure": "There seems to be a problem with your login session;\nthis action has been canceled as a precaution against session hijacking.\nGo back to the previous page, reload that page and then try again.",
index 824ec6f..eb89f59 100644 (file)
        "createacct-email-ph": "Sisesta e-posti aadress",
        "createacct-another-email-ph": "Sisesta e-posti aadress",
        "createaccountmail": "Kasuta juhuslikku parooli ja saada see määratud e-posti aadressile",
+       "createaccountmail-help": "Saab kasutada konto loomiseks teisele kasutajale ilma parooli teada saamata.",
        "createacct-realname": "Pärisnimi (valikuline)",
        "createaccountreason": "Põhjus:",
        "createacct-reason": "Põhjus",
        "createacct-reason-ph": "Miks lood teist kontot?",
+       "createacct-reason-help": "Sõnum, mida näidatakse konto loomise logis",
        "createacct-submit": "Loo konto",
        "createacct-another-submit": "Loo konto",
+       "createacct-continue-submit": "Jätka konto loomist",
+       "createacct-another-continue-submit": "Jätka konto loomist",
        "createacct-benefit-heading": "{{SITENAME}} on sinusuguste inimeste tehtud.",
        "createacct-benefit-body1": "{{PLURAL:$1|muudatus|muudatust}}",
        "createacct-benefit-body2": "{{PLURAL:$1|lehekülg|lehekülge}}",
        "nocookiesnew": "Kasutajakonto loodi, aga sa ei ole sisse logitud, sest {{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja logi siis oma vastse kasutajanime ning parooliga sisse.",
        "nocookieslogin": "{{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja proovi siis uuesti.",
        "nocookiesfornew": "Kasutajakonto jäi loomata, kuna me ei saanud selle allikat kindlaks teha.\nVeendu, et sul on küpsised lubatud, taaslaadi see lehekülg ja proovi uuesti.",
+       "createacct-loginerror": "Konto on edukalt loodud, aga automaatselt ei õnnestunud sisse logida. Et jätkata, [[Special:UserLogin|logi palun sisse käsitsi]].",
        "noname": "Sa ei sisestanud kasutajanime lubataval kujul.",
        "loginsuccesstitle": "Sisse logitud",
        "loginsuccess": "Oled sisse loginud. Sinu kasutajanimi on \"$1\".",
        "missingcommenttext": "Palun sisesta siit allapoole kommentaar.",
        "missingcommentheader": "<strong>Meeldetuletus:</strong> Sa pole kirjutanud kommentaarile teemat.\nKui klõpsad uuesti \"{{int:savearticle}}\", salvestatakse su kommentaar ilma teemata.",
        "summary-preview": "Resümee eelvaade:",
-       "subject-preview": "Alaosa pealkirja eelvaade:",
+       "subject-preview": "Resümee eelvaade:",
        "previewerrortext": "Sinu muudatuste eelvaatluse juures esines tõrge.",
        "blockedtitle": "Kasutaja on blokeeritud",
        "blockedtext": "'''Sinu kasutajanimi või IP-aadress on blokeeritud.'''\n\nBlokeeris $1.\nTema põhjendus on järgmine: ''$2''.\n\n* Blokeeringu algus: $8\n* Blokeeringu lõpp: $6\n* Sooviti blokeerida: $7\n\nKüsimuse arutamiseks võid pöörduda kasutaja $1 või mõne teise [[{{MediaWiki:Grouppage-sysop}}|administraatori]] poole.\n\nPane tähele, et sa ei saa kasutajale teadet saata, kui sa pole kinnitanud oma [[Special:Preferences|eelistuste lehel]] kehtivat e-posti aadressi.\n\nSinu praegune IP-aadress on $3 ning blokeeringu number on #$5. Lisa need andmed kõigile järelepärimistele, mida kavatsed teha.",
index c5b45d9..1e72167 100644 (file)
        "search-file-match": "(vastaa tiedoston sisältöä)",
        "search-suggest": "Tarkoititko: $1",
        "search-rewritten": "Näytetään tulokset haulla $1. Haluatko hakea haulla $2?",
-       "search-interwiki-caption": "Sisarprojektit",
+       "search-interwiki-caption": "Sisarhankkeet",
        "search-interwiki-default": "Tulokset osoitteesta $1:",
        "search-interwiki-more": "(lisää)",
        "search-interwiki-more-results": "lisää tuloksia",
        "rcfilters-filterlist-title": "Suodattimet",
        "rcfilters-filterlist-noresults": "Ei löytynyt suodattimia",
        "rcfilters-filter-registered-label": "Rekisteröitynyt",
+       "rcfilters-filter-registered-description": "Kirjautuneet muokkaukset.",
+       "rcfilters-filter-unregistered-description": "Muokkaajat, jotka eivät ole kirjautuneet sisään.",
        "rcfilters-filter-editsbyself-label": "Omat muokkauksesi",
        "rcfilters-filter-editsbyself-description": "Muokkauksesi",
        "rcfilters-filter-editsbyother-label": "Muiden muokkaukset",
        "rcfilters-filter-bots-label": "Botti",
        "rcfilters-filter-bots-description": "Muokkaukset jotka tehty automaattisilla työkaluilla.",
        "rcfilters-filter-humans-label": "Ihminen (ei botti)",
+       "rcfilters-filtergroup-significance": "Merkitys",
        "rcfilters-filter-minor-label": "Pienet muutokset",
        "rcfilters-filter-major-label": "Ei-pienet muutokset",
        "rcfilters-filter-major-description": "Muokkauksia ei ole merkitty kuin pieniksi.",
index 6b10aa7..cd7d2cc 100644 (file)
        "selfredirect": "<strong>Atención:</strong> Está redirixindo esta páxina a si mesma.\nQuizais especificou incorrectamente a páxina de destino ou poida que estea a editar unha páxina errónea.\nSe preme en \"{{int:savearticle}}\" de novo, crearase a redireción de calquera xeito.",
        "missingcommenttext": "Por favor, escriba un comentario a continuación.",
        "missingcommentheader": "<strong>Aviso:</strong> Non escribiu ningún texto no asunto deste comentario.\nSe preme en \"{{int:savearticle}}\" de novo, a súa edición gardarase sen el.",
-       "summary-preview": "Vista previa do resumo:",
+       "summary-preview": "Vista previa do resumo de edición:",
        "subject-preview": "Vista previa do asunto:",
        "previewerrortext": "Produciuse un erro ao intentar previsualizar os cambios.",
        "blockedtitle": "O usuario está bloqueado",
        "saveusergroups": "Gardar os grupos {{GENDER:$1|do usuario|da usuaria}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implícito de:",
-       "userrights-groups-help": "Pode cambiar os grupos aos que {{GENDER:$1|o usuario|a usuaria}} pertence:\n* Se a caixa ten un sinal (✓) significa que {{GENDER:$1|o usuario|a usuaria}} pertence a ese grupo.\n* Se, pola contra, non o ten, significa que non pertence.\n* Un asterisco (*) indica que non pode eliminar o grupo unha vez que o engadiu, e viceversa.",
+       "userrights-groups-help": "Pode cambiar os grupos aos que {{GENDER:$1|o usuario|a usuaria}} pertence:\n* Se a caixa ten un sinal (✓) significa que {{GENDER:$1|o usuario|a usuaria}} pertence a ese grupo.\n* Se, pola contra, non o ten, significa que non pertence.\n* Un asterisco (*) indica que non pode eliminar o grupo unha vez que o engadiu, e viceversa.\n* Un # indica que só se pode atrasar a data de caducidade deste grupo; non se pode adiantar.",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Non ten os permisos necesarios para editar os dereitos de usuario noutros wikis.",
        "userrights-nodatabase": "A base de datos \"$1\" non existe ou non é local.",
        "userrights-expiry-options": "1 día:1 día,1 semana:1 semana,1 mes:1 mes,3 meses:3 meses,6 meses:6 meses,1 ano:1 ano",
        "userrights-invalid-expiry": "O tempo de caducidade para o grupo \"$1\" non é válido.",
        "userrights-expiry-in-past": "O tempo de caducidade para o grupo \"$1\" está no pasado.",
+       "userrights-cannot-shorten-expiry": "Non pode adiantar a data de caducidade do grupo \"$1\". Só os usuarios con permisos para engadir e eliminar este grupo poden adiantar datas de caducidade.",
        "userrights-conflict": "Hai un conflito na modificación dos dereitos de usuario! Por favor, revíseo e confirme os seus cambios.",
        "group": "Grupo:",
        "group-user": "Usuarios",
index bd0a5fb..52ff8e6 100644 (file)
        "listgrouprights-key": "범례:\n* <span class=\"listgrouprights-granted\">부여된 권한</span>\n* <span class=\"listgrouprights-revoked\">해제된 권한</span>",
        "listgrouprights-group": "그룹",
        "listgrouprights-rights": "권한",
-       "listgrouprights-helppage": "위키백과:사용자 권한",
+       "listgrouprights-helppage": "Help:사용자 권한",
        "listgrouprights-members": "(사용자 목록)",
        "listgrouprights-addgroup": "{{PLURAL:$2|권한}} 부여: $1",
        "listgrouprights-removegroup": "{{PLURAL:$2|권한}} 회수: $1",
index e075af2..c85e767 100644 (file)
@@ -26,6 +26,7 @@
        "tog-watchdefault": "Hanaraka ny pejy ary ny rakitra ovaiko",
        "tog-watchmoves": "Hanaraka ny pejy ary ny rakitra ovaiko anarana",
        "tog-watchdeletion": "Hanaraka ny pejy ary ny rakitra voafafako",
+       "tog-watchuploads": "Ampiana amin'ny pejy arahako ireo rakitra vaovao nalefako",
        "tog-watchrollback": "Hanaraka pejy nanaovako famoana",
        "tog-minordefault": "Mariho ho madinika foana aloha ny fanovana rehetra",
        "tog-previewontop": "Asehoy alohan'ny boaty fanovana ny tsipalotra",
        "tagline": "Avy amin'i {{SITENAME}}",
        "help": "Fanoroana",
        "search": "Tadiavo",
+       "search-ignored-headings": "#<!-- Avelao ho toa izao ity andalana ity --> <pre>\n# Ny lohatenim-pizarana dia tsy horaharahiana amin'ny karoka.\n# Ny fiovana atao eto dia hihatra rehefa voasoratra ao amin'ny tondro ilay pejy miaraka amin'ilay lohateny.\n# Azonao atao ny famerenana an-tondro an'ilay pejy amin'ny alalan'ny fanovana tsy misy inona inona.\n# Ny rariteny dia ireo manaraka:\n# *Izay andalana rehetra manomboka amin'ny \"#\" dia resaka\n# *Izay andalana tsy fotsy dia lohateny tsy horaharahiana, iaraka amin'ny haben-tsoratra\nTsiahy\nRohy ivelany\nJereo koa\n#</pre> <!-- Avelao ho toa izao ity andalana ity -->",
        "searchbutton": "Tadiavo",
        "go": "Ndao",
        "searcharticle": "Tsidiho",
        "passwordreset-emailtext-user": "Nisy mpikambana mitondra anarana $1 eo amin'i {{SITENAME}} nangataka fampatsiahivana mikasika ny kaontinao eo amin'i {{SITENAME}} ($4). Manana io adiresy imailaka {{PLURAL:$3|io kaontim-pikambana io|ireo kaontim-pikambana ireo}} :\n\n$2\n\nHitsahatra afaka {{PLURAL:$5|iray|$5}} andro {{PLURAL:$3|io|ireo}} tenimiafina {{PLURAL:$3|io|ireo}}. Mila miditra dien'izao ianao izao ary mifidy tenimiafina vaovao. Raha tsy avy aminao ity hataka ity na efa nahatadidy ny tenimiafinao taloha ianao, ary raha tsy tianao hovaina intsony ilay tenimiafinao, dia azonao tsy raharahiana ity hafatra ity ary mampiasa ny tenimiafinao taloha.",
        "passwordreset-emailelement": "Anaram-pikambana : \n$1\n\nTenimiafina miserana : \n$2",
        "passwordreset-emailsentemail": "Lasa ny mailaka famerenana tenimiafina.",
+       "passwordreset-nocaller": "Mila manitsy mpiantso",
+       "passwordreset-nosuchcaller": "Tsy misy ilay mpiantso: $1",
        "changeemail": "Hanova ny adiresy imailaka",
        "changeemail-header": "Hanova ny adiresy imailak'ilay kaonty",
        "changeemail-no-info": "Mila tafiditra ianao vao avaka mijery ity pejy ity.",
        "yourdiff": "Fampitahana",
        "copyrightwarning": "Ny zavatra rehetra apetraka amin'ny {{SITENAME}} dia raisina ho azo adika malalaka araka ny fahazoan-dalana $2 (Jereo $1 ny fanazavana fanampiny). Raha toa ka tianao ho anao manokana ny tahirin-kevitra dia aleo tsy apetraka ato.\n\n<b>AZA MAMPIASA TAHIRINKEVITRA TSY NAHAZOAN-DALANA</b>",
        "copyrightwarning2": "Ny fandraisana anjara ao amin'i {{SITENAME}} dia azo ovaina ary fafan'ny mpikambana hafa. Raha tsy tianao ho ampiasainan, ovaina na zarazaraina ny soratrao, dia aza alefa eto ilay vokatr'asanao<br />\nNy zava-tsoratanao eto dia vokatr'asa naverinao soratana na nodikainao tany amina loharano ao amin'ny vala sarababem-bahoaka na loharano malalaka hafa (Jereo $1 ho an'ny antsipirihany).\n\n'''Aza mampiasa tahirin-kevitra tsy nahazoan-dalana!'''",
+       "editpage-cannot-use-custom-model": "Tsy mety ovaina ny modelim-botoatin'ity pejy ity.",
        "longpageerror": "'''Hadisoana : Ny tahirin-tsoratra nalefanao dia manana halava {{PLURAL:$1|iray|$1}} kilooktety, izay lava kokoa nohon'ny fetra avo indridra izay natao ho {{PLURAL:$2|iray|$2}} kilooktety.'''\nTsy afaka tahirizina ilay tahirin-tsoratra.",
        "readonlywarning": "'''FAMPITANDREMANA: Nohidiana noho ny antony fikolokoloana aloha ny banky angona,\nkoa tsy afaka mitahiry ny fanovana nataonao aloha ianao izao. Angamba tokony hanao Couper coller aloha\nianao dia tehirizo anaty rakitra ny fanovanao mandra-paha.'''\n\nNy mpandrindra nanidy ny banky angona dia nanome ny antony : <br />$1",
        "protectedpagewarning": "'''FAMPITANDREMANA:  Voaaro ity pejy ity ka ny mpikambana manana ny fahazoan-dàlana sysop ihany no afaka manova azy.'''",
        "invalid-content-data": "Data anaty votoatiny tsy miady amin'ny fepetra",
        "content-not-allowed-here": "Votoatiny ''$1'' voarara eo amin'ny pejy [[$2]]",
        "editwarning-warning": "Mety hahavery ny fanovana nataonao ny fialanao amin'ity pejy ity.\nRaha tafiditra ianao dia azonao esorina ity fampitandremana ity ao amin'ny fizarana \"{{int:prefs-editing}}\" ao amin'ny safidinao.",
+       "editpage-invalidcontentmodel-title": "Andrefim-botoatiny tsy zaka",
+       "editpage-invalidcontentmodel-text": "Andrefim-botoatiny \"$1\" tsy zaka.",
        "editpage-notsupportedcontentformat-title": "Tsy zaka io andrefim-botoatiny io",
        "editpage-notsupportedcontentformat-text": "Tsy zakan'ny maodelim-botoatiny $1 ny firafi-botoatiny $1",
        "content-model-wikitext": "wiki-soratra",
        "content-model-css": "CSS",
        "content-json-empty-object": "Zavatra foana",
        "content-json-empty-array": "Tabilao foana",
+       "deprecated-self-close-category": "Pejy mampiasa balizy HTML mihidy ho azy izay tsy azo raisina",
        "duplicate-args-category": "Pejy mampiasa dika mitovy hevitra amin'ny fiantsoana endrika",
        "expensive-parserfunction-warning": "Tandremo : Betsaka loatra ny fanantsoana ny tao parser.\n\nTsy maintsy latsaky ny $2 ny tao, kanefa misy $1. {{PLURAL:$2||}}",
        "expensive-parserfunction-category": "Pejy mampiasa be loatra ny tao parser",
        "search-interwiki-caption": "zandri-tetikasa",
        "search-interwiki-default": "Valiny amin'ny $1 :",
        "search-interwiki-more": "(be kokoa)",
+       "search-interwiki-more-results": "Valiny be kokoa",
        "search-relatedarticle": "voadinika",
        "searchrelated": "voadinika",
        "searchall": "rehetra",
        "youremail": "Imailaka:",
        "username": "{{GENDER:$1}}Anaram-pikambana :",
        "prefs-memberingroups": "Mpikambana{{GENDER:$2}} ao amin'ny vondrona{{PLURAL:$1}}:",
+       "group-membership-link-with-expiry": "$1 (hatramin'i $2)",
        "prefs-registration": "Daty fidirana :",
        "yourrealname": "Tena anarana marina:",
        "yourlanguage": "Tenim-pirenena:",
        "prefswarning-warning": "Efa nanova tamin'ny safidinao tsy mbola voatahiry ianao. Raha miala amin'ity pejy ity amin'ny alalan'ny fanindriana an'i \"$1\" ianao dia tsy ho voavao ny safidinao.",
        "prefs-tabs-navigation-hint": "Torohevitra: afaka mampiasa ny zana-tsipika havia ary havanana ianao ho an'ny fitetezana ny vakizoro ao amin'ny lisi-bakizoro",
        "userrights": "Fandrindràna ny fahefahan'ny mpikambana",
-       "userrights-lookup-user": "Handrindra vondrom-pikambana",
+       "userrights-lookup-user": "Hisafidy mpikambana",
        "userrights-user-editname": "Manomeza solonanarana:",
-       "editusergroup": "Hanova satan'ny {{GENDER:$1|}}mpikambana",
+       "editusergroup": "Hampiditra vondrom-pikambana",
        "editinguser": "Fanovana ny zon'ny mpikambana <strong>{{GENDER:$1|}}[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Hanova vondrom-pikambana",
        "saveusergroups": "{{GENDER:$1|}}Tehirizo ny vondrom-pikambana",
        "userrights-changeable-col": "Ny gropy azonao ovaina",
        "userrights-unchangeable-col": "Ny gropy tsy azonao ovaina",
        "userrights-expiry-current": "Mitsahatra ny $1",
+       "userrights-expiry-none": "Tsy mitsahatra",
        "userrights-expiry": "Fitsaharana:",
+       "userrights-expiry-existing": "Fotoam-pitsaharana ankehitriny: $3, $2",
+       "userrights-expiry-othertime": "Fotoana hafa:",
+       "userrights-expiry-options": "1 andro:1 day,herinandro:1 week,1 volana:1 month,3 volana:3 months,6 volana:6 months,herintaona:1 year",
+       "userrights-invalid-expiry": "Tsy azo raisina ny fotoam-pitsaharana ho an'ny vondrona \"$1\".",
        "userrights-conflict": "Fifandonana fanovana zom-pikambana! Avereno vakiana ary marino ny fanovanao.",
        "group": "Gropy :",
        "group-user": "Mpikambana",
index 828a094..3cfbe34 100644 (file)
@@ -38,7 +38,7 @@
        "tog-watchdeletion": "Apondre las paginas e los fichièrs que suprimissi de ma lista de seguiment",
        "tog-watchuploads": "Apondre los novèls fichièrs qu’impòrti a ma lista de seguiment",
        "tog-watchrollback": "Apondre a ma lista de seguiment las paginas sus las qualas ai efectuat una revocacion",
-       "tog-minordefault": "Considerar mas modificacions coma menoras per defaut",
+       "tog-minordefault": "Considerar totas las modificacions coma menoras per defaut",
        "tog-previewontop": "Far veire la previsualizacion al dessús de la zòna de modificacion",
        "tog-previewonfirst": "Far veire la previsualizacion al moment de la primièra edicion",
        "tog-enotifwatchlistpages": "M’avertir per corrièr electronic quand una pagina o un fichièr de ma lista de seguiment es modificat",
        "oct": "d'oct",
        "nov": "de nov",
        "dec": "de dec",
-       "january-date": "$1 de genièr",
-       "february-date": "$1 de febrièr",
-       "march-date": "$1 de març",
+       "january-date": "{{PLURAL:$1|1=1èr|$1}} de genièr",
+       "february-date": "{{PLURAL:$1|1=1èr|$1}} de febrièr",
+       "march-date": "{{PLURAL:$1|1=1èr|$1}} de març",
        "april-date": "$1 d'abril",
        "may-date": "$1 de mai",
        "june-date": "$1 de junh",
        "september-date": "$1 de setembre",
        "october-date": "$1 d'octobre",
        "november-date": "$1 de novembre",
-       "december-date": "$1 de decembre",
+       "december-date": "{{PLURAL:$1|1=1èr|$1}} de decembre",
        "period-am": "AM",
        "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorias}}",
        "permissionserrorstext": "Avètz pas la permission d’efectuar l’operacion demandada per {{PLURAL:$1|la rason seguenta|las rasons seguentas}} :",
        "permissionserrorstext-withaction": "Sètz pas autorizat(ada) a $2, per {{PLURAL:$1|la rason seguenta|las rasons seguentas}} :",
        "recreate-moveddeleted-warn": "'''Atencion : sètz a tornar crear una pagina qu'es estada suprimida precedentament.'''\n\nDemandatz-vos s'es vertadièrament apropriat de contunhar de l’editar.\nL’istoric de las supressions e dels cambiaments de nom es afichat çaijós :",
-       "moveddeleted-notice": "Aquesta pagina es estat suprimida.\nL'istoric de las supressions e dels cambiaments de nom es afichat çaijós coma referéncia.",
+       "moveddeleted-notice": "Aquesta pagina es estada suprimida.\nL'istoric de las supressions e dels cambiaments de nom es afichat çaijós coma referéncia.",
        "log-fulllog": "Veire lo jornal complet",
        "edit-hook-aborted": "Modificacion fracassada per croquet.\nCap d'explicacion pas balhada.",
        "edit-gone-missing": "A pas pogut metre a jorn la pagina.\nSembla que siá estada suprimida.",
        "allpagesfrom": "Afichar las paginas a partir de :",
        "allpagesto": "Afichar las paginas fins a :",
        "allarticles": "Totas las paginas",
-       "allinnamespace": "Totas las paginas (espaci de noms $1)",
+       "allinnamespace": "Totas las paginas (dins l'espaci de noms $1)",
        "allpagessubmit": "Validar",
        "allpagesprefix": "Afichar las paginas que començan pel prefix :",
        "allpagesbadtitle": "Lo títol rensenhat per la pagina es incorrècte o possedís un prefix reservat. Conten segurament un o mantun caractèr especial que pòt pas èsser utilizats dins los títols.",
        "import-interwiki-sourcewiki": "Wiki font :",
        "import-interwiki-sourcepage": "Pagina font :",
        "import-interwiki-history": "Copiar totas las versions de l'istoric d'aquesta pagina",
-       "import-interwiki-templates": "Enclure totes los modèls",
+       "import-interwiki-templates": "Inclure totes los modèls",
        "import-interwiki-submit": "Importar",
        "import-mapping-default": "Importar als emplaçaments per defaut",
        "import-mapping-namespace": "Importar cap a un espaci de noms :",
        "spambot_username": "Netejatge de spam de MediaWiki",
        "spam_reverting": "Restabliment de la darrièra version que conten pas de ligam cap a $1",
        "spam_blanking": "Totas las versions que contenon de ligams cap a $1 son blanquidas",
-       "spam_deleting": "Totas las versions contenonián de ligams cap a $1, supression",
+       "spam_deleting": "Totas las versions contenián de ligams cap a $1, supression",
        "simpleantispam-label": "Verificacion antispam.\nInscriviscatz '''PAS RES''' dedins !",
        "pageinfo-title": "Informacions per « $1 »",
        "pageinfo-not-current": "O planhèm, impossible de provesir aquesta informacion per las ancianas revisions.",
index 21556cf..4898c19 100644 (file)
        "redirectedfrom": "(لیایا گیا $1)",
        "redirectpagesub": "صفحہ ریڈائریکٹ کرو",
        "redirectto": "اگے کرو:",
-       "lastmodifiedat": "اس صفحے نوں آخری آری $1 تریخ نوں $2 وجے بدلیا گیا۔",
+       "lastmodifiedat": "اس صفحے نوں آخری واری $1 تریخ نوں $2 وجے بدلیا گیا۔",
        "viewcount": "اس صفحے نوں {{PLURAL:$1|اک واری|$1 واری}} کھولیا گیا اے۔",
        "protectedpage": "بجایا صفحہ",
        "jumpto": "جاؤ:",
        "policy-url": "Project:پالیسی",
        "portal": "بیٹھک",
        "portal-url": "ویونت:بیٹھک",
-       "privacy": "پرائیویسی اصول",
-       "privacypage": "Project:پرائیویسی اصول",
+       "privacy": "پرائیویسی پالیسی",
+       "privacypage": "Project:پرائیویسی پالیسی",
        "badaccess": "اجازت دے وچ غلطی اے",
        "badaccess-group0": "تھاونوں ایس کم دی اجازت نیں جیہڑا تسیں آکھیا اے۔",
        "badaccess-groups": "جیڑا کم تسی کرنا چا رۓ او اوہ صرف {{PLURAL:$2|اس گروپ|ایناں گروپاں}} دے ورتن آلے کر سکدے نیں: $1۔",
        "whatlinkshere-prev": "{{PLURAL:$1|پچھلا $1ا|پچھلا}}",
        "whatlinkshere-next": "{{PLURAL:$1|اگلا $1|اگلا}}",
        "whatlinkshere-links": "← جوڑ",
-       "whatlinkshere-hideredirs": "$1 ریڈائریکٹس",
+       "whatlinkshere-hideredirs": "$1 ریڈائریکٹ",
        "whatlinkshere-hidetrans": "$1 ٹرانسکلوژن",
        "whatlinkshere-hidelinks": "$1 جوڑ",
        "whatlinkshere-hideimages": "$1 مورت جوڑ",
index a789eb5..0ed8589 100644 (file)
        "selfredirect": "<strong>Aviso:</strong> Está a redirecionar esta página para si mesma.\nPode ter especificado o destino errado para a página ou até a editar a página errada.\nSe clicar em \"{{int:savearticle}}\" novamente, o redirecionamento será criado na mesma.",
        "missingcommenttext": "Introduza um comentário abaixo, por favor.",
        "missingcommentheader": "<strong>Atenção:</strong> Não introduziu um assunto para este comentário.\nSe clicar novamente \"{{int:savearticle}}\", a sua edição será gravada sem assunto.",
-       "summary-preview": "Antevisão do resumo:",
+       "summary-preview": "Antevisão do resumo de edição:",
        "subject-preview": "Antevisão do assunto:",
        "previewerrortext": "Ocorreu um erro enquanto tentava antever as suas alterações.",
        "blockedtitle": "O utilizador está bloqueado",
index 2e02447..6ffc851 100644 (file)
        "permissionserrorstext-withaction": "This message is \"with action\" version of {{msg-mw|Permissionserrorstext}}.\n\nParameters:\n* $1 - the number of reasons that were found why the action cannot be performed\n* $2 - one of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.",
        "contentmodelediterror": "Error message shown when trying to edit an old revision with a content model different from that of the current revision\n* $1 - content model of the old revision\n* $2 - content model of the current revision",
        "recreate-moveddeleted-warn": "Warning shown when creating a page which has already been deleted. See for example [[Test]].",
-       "moveddeleted-notice": "Shown on top of a deleted page in normal view modus ([{{canonicalurl:Test}} example]).",
-       "moveddeleted-notice-recent": "Shown on top of a recently deleted page in normal view modus ([{{canonicalurl:Test}} example]).",
+       "moveddeleted-notice": "Shown on top of a deleted page in normal view modus ([{{canonicalurl:Test}} example]).\n\nSee also {{msg-mw|moveddeleted-notice-recent}}",
+       "moveddeleted-notice-recent": "Shown on top of a recently deleted page in normal view modus ([{{canonicalurl:Test}} example]).\n\nSee also {{msg-mw|moveddeleted-notice}}",
        "log-fulllog": "Used as link text.",
        "edit-hook-aborted": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}\n* {{msg-mw|edit-already-exists}}",
        "edit-gone-missing": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}\n* {{msg-mw|edit-already-exists}}",
        "booksources-text": "Used in [[Special:BookSources/1]].\n\nThis message is followed by a list of links to other sites.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
        "booksources-invalid-isbn": "This message is displayed after an invalid ISBN is entered on [[Special:Booksources]].",
        "magiclink-tracking-rfc": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use RFC magic links will be added.\n\nSee [https://en.wikipedia.org/wiki/Help:Magic_links#RFC Help:Magic links] for more information on RFC magic links.",
-       "magiclink-tracking-rfc-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-rfc}}",
+       "magiclink-tracking-rfc-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-rfc}}",
        "magiclink-tracking-pmid": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use PMID magic links will be added.",
-       "magiclink-tracking-pmid-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-pmid}}",
+       "magiclink-tracking-pmid-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-pmid}}",
        "magiclink-tracking-isbn": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use ISBN magic links will be added.",
-       "magiclink-tracking-isbn-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-isbn}}",
+       "magiclink-tracking-isbn-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-isbn}}",
        "rfcurl": "{{notranslate}}\nParameters:\n* $1 - RFC number\nSee also:\n* {{msg-mw|Pubmedurl}}",
        "pubmedurl": "{{notranslate}}\nParameters:\n* $1 - Pubmed number\nSee also:\n* {{msg-mw|Rfcurl}}",
        "specialloguserlabel": "Used in [[Special:Log]] as a label for an input field with which the log can be filtered for entries describing actions ''performed'' by the specified user.  \"Carried out\" and \"done\" are possible alternatives for \"performed\".",
        "editcomment": "Only shown if there is an edit {{msg-mw|Summary}}. Parameters:\n* $1 - the edit summary",
        "revertpage": "Parameters:\n* $1 - username 1\n* $2 - username 2\n* $3 - (Optional) revision ID of the revision reverted to\n* $4 - (Optional) timestamp of the revision reverted to\n* $5 - (Optional) revision ID of the revision reverted from\n* $6 - (Optional) timestamp of the revision reverted from\nSee also:\n* {{msg-mw|Revertpage-nouser}}\n{{Identical|Revert}}",
        "revertpage-nouser": "This is a confirmation message a user sees after reverting, when the username of the version is hidden with RevisionDelete.\n\nIn other cases the message {{msg-mw|Revertpage}} is used.\n\nParameters:\n* $1 - username 1, can be used for GENDER\n* $2 - (Optional) username 2\n* $3 - (Optional) revision ID of the revision reverted to\n* $4 - (Optional) timestamp of the revision reverted to\n* $5 - (Optional) revision ID of the revision reverted from\n* $6 - (Optional) timestamp of the revision reverted from",
-       "rollback-success": "This message shows up on screen after successful revert (generally visible only to admins). $1 describes user whose changes have been reverted, $2 describes user which produced version, which replaces reverted version.\n{{Identical|Revert}}\n{{Identical|Rollback}}",
+       "rollback-success": "This message shows up on screen after successful revert (generally visible only to admins). Parameters:\n* $1 - user whose changes have been reverted\n* $2 - user who produced version, which replaces reverted version\n* $3 - the first user's name, can be used for GENDER\n* $4 - the second user's name, can be used for GENDER\n{{Identical|Revert}}\n{{Identical|Rollback}}",
        "rollback-success-notify": "Notification shown after a successful revert.\n* $1 - User whose changes have been reverted\n* $2 - User that made the edit that was restored\n* $3 - Url to the diff of the rollback\nSee also:\n* {{msg-mw|showdiff}}\n{{related|rollback-success}}\n{{Format|jquerymsg}}",
        "sessionfailure-title": "Used as title of the error message {{msg-mw|Sessionfailure}}.",
        "sessionfailure": "Used as error message.\n\nThe title for this error message is {{msg-mw|Sessionfailure-title}}.",
index 104c497..f244230 100644 (file)
        "uploaddisabledtext": "கோப்பு பதிவேற்றங்கள் செயலிழக்கச் செய்யப்பட்டுள்ளன.",
        "php-uploaddisabledtext": "கோப்பு தரவேற்றம் PHP இல் முடக்கப்பட்டுள்ளது.தயவுகூர்ந்து file_uploads அமைப்பை சரிபார்க்கவும்.",
        "uploadscripted": "இந்தக் கோப்பு உலாவியால் பிழையாக விளங்கிக் கொள்ளக்கூடிய எச்.டி.எம்.எல். அல்லது வேறு நிரல்களைக் கொண்டுள்ளது.",
-       "uploadscriptednamespace": "இந்த SVG கோப்பு ஒரு சரியில்லாத பெயரிடைவெளியை \"<nowiki>$1</nowiki>\" கொண்டுள்ளது.",
+       "uploadscriptednamespace": "இந்த SVG கோப்பு ஒரு சரியில்லாத பெயரிடைவெளியை கொண்டுள்ளது \"<nowiki>$1</nowiki>\".",
        "uploadinvalidxml": "ஏற்றபட்ட கோப்பில் உள்ள XML ஆராய முடியாது.",
        "uploadvirus": "கோப்பு நச்சுநிரலைக் (வைரஸ்) கொண்டுள்ளது! விபரங்கள்:$1",
        "uploadjava": "இது ஒரு zip கோப்பு.இதில் java.class என்ற கோப்பு உள்ளது.\nஜாவா கோப்புகளை தகவலேற்றுவது தடைசெய்யப்பட்டுள்ளது.ஏனெனில் அது பாதுகாப்பு தடைகளை மீற வழிவகுக்கும்.",
index 32773e3..85ef77a 100644 (file)
        "period-am": "AM",
        "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|分类}}",
-       "category_header": "å\88\86ç±»â\80\9c$1â\80\9d中的页面",
+       "category_header": "å\88\86ç±»â\80\9c$1â\80\9dä¸\8b的页面",
        "subcategories": "子分类",
        "category-media-header": "分类“$1”中的媒体文件",
        "category-empty": "<em>本分类目前不含有任何页面或媒体文件。</em>",
        "randompage-nopages": "在以下{{PLURAL:$2|名字空间}}中没有页面:$1。",
        "randomincategory": "分类中随机页面",
        "randomincategory-invalidcategory": "“$1”不是一个有效的分类名称。",
-       "randomincategory-nopages": "[[:Category:$1|$1]]å\88\86类中没有页面。",
+       "randomincategory-nopages": "[[:Category:$1|$1]]å\88\86ç±»ä¸\8b没有页面。",
        "randomincategory-category": "分类:",
        "randomincategory-legend": "分类中随机页面",
        "randomincategory-submit": "提交",
        "ancientpages": "最老页面",
        "move": "移动",
        "movethispage": "移动本页",
-       "unusedimagestext": "以下文件实际存在,但并没有插入任何页面。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。",
+       "unusedimagestext": "存在以下没有插入任何页面的文件。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。",
        "unusedcategoriestext": "以下分类页面实际存在,即使没有其它页面或分类利用它们。",
        "notargettitle": "无目标",
        "notargettext": "您还没有指定一个目标页面或用户以进行此项操作。",
        "siteuser": "{{SITENAME}}用户$1",
        "anonuser": "{{SITENAME}}匿名用户$1",
        "lastmodifiedatby": "本页面被$3最后修改于$1 $2。",
-       "othercontribs": "å\9fºäº\8e$1ç\9a\84å·¥ä½\9cã\80\82",
+       "othercontribs": "å\9fºäº\8e$1ç\9a\84å\8a³å\8a¨æ\88\90æ\9e\9cã\80\82",
        "others": "其他",
        "siteusers": "{{SITENAME}}{{PLURAL:$2|{{GENDER:$1|用户}}}}$1",
        "anonusers": "{{SITENAME}}匿名{{PLURAL:$2|用户}}$1",
        "variantname-gan-hant": "hant",
        "variantname-kk-cyrl": "kk-cyrl",
        "metadata": "元数据",
-       "metadata-help": "此文件中包含有扩展的信息。这些信息可能是由数码相机或扫描仪在创建或数字化过程中所添加的。\n\n如果此文件的源文件已经被修改,一些信息在修改后的文件中将不能完全反映出来。",
+       "metadata-help": "此文件中包含有额外的信息。这些信息可能是由数码相机或扫描仪在创建或数字化过程中所添加的。如果已自文件的初始状态修改,一些详细说明可能无法反映修改后的文件。",
        "metadata-expand": "显示详细资料",
        "metadata-collapse": "隐藏详细资料",
        "metadata-fields": "在本信息中所列出的 EXIF 元数据域将包含在图片显示页面,当元数据表损坏时只显示以下信息。\n其他的元数据默认为隐藏。\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
index 9044e45..2896d34 100644 (file)
        "variantname-gan-hans": "‪中文(简体)",
        "variantname-gan-hant": "‪中文(繁體)",
        "metadata": "詮釋資料",
-       "metadata-help": "此檔案包含額外的資訊,可能由數位相機或掃描機所建立的。\n若修改此檔案,部份資訊將無法保留。",
+       "metadata-help": "此檔案包含額外的資訊,可能由數位相機或掃描機所建立的。\n\n如果已自檔案初始狀態修改,一些詳細說明可能無法反映修改後的檔案。",
        "metadata-expand": "顯示詳細資料",
        "metadata-collapse": "隱藏詳細資料",
        "metadata-fields": "在本訊息中所列出的 EXIF 詮釋資料域將包含在圖片顯示頁面,當詮釋資料表損壞時只顯示以下訊息。\n其他的詮釋資料預設為隱藏。\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
index cb26337..b38287e 100644 (file)
@@ -128,6 +128,7 @@ $specialPageAliases = [
 ];
 
 $magicWords = [
+       'redirect'                  => [ '0', '#REDIRECCIÓ', '#REDIRECCIO', '#REDIRECT' ],
        'numberofarticles'          => [ '1', 'NOMBRED\'ARTICLES', 'NUMBEROFARTICLES' ],
        'numberoffiles'             => [ '1', 'NOMBRED\'ARXIUS', 'NUMBEROFFILES' ],
        'numberofusers'             => [ '1', 'NOMBRED\'USUARIS', 'NUMBEROFUSERS' ],
@@ -169,8 +170,7 @@ $datePreferences = [
 $defaultDateFormat = 'dmy';
 
 $bookstoreList = [
-       'Catàleg Col·lectiu de les Universitats de Catalunya' => 'http://ccuc.cbuc.es/cgi-bin/vtls.web.gateway?searchtype=control+numcard&searcharg=$1',
-       'Totselsllibres.com' => 'http://www.totselsllibres.com/tel/publi/busquedaAvanzadaLibros.do?ISBN=$1',
+       'Catàleg Col·lectiu de les Universitats de Catalunya' => 'http://ccuc.cbuc.cat/search*cat/X?SEARCH=$1',
        'inherit' => true,
 ];
 
index 4353dd7..0aaa4ff 100644 (file)
@@ -12,6 +12,7 @@
  *
  * @author Timo Tijhof, 2011-2012
  */
+/* eslint-env qunit */
 ( function ( mw, $ ) {
        'use strict';
 
index 185523a..d466216 100644 (file)
@@ -76,6 +76,8 @@
        font-size: 0.8em;
        margin-left: 0.5em;
        margin-bottom: 0.5em;
+       border: 0;
+       border-collapse: collapse;
        width: 400px;
 }
 
        font-weight: bold;
 }
 
-.mw_metadata th {
-       font-weight: normal;
-       text-align: center;
-}
-
-.mw_metadata td {
-       padding: 0.1em;
-}
-
-.mw_metadata {
-       border: 0;
-       border-collapse: collapse;
-}
-
 .mw_metadata td,
 .mw_metadata th {
        border: 1px solid #a2a9b1;
 
 .mw_metadata th {
        background-color: #f8f9fa;
+       font-weight: normal;
+       text-align: center;
 }
 
 .mw_metadata td {
        background-color: #fcfcfc;
+       padding-top: 0.1em;
+       padding-bottom: 0.1em;
 }
 
 .mw_metadata ul.metadata-langlist {
index ed21303..7c2f92b 100644 (file)
@@ -182,22 +182,16 @@ a {
        content: " (https:" attr( href ) ")";
 }
 
-/* MSIE/Win doesn't understand 'inherit' */
 a,
 a.external,
 a.new,
 a.stub {
+       /* IE 6 & 7 don't understand `inherit` */
        color: #000 !important;
        text-decoration: none !important;
-}
-
-/* Continue ... */
-a,
-a.external,
-a.new,
-a.stub {
-       color: inherit !important;
-       text-decoration: inherit !important;
+       /* Modern browser will apply this, IE 6 & 7 ignore the unknown */
+       color: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+       text-decoration: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
 
 /**
index a46e51d..7c4dbb1 100644 (file)
@@ -334,25 +334,14 @@ li span.deleted {
 /* Classes for Exif data display */
 table.mw_metadata {
        margin-left: 0.5em;
+       border: 0;
+       border-collapse: collapse;
 }
 
 table.mw_metadata caption {
        font-weight: bold;
 }
 
-table.mw_metadata th {
-       font-weight: normal;
-}
-
-table.mw_metadata td {
-       padding: 0.1em;
-}
-
-table.mw_metadata {
-       border: 0;
-       border-collapse: collapse;
-}
-
 table.mw_metadata td,
 table.mw_metadata th {
        border: 1px solid #aaa;
@@ -362,10 +351,13 @@ table.mw_metadata th {
 
 table.mw_metadata th {
        background-color: #f9f9f9;
+       font-weight: normal;
 }
 
 table.mw_metadata td {
        background-color: #fcfcfc;
+       padding-top: 0.1em;
+       padding-bottom: 0.1em;
 }
 
 table.mw_metadata td.spacer {
index 15bf676..0d7512f 100644 (file)
@@ -166,6 +166,7 @@ div.patrollink {
  */
 td.mw-label {
        text-align: right;
+       vertical-align: middle;
 }
 
 td.mw-input {
@@ -174,13 +175,6 @@ td.mw-input {
 
 td.mw-submit {
        text-align: left;
-}
-
-td.mw-label {
-       vertical-align: middle;
-}
-
-td.mw-submit {
        white-space: nowrap;
 }
 
index da35ac2..4cca1a6 100644 (file)
        order: @order;
 }
 
+/* stylelint-disable selector-no-vendor-prefix, at-rule-no-unknown */
+.mixin-placeholder( @rules ) {
+       // WebKit, Blink, Edge
+       &::-webkit-input-placeholder {
+               @rules();
+       }
+       // Internet Explorer 10-11
+       &:-ms-input-placeholder {
+               @rules();
+       }
+       // Firefox 19-
+       &::-moz-placeholder {
+               @rules();
+       }
+       // Firefox 4-18
+       &:-moz-placeholder {
+               @rules();
+       }
+       // W3C Standard Selectors Level 4
+       &::placeholder {
+               @rules();
+       }
+       // For inputs that use jquery.placeholder.js e.g. IE9
+       &.placeholder {
+               @rules();
+       }
+}
+/* stylelint-enable selector-no-vendor-prefix, at-rule-no-unknown */
+
 // Screen Reader Helper Mixin
 .mixin-screen-reader-text() {
        display: block;
index 31bb318..b4fe934 100644 (file)
@@ -129,6 +129,7 @@ figure[typeof~='mw:Image/Frame'] > *:first-child > img,
 .mw-image-border > *:first-child > img {
        border: 1px solid #ccc;
        margin: 3px;
+       background: #fff;
 }
 
 /* Hide the caption for frameless and plain floated images */
index 7147f04..8d63902 100644 (file)
@@ -8,28 +8,28 @@
 
 .iw-headline {
        font-weight: bold;
-    font-size: 1rem;
-    font-size: 16px;
-    opacity: 0.7;
+       font-size: 1rem;
+       font-size: 16px;
+       opacity: 0.7;
 }
 
 .iw-results {
-    list-style: none;
+       list-style: none;
        margin: 0;
 }
 
 .iw-resultset {
        margin-bottom: 1.2em;
        background-color: #f2f4f7;
-    vertical-align: top;
-    width: 100%;
-    float: left;
-    list-style-type: none;
+       vertical-align: top;
+       width: 100%;
+       float: left;
+       list-style-type: none;
 }
 
 /* clearfix */
 .iw-result:after {
-    visibility: hidden;
+       visibility: hidden;
        display: block;
        font-size: 0;
        content: " ";
 }
 
 * html .interwiki-result { /* IE6 */
-    zoom: 1;
+       zoom: 1;
 }
 *:first-child + html .iw-resultset { /* IE7 */
-    zoom: 1;
+       zoom: 1;
 }
 
 /* padding each .iw-resultset section seperately.
@@ -52,55 +52,55 @@ header and footer. */
 .iw-result__title,
 .iw-result__content,
 .iw-result__footer {
-    padding: 0.25em 0.85em;
+       padding: 0.25em 0.85em;
 }
 
 /* definition titles appear inline,
 to resemble a traditional dictionary definition */
 .iw-resultset--definition .iw-result__title {
-    display: inline;
-    padding: 0;
+       display: inline;
+       padding: 0;
 }
 
 .iw-resultset > div:first-child {
-    padding-top: 0.85em;
+       padding-top: 0.85em;
 }
 
 .iw-resultset > div:last-child {
-    padding-bottom: 0.85em;
+       padding-bottom: 0.85em;
 }
 
 .iw-result__title {
-    font-size: 16px; /* rem fallback */
-    font-size: 1rem;
+       font-size: 16px; /* rem fallback */
+       font-size: 1rem;
 }
 
 .iw-result__title a.extiw {
-    color: #252525;
-    font-weight: bold;
+       color: #252525;
+       font-weight: bold;
 }
 
 .iw-result__content:after { /* clearfix */
-     visibility: hidden;
-     display: block;
-     font-size: 0;
-     content: " ";
-     clear: both;
-     height: 0;
+       visibility: hidden;
+       display: block;
+       font-size: 0;
+       content: " ";
+       clear: both;
+       height: 0;
 }
 
 .iw-result__footer {
-    float: right;
+       float: right;
 }
 
 .iw-result__icon {
-    display: inline-block;
-    width: 24px;
-    height: 24px;
-    vertical-align: middle;
-    margin-right: 0.25em;
-    background: url( images/special.search/definition-icon.svg ) no-repeat 0 0;
-    background-size: 100% 100%;
+       display: inline-block;
+       width: 24px;
+       height: 24px;
+       vertical-align: middle;
+       margin-right: 0.25em;
+       background: url( images/special.search/definition-icon.svg ) no-repeat 0 0;
+       background-size: 100% 100%;
 }
 
 @interwikiContentTypes: definition, travel, quotation, book, course, news, textbook, image;
@@ -108,78 +108,79 @@ to resemble a traditional dictionary definition */
 .generate-iwIcons();
 
 .generate-iwIcons( @i:1 ) when ( @i =< length( @interwikiContentTypes ) ) {
-     @iwIcon: extract( @interwikiContentTypes, @i );
+       @iwIcon: extract( @interwikiContentTypes, @i );
 
-    .iw-result__icon--@{iwIcon} {
-        /*  stylelint-disable-next-line function-url-quotes */
-        background-image: url( 'images/special.search/@{iwIcon}-icon.png' );
-        /*  stylelint-disable-next-line function-url-quotes */
-        background-image: url( 'images/special.search/@{iwIcon}-icon.svg' );
-    }
+       .iw-result__icon--@{iwIcon} {
+               /*  stylelint-disable-next-line function-url-quotes */
+               background-image: url( 'images/special.search/@{iwIcon}-icon.png' );
+               /*  stylelint-disable-next-line function-url-quotes */
+               background-image: url( 'images/special.search/@{iwIcon}-icon.svg' );
+       }
 
-    .generate-iwIcons( @i + 1 );
+       .generate-iwIcons( @i + 1 );
 }
 
 /* image search result */
 .iw-result__mini-gallery {
-    position: relative;
-    float: left;
-    width: 60%;
-    height: 200px;
-    box-sizing: border-box;
-    padding: 0.25rem;
+       position: relative;
+       float: left;
+       width: 60%;
+       height: 200px;
+       box-sizing: border-box;
+       padding: 0.25rem;
 }
 
-.iw-result__mini-gallery__image {
-    display: block;
-    position: relative;
-    width: 100%;
-    height: 100%;
-    background-size: cover;
-    background-repeat: no-repeat;
-    background-position: center center;
+/* second and third images are small */
+.iw-result__mini-gallery:nth-child( 2 ),
+.iw-result__mini-gallery:nth-child( 3 ) { /* stylelint-disable-line indentation */
+       width: 40%;
+       height: 100px;
 }
 
-.iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption {
-    visibility: visible;
+.iw-result__mini-gallery__image {
+       display: block;
+       position: relative;
+       width: 100%;
+       height: 100%;
+       background-size: cover;
+       background-repeat: no-repeat;
+       background-position: center center;
 }
 
 .iw-result__mini-gallery__image > .iw-result__mini-gallery__caption { /* image gallery text */
-  visibility: hidden;
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  text-align: center;
-  color: #fff;
-  text-shadow: 0 0 10px rgba( 0, 0, 0, 0.4 ); /* improves legibility on white background*/
-  font-size: 0.8em;
-  padding: 5px;
-  background-color: rgba( 0, 0, 0, 0.5 );
+       visibility: hidden;
+       position: absolute;
+       bottom: 0;
+       left: 0;
+       text-align: center;
+       color: #fff;
+       text-shadow: 0 0 10px rgba( 0, 0, 0, 0.4 ); /* improves legibility on white background*/
+       font-size: 0.8em;
+       padding: 5px;
+       background-color: rgba( 0, 0, 0, 0.5 );
 }
 
-.iw-result__mini-gallery:nth-child(2),
-.iw-result__mini-gallery:nth-child(3) { /* second and third images are small */
-    width: 40%;
-    height: 100px;
+.iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption {
+       visibility: visible;
 }
 
 /* different types of interwiki result boxes */
 /* quotation box */
 .iw-resultset--quotation .iw-result__content {
-    border-left: 4px solid #afb1b5;
-    margin-left: 1em;
-    padding-top: 0;
-    margin-top: 0.25em;
+       border-left: 4px solid #afb1b5;
+       margin-left: 1em;
+       padding-top: 0;
+       margin-top: 0.25em;
 }
-.iw-resultset--quotation .iw-result__title{
-    margin-left: 1em;
+.iw-resultset--quotation .iw-result__title {
+       margin-left: 1em;
 }
-.iw-result--quotation .iw-result__title:before{
-    content: ' — ';
-    display: inline-block;
+.iw-result--quotation .iw-result__title:before {
+       content: ' — ';
+       display: inline-block;
 }
 .iw-result--quotation .iw-result__footer {
-    text-align: right;
+       text-align: right;
 }
 
 /* no results
@@ -187,42 +188,37 @@ span the interwiki results across the bottom of the page.
 */
 
 .mw-search-nonefound ~ #mw-search-interwiki {
-    width: 100%;
+       width: 100%;
 }
 
 .mw-search-nonefound ~ #mw-search-interwiki .iw-resultset {
-    width: 30%;
-    max-width: 300px;
-    margin-left: 0.5em;
-    margin-right: 0.5em;
+       width: 30%;
+       max-width: 300px;
+       margin-left: 0.5em;
+       margin-right: 0.5em;
 }
 
 /* mobile */
 @media only screen and ( max-width: 768px ) {
-    #mw-interwiki-results {
-        width: 100%;
-    }
-    .mw-search-results {
-        max-width: none !important;
-    }
-    .iw-resultset {
-        width: 45% !important;
-        margin-left: 0.5em !important;
-        margin-right: 0.5em !important;
-    }
+       #mw-interwiki-results {
+               width: 100%;
+       }
+       .mw-search-results {
+               max-width: none !important;
+       }
+       .iw-resultset {
+               width: 45% !important;
+               margin-left: 0.5em !important;
+               margin-right: 0.5em !important;
+       }
 
 }
 
 @media only screen and ( max-width: 600px ) {
-    .iw-resultset {
-        width: 100% !important;
-        margin-left: 0 !important;
-        margin-right: 0 !important;
-        max-width: none !important;
-    }
-}
-
-/* Evil temporary hax for cawiki */
-#sisterproject {
-       display: none;
+       .iw-resultset {
+               width: 100% !important;
+               margin-left: 0 !important;
+               margin-right: 0 !important;
+               max-width: none !important;
+       }
 }
index 87ce7be..d57c1de 100644 (file)
        vertical-align: middle;
 
        // Normalize & style placeholder text, see T139034
-       // Placeholder styles can't be grouped, otherwise they're ignored as invalid.
-
-       // Placeholder mixin
-       .mixin-placeholder() {
+       /* stylelint-disable indentation */
+       .mixin-placeholder( {
                color: @colorGray7;
-               font-style: italic;
-       }
-       // Firefox 4-18
-       &:-moz-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-               opacity: 1;
-       }
-       // Firefox 19-
-       &::-moz-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
                opacity: 1;
-       }
-       // Internet Explorer 10-11
-       &:-ms-input-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-       }
-       // WebKit, Blink, Edge
-       // Don't set `opacity < 1`, see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3901363/
-       &::-webkit-input-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-       }
-       // W3C Standard Selectors Level 4
-       &:placeholder-shown {
-               .mixin-placeholder;
-       }
+               // TODO: Is italic necessary? T147808
+               font-style: italic;
+       } );
+       /* stylelint-enable indentation */
 
        // Firefox: Remove red outline when `required` attribute set and invalid content.
        // See https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid
                // Remove the inner padding and cancel buttons in Chrome on OS X and Safari on OS X
                &::-webkit-search-cancel-button,
                &::-webkit-search-decoration {
-                       -webkit-appearance: none;
+                       -webkit-appearance: none;
                }
        }
 }
index 413efd4..b5b9cbe 100644 (file)
@@ -1,3 +1,4 @@
+/* stylelint-disable no-duplicate-selectors */
 @import "mediawiki.widgets.datetime.definitions";
 
 .mw-widgets-datetime-calendarWidget {
index 6317e9e..1c6c490 100644 (file)
@@ -1,3 +1,4 @@
+/* stylelint-disable no-duplicate-selectors */
 @import "mediawiki.widgets.datetime.definitions";
 
 .mw-widgets-datetime-dateTimeInputWidget {
index aa5c60a..b929a5a 100644 (file)
@@ -5,6 +5,7 @@
  * @license The MIT License (MIT); see LICENSE.txt
  */
 
+/* stylelint-disable no-duplicate-selectors */
 @import 'mediawiki.mixins';
 
 @calendarWidth: 21em;
index f70c03d..4a59dae 100644 (file)
@@ -1,3 +1,5 @@
+@import 'mediawiki.mixins';
+
 .mw-widgets-stashedFileWidget {
        display: inline-block;
        vertical-align: middle;
        vertical-align: middle;
        position: relative;
        overflow: hidden;
-       -webkit-box-sizing: border-box;
-          -moz-box-sizing: border-box;
-               box-sizing: border-box;
+       .box-sizing( border-box );
 
        > .mw-widgets-stashedFileWidget-label {
                line-height: 2.3em;
                margin: 0;
                overflow: hidden;
                white-space: nowrap;
-               -webkit-box-sizing: border-box;
-                  -moz-box-sizing: border-box;
-                               box-sizing: border-box;
+               .box-sizing( border-box );
                text-overflow: ellipsis;
                left: 0.5em;
                right: 2.375em;
index 660064a..37c0c9b 100644 (file)
                'stashwrongowner',
                'stashnosuchfilekey'
        ];
-       mw.log.deprecate( mw.Api, 'errors', mw.Api.errors, 'mw.Api.errors' );
+       mw.log.deprecate( mw.Api, 'errors', mw.Api.errors, null, 'mw.Api.errors' );
 
        /**
         * @static
                'duplicate',
                'exists'
        ];
-       mw.log.deprecate( mw.Api, 'warnings', mw.Api.warnings, 'mw.Api.warnings' );
+       mw.log.deprecate( mw.Api, 'warnings', mw.Api.warnings, null, 'mw.Api.warnings' );
 
 }( mediaWiki, jQuery ) );
index 1b9d2fb..a53e863 100644 (file)
@@ -44,9 +44,10 @@ tr.mw-htmlform-vertical-label td.mw-label {
        margin-left: 4px;
 }
 
-.mw-icon-question:lang(ar),
-.mw-icon-question:lang(fa),
-.mw-icon-question:lang(ur) {
+/* stylelint-disable indentation */
+.mw-icon-question:lang( ar ),
+.mw-icon-question:lang( fa ),
+.mw-icon-question:lang( ur ) {
        -webkit-transform: scaleX( -1 );
        -ms-transform: scaleX( -1 );
        transform: scaleX( -1 );
index e651c9c..3cb8e9d 100644 (file)
                        .removeAttr( 'height' );
 
                // Stretch image to take up the required size
-               if ( this.$thumbnail.width() > this.$thumbnail.height() ) {
-                       this.$img.attr( 'width', this.imageWidth + 'px' );
-               } else {
-                       this.$img.attr( 'height', this.imageHeight + 'px' );
-               }
+               this.$img.attr( 'height', ( this.imageHeight - this.$imgCaption.outerHeight() ) + 'px' );
 
                // Make the image smaller in case the current image
                // size is larger than the original file size.
                var imageLi = this.getCurrentImage(),
                        caption = imageLi.find( '.gallerytext' );
 
-               // Highlight current thumbnail
+               // The order of the following is important for size calculations
+               // 1. Highlight current thumbnail
                this.$gallery
                        .find( '.gallerybox.slideshow-current' )
                        .removeClass( 'slideshow-current' );
                imageLi.addClass( 'slideshow-current' );
 
-               // Show thumbnail stretched to the right size while the image loads
+               // 2. Show thumbnail
                this.$thumbnail = imageLi.find( 'img' );
                this.$img.attr( 'src', this.$thumbnail.attr( 'src' ) );
                this.$img.attr( 'alt', this.$thumbnail.attr( 'alt' ) );
                this.$imgLink.attr( 'href', imageLi.find( 'a' ).eq( 0 ).attr( 'href' ) );
-               this.setImageSize();
 
-               // Copy caption
+               // 3. Copy caption
                this.$imgCaption
                        .empty()
                        .append( caption.clone() );
 
-               // Load image at the required size
+               // 4. Stretch thumbnail to correct size
+               this.setImageSize();
+
+               // 5. Load image at the required size
                this.loadImage( this.$thumbnail ).done( function ( info, $img ) {
                        // Show this image to the user only if its still the current one
                        if ( this.$thumbnail.attr( 'src' ) === $img.attr( 'src' ) ) {
index 35b0190..be6e3a8 100644 (file)
@@ -1488,9 +1488,11 @@ nowiki 3
 Entities inside <nowiki>
 !! wikitext
 <nowiki>&lt;</nowiki>
-!! html
+!! html/php
 <p>&lt;
 </p>
+!! html/parsoid
+<p><span typeof="mw:Nowiki"><span typeof="mw:Entity" data-parsoid='{"src":"&amp;lt;","srcContent":"&lt;"}'>&lt;</span></span></p>
 !! end
 
 !! test
@@ -2311,8 +2313,12 @@ Entities inside <pre>
 <pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"#tag:pre","function":"#tag"},"params":{"1":{"wt":"Foo &lt;nowiki>&amp;rarr;bar&lt;/nowiki>"}},"i":0}}]}'>Foo <span typeof="mw:Entity">→</span>bar</pre>
 !! end
 
+## Don't expect this to rt, Parsoid drops the unmatched closing pre tags that
+## aren't enclosed in nowikis.
 !! test
 <nowiki> and <pre> preference (first one wins)
+!! options
+parsoid=wt2html
 !! wikitext
 <pre>
 <nowiki>
@@ -2341,17 +2347,16 @@ Entities inside <pre>
 &lt;/pre&gt;
 </p>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html","strippedNL":true}'>&lt;nowiki>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n&lt;nowiki>\n"}}'>&lt;nowiki>
 </pre>
-<p><span typeof="mw:Placeholder" data-parsoid='{"src":"&lt;/nowiki>"}'>&lt;/nowiki></span>
-&lt;/pre></p>
+<p>&lt;/nowiki></p>
+
 
 <p><span typeof="mw:Nowiki">
 &lt;pre>
 &lt;nowiki>
 &lt;/pre>
-</span>
-&lt;/pre></p>
+</span></p>
 !! end
 
 !! test
@@ -2366,8 +2371,6 @@ Entities inside <pre>
 # Parsoid doesn't strip empty tags, like Tidy does.
 !! test
 Empty pre; pre inside other HTML tags (T56946)
-!! options
-parsoid=wt2html,wt2wt
 !! wikitext
 a
 
@@ -2392,9 +2395,9 @@ foo
 !! html/parsoid
 <p>a</p>
 
-<div><pre>foo
+<div data-parsoid='{"stx":"html"}'><pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\nfoo\n"}}'>foo
 </pre></div>
-<pre></pre>
+<pre typeof="mw:Extension/pre" about="#mwt4" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":""}}'></pre>
 !! end
 
 !! test
@@ -2410,7 +2413,7 @@ HTML pre followed by indent-pre
 
 # Note that tidy removes the empty <p> tags from the start and end.
 # Parsoid does not, by design.
-!!test
+!! test
 Block tag pre
 !! wikitext
 <p><pre>foo</pre></p>
@@ -2419,8 +2422,8 @@ Block tag pre
 foo
 </pre>
 !! html/parsoid
-<p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre data-parsoid='{"stx":"html"}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
-!!end
+<p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
+!! end
 
 !!test
 Templates: Indent-Pre: 1a. Templates that break a line should suppress <pre>
@@ -2541,8 +2544,11 @@ Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
 </pre>
 !!end
 
+## Hmm, should Parsoid rt this?
 !! test
 Pres with newline attributes
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 <pre class="one
 two">hi</pre>
@@ -2550,8 +2556,7 @@ two">hi</pre>
 <pre class="one two">hi</pre>
 
 !! html/parsoid
-<pre class="one
-two" data-parsoid='{"stx":"html"}'>hi</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" class="one two" data-mw='{"name":"pre","attrs":{"class":"one two"},"body":{"extsrc":"hi"}}'>hi</pre>
 !! end
 
 !! test
@@ -2583,7 +2588,7 @@ x
 </pre>
 <p>&lt;pre</p>
 !! html/parsoid
-<pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
+<pre about="#mwt1" typeof="mw:Transclusion mw:Extension/pre" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
 
 
 <p>&lt;pre </p>
@@ -2601,7 +2606,7 @@ parsoid=wt2html
 <pre style="width:50%;">{{echo|foo}}</pre>
 
 !! html/parsoid
-<pre style="width:50%;">{{echo|foo}}</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" style="width:50%;" data-mw='{"name":"pre","attrs":{"style":"width:50%;"},"body":{"extsrc":"{{echo|foo}}"}}'>{{echo|foo}}</pre>
 !! end
 
 # TODO / maybe: fix wt2wt for this
@@ -3266,6 +3271,17 @@ array (
  a <pre typeof="mw:Extension/tag" about="#mwt2" data-parsoid='{}' data-mw='{"name":"tag","attrs":{},"body":null}'></pre>
 !! end
 
+!! test
+5. Indent-Pre and html pre
+!! wikitext
+ <pre class="123">hi</pre>
+!! html/php
+ <pre class="123">hi</pre>
+
+!! html/parsoid
+ <pre typeof="mw:Extension/pre" about="#mwt2" class="123" data-mw='{"name":"pre","attrs":{"class":"123"},"body":{"extsrc":"hi"}}'>hi</pre>
+!! end
+
 !!test
 Render paragraphs when indent-pre is suppressed in blocklevels
 !! wikitext
@@ -3455,18 +3471,17 @@ foo
 foo
 </pre>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html"}'>foo</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre>
 
-<pre data-parsoid='{"stx":"html","strippedNL":"\n"}'>
-foo
+<pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\nfoo\n"}}'>foo
 </pre>
 
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt6" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\nfoo\n"}}'>
 
 foo
 </pre>
 
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt8" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\n\nfoo\n"}}'>
 
 
 foo
@@ -3510,7 +3525,7 @@ haha
 
 </pre>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\n\n\n\nhaha\n\n\n\n\nhaha\n\n\n\n\n"}}'>
 
 
 
@@ -3561,7 +3576,7 @@ HTML-pre: 3: other wikitext
 </pre>
 
 !! html/parsoid
-<pre data-parsoid='{"stx":"html","strippedNL":true}'>* foo
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n* foo\n# bar\n= no-h =\n&#39;&#39; no-italic &#39;&#39;\n[[ NoLink ]]\n"}}'>* foo
 # bar
 = no-h =
 '' no-italic ''
@@ -6969,12 +6984,6 @@ Wikitext table with html-syntax row
 <td>foo</td></tr></tbody></table>
 !! end
 
-## Note that Parsoid output differs from PHP and PHP+tidy here.
-## The lack of <tr> tags in the PHP output is arguably a bug in the
-## PHP parser, which tidy then compounds by fostering the content
-## entirely out of the table.  Parsoid recognizes the table context
-## and generates <tr> and <td> wrappers as needed.  Hopefully nobody
-## depends on PHP's treatment of broken table markup!
 !! test
 Implicit <td> after a |-
 !! options
 !! html/php+tidy
 <p>a</p>
 !! html/parsoid
-<table>
-<tr><td>a</td></tr>
-</table>
-!! end
-
-# Again, Parsoid adds implicit <td>s here, PHP and Tidy strip the b out.
-!! test
-<pre> tags should be recognized in an explicit <td> context, but not in an implicit <td> context
-!! options
-parsoid=wt2html,html2html
-!! wikitext
-{|
-|-
-|
- a
-|-
- b
-|}
-!! html/php
-<table>
-
-<tr>
-<td>
-<pre>a
-</pre>
-</td></tr>
- b
-</table>
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>a</p><table>
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
 
-!! html/php+tidy
-<p>b</p>
-<table>
-<tr>
-<td>
-<pre>
-a
-</pre></td>
-</tr>
-</table>
-!! html/parsoid
-<table>
-<tbody>
-<tr><td><pre>a</pre></td></tr>
-<tr><td> b</td></tr>
-</tbody>
-</table>
+</tr></tbody></table>
 !! end
 
-# PHP + Tidy strips the list out of the table; Parsoid wraps it.
-# Parsoid generates the missing <td>, so wt2wt won't succeed.
 !! test
 Lists should be recognized in an implicit <td> context
 !! options
@@ -7063,13 +7028,10 @@ parsoid=wt2html,html2html
 <li>a</li>
 </ul>
 !! html/parsoid
-<table>
-<tr>
-<td><ul>
-<li>a</li>
-</ul></td>
-</tr>
-</table>
+<ul data-parsoid='{"fostered":true,"autoInsertedEnd":true}'><li>a</li></ul><table>
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
+
+</tr></tbody></table>
 !! end
 
 !! test
@@ -7090,8 +7052,7 @@ Table cells not properly parsed in an implicit-td context
 !! html/parsoid
 <table>
 <tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["",{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," "]}'> </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> a </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> b</td></tr>
-</tbody></table>
+<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," || a || b"]}'> </td><td about="#mwt1"> a </td><td about="#mwt1"> b</td></tr>
 !! end
 
 !! test
@@ -7531,7 +7492,7 @@ Piped link with no link text
 !! test
 Piped link with empty link text
 !! wikitext
-[[Main Page|<nowiki />]] - empty nowiki
+[[Main Page|<nowiki/>]] - empty nowiki
 [[Main Page| ]] - empty space
 [[Main Page|&nbsp;]] - empty non breaking space
 !! html/php
@@ -7540,7 +7501,7 @@ Piped link with empty link text
 <a href="/wiki/Main_Page" title="Main Page">&#160;</a> - empty non breaking space
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><meta typeof="mw:Placeholder" data-parsoid='{"src":"&lt;nowiki />"}'/></a> - empty nowiki
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><span typeof="mw:Nowiki"></span></a> - empty nowiki
 <a rel="mw:WikiLink" href="./Main_Page" title="Main Page"> </a> - empty space
 <a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><span typeof="mw:Entity" data-parsoid='{"src":"&amp;nbsp;","srcContent":" "}'> </span></a> - empty non breaking space</p>
 !! end
@@ -7881,6 +7842,22 @@ Link containing double quotes and spaces
 <p><a rel="mw:WikiLink" href="./Cool_%22Gator%22" title='Cool "Gator"'>Cool "Gator"</a></p>
 !! end
 
+!! test
+File containing double quotes and spaces
+!! wikitext
+[[File:Cool "Gator".png]]
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-parsoid='{"optList":[]}' data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Cool_%22Gator%22.png" data-parsoid='{"a":{"href":"./File:Cool_%22Gator%22.png"},"sa":{"href":"File:Cool \"Gator\".png"}}'><img resource='./File:Cool_"Gator".png' src="./Special:FilePath/Cool_%22Gator%22.png" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Cool_\"Gator\".png","height":"220","width":"220","src":"./Special:FilePath/Cool_%22Gator%22.png"},"sa":{"resource":"File:Cool \"Gator\".png","src":"./Special:FilePath/Cool_\"Gator\".png"}}'/></a></span></p>
+!! end
+
+!! test
+Redirect containing double quotes and spaces
+!! wikitext
+#REDIRECT [[Cool "Gator"]]
+!! html/parsoid
+<link rel="mw:PageProp/redirect" href="./Cool_%22Gator%22" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Cool_%22Gator%22"},"sa":{"href":"Cool \"Gator\""}}'/>
+!! end
+
 !! test
 Link containing double-single-quotes '' in text (T6598 sanity check)
 !! wikitext
@@ -8641,7 +8618,7 @@ Blah blah blah
 !! end
 
 !! test
-Escaping of interlanguage links
+Escaping of interlanguage links (T129218, T156308)
 !! wikitext
 Blah blah blah
 [[:es:Spanish]]
@@ -8652,7 +8629,8 @@ Blah blah blah
 <a href="http://zh.wikipedia.org/wiki/Chinese" class="extiw" title="zh:Chinese"> zh : Chinese </a>
 </p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Spanish" title="es:Spanish">es:Spanish</a>
+<p>Blah blah blah
+<a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Spanish" title="es:Spanish">es:Spanish</a>
 <a rel="mw:ExtLink" href="http://zh.wikipedia.org/wiki/Chinese" title="zh:Chinese"> zh : Chinese </a></p>
 !! end
 
@@ -9487,8 +9465,8 @@ List items are not parsed correctly following a <pre> block (T2785)
 <li> zar</li></ul>
 
 !! html/parsoid
-<ul><li> <pre data-parsoid='{"stx":"html"}'>foo</pre></li>
-<li> <pre data-parsoid='{"stx":"html"}'>bar</pre></li>
+<ul><li> <pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre></li>
+<li> <pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"bar"}}'>bar</pre></li>
 <li> zar</li></ul>
 !! end
 
@@ -17918,7 +17896,7 @@ http://example.com<nowiki>junk</nowiki>
 <p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a><span typeof="mw:Nowiki">junk</span></p>
 !! end
 
-!!test
+!! test
 Fuzz testing: URL adjacent extension (no space, dirty; pre)
 !! wikitext
 http://example.com<pre>junk</pre>
@@ -17931,10 +17909,10 @@ http://example.com<pre>junk</pre>
 junk
 </pre>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a></p><pre data-parsoid='{"stx":"html"}'>junk</pre>
-!!end
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a></p><pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"junk"}}'>junk</pre>
+!! end
 
-!!test
+!! test
 Fuzz testing: image with bogus manual thumbnail
 !! wikitext
 [[Image:foobar.jpg|thumbnail= ]]
@@ -17943,15 +17921,17 @@ Fuzz testing: image with bogus manual thumbnail
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"manualthumb","ak":"thumbnail= "}]}' data-mw='{"errors":[{"key":"missing-thumbnail","message":"This thumbnail does not exist.","params":{"name":""}}],"thumb":""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="./Special:FilePath/" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"220"},"sa":{"resource":"Image:foobar.jpg"}}'/></a></figure>
-!!end
+!! end
 
 !! test
 Fuzz testing: encoded newline in generated HTML replacements (T8577)
 !! wikitext
 <pre dir="&#10;"></pre>
-!! html
+!! html/php
 <pre dir="&#10;"></pre>
 
+!! html/parsoid
+<pre typeof="mw:Extension/pre" about="#mwt2" dir="&amp;#10;" data-mw='{"name":"pre","attrs":{"dir":"&amp;#10;"},"body":{"extsrc":""}}'></pre>
 !! end
 
 !! test
@@ -20750,9 +20730,6 @@ Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiw
 </p>
 !! end
 
-# Since Parsoid is starting to emit canonical wikitext for links,
-# [http://example.com http://example.com] will not RT back to that
-# form anymore.
 !! test
 HTML markups with conversion syntax in attribs, nested in other conversion blocks
 !! options
@@ -20775,6 +20752,9 @@ language=zh variant=zh-cn disabled
 </p>
 !! end
 
+# Since Parsoid is starting to emit canonical wikitext for links,
+# [http://example.com http://example.com] will not RT back to that
+# form anymore.
 !! test
 Proper conversion of text in external links
 !! options
@@ -22557,25 +22537,6 @@ Ignore pipe between table row attributes
 
 !! end
 
-!!test
-Gallery override link with WikiLink (T36852)
-!! wikitext
-<gallery>
-File:foobar.jpg|caption|alt=galleryalt|link=InterWikiLink
-</gallery>
-!! html
-<ul class="gallery mw-gallery-traditional">
-               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
-                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
-                       <div class="gallerytext">
-<p>caption
-</p>
-                       </div>
-               </div></li>
-</ul>
-
-!! end
-
 !!test
 Language parser function
 !! wikitext
@@ -22758,573 +22719,6 @@ parsoid=wt2html,wt2wt
 <p></p>
 !! end
 
-#### ----------------------------------------------------------------
-#### Parsoid-only testing of Parsoid's impl of <ref> and <references>
-#### tags. Parsoid's output for these tags differs from that of the
-#### PHP parser.
-#### ----------------------------------------------------------------
-
-!!test
-Ref: 1. ref-location should be replaced with an index span
-!! wikitext
-A <ref>foo</ref>
-B <ref name="x">foo</ref>
-C <ref name="y" />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-2"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-2"><span class="mw-reflink-text">[2]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-y_3-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"y"}}'><a href="./Main_Page#cite_note-y-3"><span class="mw-reflink-text">[3]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-x-2" id="cite_note-x-2"><a href="./Main_Page#cite_ref-x_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-x-2" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-y-3" id="cite_note-y-3"><a href="./Main_Page#cite_ref-y_3-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-y-3" class="mw-reference-text"></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 2. ref-tags with identical names should all get the same index
-!! wikitext
-A <ref name="x">foo</ref>
-B <ref name="x" />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 3. spaces in ref-names should be ignored
-!! wikitext
-A <ref name="x">foo</ref>
-B <ref name=" x " />
-C <ref name= x  />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-x_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-x_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-# NOTE: constructor is a predefined property in JS and constructor as a ref-name can clash with it if not handled properly)
-!!test
-Ref: 4. 'constructor' should be accepted as a valid ref-name
-!! wikitext
-A <ref name="constructor">foo</ref>
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-constructor_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-constructor-1"},"attrs":{"name":"constructor"}}'><a href="./Main_Page#cite_note-constructor-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-constructor-1" id="cite_note-constructor-1"><a href="./Main_Page#cite_ref-constructor_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-constructor-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 5. body should accept generic wikitext
-!! wikitext
-A <ref>
- This is a '''[[bolded link]]''' and this is a {{echo|transclusion}}
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">This is a <b><a rel="mw:WikiLink" href="./Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 6. indent-pres should not be output in ref-body
-!! wikitext
-A <ref>
- foo
- bar
- baz
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
- bar
- baz
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 7. No p-wrapping in ref-body
-!! wikitext
-A <ref>
-foo
-
-bar
-
-
-baz
-
-
-
-booz
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
-
-bar
-
-
-baz
-
-
-
-booz
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 8. transclusion wikitext has lower precedence
-!! wikitext
-A <ref> foo {{echo|</ref> B C}}
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C}}</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo {{echo|</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 9. unclosed comments should not leak out of ref-body
-!! wikitext
-A <ref> foo <!--</ref> B C
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <!----></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 10. Unclosed HTML tags should not leak out of ref-body
-!! wikitext
-A <ref> <b> foo </ref> B C
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
-
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 11. ref-tags acts like an inline element wrt P-wrapping
-!! wikitext
-A <ref>foo</ref> B
-C <ref>bar</ref> D
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B
-C <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> D</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 12. ref-tags act as trailing newline migration barrier
-!! wikitext
-<!--the newline at the end of this line moves out of the p tag-->a
-
-b<!--the newline at the end of this line stays inside the p tag--> <ref />
-<ref />
-
-c
-<references />
-!! html/parsoid
-<!--the newline at the end of this line moves out of the p tag--><p>a</p>
-
-
-<p>b<!--the newline at the end of this line stays inside the p tag--> <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<p>c</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"></span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"></span></li></ol>
-!!end
-
-!!test
-Ref: 13. ref-tags are not SOL-transparent and block indent-pres
-!! wikitext
-<ref>foo</ref> A
-<ref>bar
-</ref> B
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> A
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> B</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar
-</span></li>
-</ol>
-!!end
-
-## Roundtripping fails because of nowiki'ing
-!! test
-Ref: 14. A nested ref-tag should be emitted as plain text
-!! options
-parsoid=wt2html
-!! wikitext
-<ref>foo <ref>bar</ref> baz</ref>
-
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span> baz&lt;/ref></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo &lt;ref>bar</span></li></ol>
-!! end
-
-!!test
-Ref: 15. ref-tags with identical names should get identical indexes
-!! wikitext
-A1 <ref name="a">foo</ref> A2 <ref name="a" />
-B1 <ref name="b" /> B2 <ref name="b">bar</ref>
-
-<references />
-!! html/parsoid
-<p>A1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a-1"},"attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span> A2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B1 <span about="#mwt7" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span> B2 <span about="#mwt8" class="mw-ref" id="cite_ref-b_2-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-b_2-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-b_2-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-## We don't bother wt2wt-ing non-standard whitespace
-!!test
-Ref: 16. Tokenizer should accept non-standard whitespace in <ref> and </ref> tags
-!!options
-parsoid=wt2html
-!! wikitext
-A <ref >foo</ref >
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
-!!end
-
-!!test
-Ref: 17. Generate valid HTML5 id/about attributes
-!!wikitext
-<ref name="a b">foo</ref>
-<ref name=":0">ve-created name</ref>
-
-<references />
-!!html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-a_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_b-1"},"attrs":{"name":"a b"}}'><a href="./Main_Page#cite_note-a_b-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span>
-<span about="#mwt4" class="mw-ref" id="cite_ref-:0_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-:0-2"},"attrs":{"name":":0"}}'><a href="./Main_Page#cite_note-:0-2" style="counter-reset: mw-Ref 2;"><span class="mw-reflink-text">[2]</span></a></span>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a_b-1" id="cite_note-a_b-1"><a href="./Main_Page#cite_ref-a_b_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a_b-1" class="mw-reference-text">foo</span></li><li about="#cite_note-:0-2" id="cite_note-:0-2"><a href="./Main_Page#cite_ref-:0_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-:0-2" class="mw-reference-text">ve-created name</span></li></ol>
-
-!!end
-
-!!test
-Ref: 18. T58916: Extension attributes should be parsed as plain text
-!!wikitext
-<ref name="{{echo|a}}">foo</ref>
-
-<references />
-!!html/parsoid
-<p><span class="mw-ref" id="cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1"},"attrs":{"name":"{{echo|a}}"}}'><a href="./Main_Page#cite_note-.7B.7Becho.7Ca.7D.7D-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-.7B.7Becho.7Ca.7D.7D-1" id="cite_note-.7B.7Becho.7Ca.7D.7D-1"><a href="./Main_Page#cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 19. ref-tags with identical name encodings should get identical indexes
-!! wikitext
-1 <ref name="a & b">foo</ref> 2 <ref name="a &amp; b" />
-
-<references />
-!! html/parsoid
-<p>1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_.26_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_.26_b-1"},"attrs":{"name":"a &amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span> 2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_.26_b_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a &amp;amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-a_.26_b-1" id="cite_note-a_.26_b-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_.26_b_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_.26_b_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a_.26_b-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 20. ref-tags with identical names but different content should keep it
-!! wikitext
-A <ref name="foo">Foo one</ref>
-B <ref name="foo">Foo two</ref>
-C <ref name="foo" />
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-foo_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-foo-1"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-foo_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"Foo two"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-foo_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-foo-1" id="cite_note-foo-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-foo_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-foo_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-foo_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-foo-1" class="mw-reference-text">Foo one</span></li>
-</ol>
-!!end
-
-!!test
-References: 1. references tag without any refs should be handled properly
-!! wikitext
-<references />
-!! html/parsoid
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
-!!end
-
-!!test
-References: 2. references tag with group only outputs references from that group
-!! wikitext
-A <ref group="a">foo</ref>
-B <ref group="b">bar</ref>
-C <ref>baz</ref>
-
-<references group="a" />
-<references />
-<references group="b" />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"b"}}'><a href="./Main_Page#cite_note-2" data-mw-group="b"><span class="mw-reflink-text">[b 1]</span></a></span>
-C <span class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">baz</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt12" data-mw-group="b" data-mw='{"name":"references","attrs":{"group":"b"}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="b" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-References: 3. ref list should be cleared after processing references
-!! wikitext
-A <ref>foo</ref>
-
-<references />
-
-B <ref>bar</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-
-<p>B <span about="#mwt6" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-References: 4. only referenced group should be cleared after processing references
-!! wikitext
-A <ref group="a">afoo</ref>
-B <ref>bfoo</ref>
-
-<references group="a" />
-
-C <ref>cfoo</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">afoo</span></li>
-</ol>
-
-<p>C <span about="#mwt8" class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bfoo</span></li><li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">cfoo</span></li>
-</ol>
-!!end
-
-## Don't expect this to rt since we're dropping content
-!! test
-References: 5. ref tags in references should be processed while ignoring all other content
-!! options
-parsoid=wt2html,html2html
-!! wikitext
-A <ref name="a" />
-B <ref name="b">bar</ref>
-
-<references>
-<ref name="a">foo</ref>
-This should just get lost.
-</references>
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{},"body":{"html":"\n&lt;span about=\"#mwt8\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[59,82,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-a-1\"},\"attrs\":{\"name\":\"a\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-a-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>\n"}}'><li about="#cite_note-a-1" id="cite_note-a-1"><a href="./Main_Page#cite_ref-a_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
-</ol>
-!! end
-
-!! test
-References: 6. <references /> from a transclusion
-!! wikitext
-<ref>Foo</ref> {{echo|<references />}}
-!! html/parsoid
-<p><span about="#mwt3" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p> <ol class="mw-references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>
-</ol>
-!! end
-
-!! test
-References: 7. Multiple references tags (one without and one with nested refs) should be correctly handled
-!! wikitext
-A <ref>foo bar for a</ref>
-B <ref group="X" name="b" />
-
-<references />
-
-<references group="X">
-<ref name="b">foo</ref>
-</references>
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}'><a href="./Main_Page#cite_note-b-2" data-mw-group="X"><span class="mw-reflink-text">[X 1]</span></a></span>
-</p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo bar for a</span></li>
-</ol>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="X" data-mw='{"name":"references","attrs":{"group":"X"},"body":{"html":"\n&lt;span about=\"#mwt10\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[96,119,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-b-2\"},\"attrs\":{\"name\":\"b\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-b-2\" style=\"counter-reset: mw-Ref 1;\" data-mw-group=\"X\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[X 1]&lt;/span>&lt;/a>&lt;/span>\n"}}'>
-<li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" data-mw-group="X" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">foo</span></li>
-</ol>
-!! end
-
-!! test
-References: 8. T88019: Remove <meta>s from templates inside <ref> that's itself inside a template
-!! wikitext
-X{{echo|<ref>foo {{echo|<b>bar</b>}} and {{echo|baz}} boo</ref>}}
-<references />
-!! html/parsoid
-<p>X<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo {{echo|&lt;b>bar&lt;/b>}} and {{echo|baz}} boo&lt;/ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt7" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <b data-parsoid='{"stx":"html"}'>bar</b> and baz boo</span></li>
-</ol>
-!!end
-
-# This test only works in wt2html now as the <references /> are always generated
-# unless selser is active. Once T72722 is fixed, we should add a changes test
-# here to ensure that unrelated changes don't add the new <references />
-# when selser is active.
-!! test
-References: 9. Generate missing references list at the end
-!! wikitext
-A <ref>foo</ref>
-B <ref group="inexistent">bar</ref>
-!! html/parsoid
-<p>A <span class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B <span class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="./Main_Page#cite_note-2" data-mw-group="inexistent"><span class="mw-reflink-text">[inexistent 1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="inexistent" data-mw='{"name":"references","attrs":{"group":"inexistent"},"autoGenerated":true}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="inexistent" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!! end
-
-!! test
-References: 10. New <references/> shouldn't be added for unrelated edits.
-!! options
-parsoid={
-  "modes": ["selser"],
-  "changes": [["#x", "remove"]],
-  "selser": "noauto"
-}
-!! wikitext
-Unrelated text<span id="x"> that's going to disappear</span>.
-A <ref>foo</ref>
-!! wikitext/edited
-Unrelated text.
-A <ref>foo</ref>
-!!end
-
-!! test
-Entities in ref name
-!! wikitext
-<ref name="test &amp; me">hi</ref>
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-test_.26_me_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-test_.26_me-1"},"attrs":{"name":"test &amp;amp; me"}}'><a href="./Main_Page#cite_note-test_.26_me-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-test_.26_me-1" id="cite_note-test_.26_me-1"><a href="./Main_Page#cite_ref-test_.26_me_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-test_.26_me-1" class="mw-reference-text">hi</span></li>
-</ol>
-!! end
-
-## The output here may look funny, but it's what the php parser will do.  The
-## unclosed references tag becomes escaped text, and then a new references
-## tag is auto-generated.  The test is wt2html only because it roundtrips with
-## nowiki tags, and the auto-generated references tag is only dropped in
-## rtTestMode.
-!! test
-Generate references for unclosed references tag
-!! options
-parsoid=wt2html
-!! wikitext
-a<ref>foo</ref>
-
-<references>
-!! html/parsoid
-<p>a<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<p>&lt;references></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
-!! end
-
-!! test
-New reference serializes on its own line
-!! options
-parsoid=wt2wt,html2wt
-!! wikitext
-foo
-<references />
-!! html/parsoid
-foo<ol class="mw-references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
-!! end
-
 #### ----------------------------------------------------------------
 #### Parsoid-only testing of Parsoid's impl of LST
 #### Not implemented yet, see
@@ -26814,7 +26208,7 @@ WTS of autolinks with escapes (editing)
 parsoid={
   "modes": ["wt2wt"],
   "changes": [
-    [ "meta", "remove" ]
+    [ "span", "remove" ]
   ]
 }
 !! wikitext
index eff41e3..9060dfb 100644 (file)
@@ -451,7 +451,10 @@ class ApiMainTest extends ApiTestCase {
                $context->setRequest( new FauxRequest( [ 'errorformat' => 'plaintext' ] ) );
                $context->setLanguage( 'en' );
                $context->setConfig( new MultiConfig( [
-                       new HashConfig( [ 'ShowHostnames' => true, 'ShowSQLErrors' => false ] ),
+                       new HashConfig( [
+                               'ShowHostnames' => true, 'ShowSQLErrors' => false,
+                               'ShowExceptionDetails' => true, 'ShowDBErrorBacktrace' => true,
+                       ] ),
                        $context->getConfig()
                ] ) );
 
index cde1e5a..e0a82d0 100644 (file)
@@ -18,6 +18,7 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                        // to avoid notices during testMakeModuleResponse for missing
                        // wgResourceLoaderLESSVars keys in extension hooks.
                        'wgHooks' => [],
+                       'wgShowExceptionDetails' => true,
                ] );
        }
 
index 941e940..65b49ba 100644 (file)
@@ -862,4 +862,26 @@ class UserTest extends MediaWikiTestCase {
                // Clean up.
                $block->delete();
        }
+
+       public function testIsPingLimitable() {
+               $request = new FauxRequest();
+               $request->setIP( '1.2.3.4' );
+               $user = User::newFromSession( $request );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
+               $this->assertTrue( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.4' ] );
+               $this->assertFalse( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.0/8' ] );
+               $this->assertFalse( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
+               $noRateLimitUser = $this->getMockBuilder( User::class )->disableOriginalConstructor()
+                       ->setMethods( [ 'getIP', 'getRights' ] )->getMock();
+               $noRateLimitUser->expects( $this->any() )->method( 'getIP' )->willReturn( '1.2.3.4' );
+               $noRateLimitUser->expects( $this->any() )->method( 'getRights' )->willReturn( [ 'noratelimit' ] );
+               $this->assertFalse( $noRateLimitUser->isPingLimitable() );
+       }
 }
diff --git a/tests/phpunit/includes/utils/ClassCollectorTest.php b/tests/phpunit/includes/utils/ClassCollectorTest.php
new file mode 100644 (file)
index 0000000..e8a228e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * @covers ClassCollector
+ */
+class ClassCollectorTest extends PHPUnit_Framework_TestCase {
+
+       public static function provideCases() {
+               return [
+                       [
+                               "class Foo {}",
+                               [ 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass Bar {}",
+                               [ 'Example\Foo', 'Example\Bar' ],
+                       ],
+                       [
+                               "class_alias( 'Foo', 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 'Example\Foo', 'Foo' );",
+                               [ 'Example\Foo', 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 'Example\Foo', 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+                       [
+                               "class_alias( Foo::class, 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( Foo::class, 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCases
+        */
+       public function testGetClasses( $code, array $classes, $message = null ) {
+               $cc = new ClassCollector();
+               $this->assertEquals( $classes, $cc->getClasses( "<?php\n$code" ), $message );
+       }
+}
index f36b51a..d81e8c6 100644 (file)
@@ -68,6 +68,7 @@ class AutoLoaderTest extends MediaWikiTestCase {
                        }
 
                        // We could use token_get_all() here, but this is faster
+                       // Note: Keep in sync with ClassCollector
                        $matches = [];
                        preg_match_all( '/
                                ^ [\t ]* (?:
@@ -78,6 +79,11 @@ class AutoLoaderTest extends MediaWikiTestCase {
                                                ([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s*
                                                ([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s*
                                        \) \s* ;
+                               |
+                                       class_alias \s* \( \s*
+                                               (?P<originalStatic> [a-zA-Z0-9_]+)::class \s* , \s*
+                                               ([\'"]) (?P<aliasString> [^\'"]+ ) \g{-2} \s*
+                                       \) \s* ;
                                )
                        /imx', $contents, $matches, PREG_SET_ORDER );
 
@@ -95,11 +101,18 @@ class AutoLoaderTest extends MediaWikiTestCase {
 
                        foreach ( $matches as $match ) {
                                if ( !empty( $match['class'] ) ) {
+                                       // 'class Foo {}'
                                        $class = $fileNamespace . $match['class'];
                                        $actual[$class] = $file;
                                        $classesInFile[$class] = true;
                                } else {
-                                       $aliasesInFile[$match['alias']] = $match['original'];
+                                       if ( !empty( $match['original'] ) ) {
+                                               // 'class_alias( "Foo", "Bar" );'
+                                               $aliasesInFile[$match['alias']] = $match['original'];
+                                       } else {
+                                               // 'class_alias( Foo::class, "Bar" );'
+                                               $aliasesInFile[$match['aliasString']] = $fileNamespace . $match['originalStatic'];
+                                       }
                                }
                        }
 
diff --git a/tests/qunit/.eslintrc.json b/tests/qunit/.eslintrc.json
new file mode 100644 (file)
index 0000000..b3a46f4
--- /dev/null
@@ -0,0 +1,14 @@
+{
+       "extends": "../../.eslintrc.json",
+       "env": {
+               "qunit": true
+       },
+       "globals": {
+               "sinon": false
+       },
+       "rules": {
+               "operator-linebreak": 0,
+               "quote-props": [ "error", "as-needed" ],
+               "valid-jsdoc": 0
+       }
+}
index 5a96dc3..1c79f6d 100644 (file)
@@ -16,7 +16,7 @@
 /*
  * @example QUnit
  * <code>
-       QUnit.test( 'Output matches PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
+       QUnit.test( 'Output matches PHP parser', function ( assert ) {
                mw.messages.set( mw.libs.phpParserData.messages );
                $.each( mw.libs.phpParserData.tests, function ( i, test ) {
                        QUnit.stop();
@@ -133,7 +133,7 @@ class GenerateJqueryMsgData extends Maintenance {
                                . "// languages, and parser modes. Intended for use by a unit test framework by looping\n"
                                . "// through the object and comparing its parser return value with the 'result' property.\n"
                                . '// Last generated with ' . basename( __FILE__ ) . ' at ' . gmdate( 'r' ) . "\n"
-                               . "//jscs:disable\n"
+                               . "/* eslint-disable */\n"
                                . "\n"
                                . 'mediaWiki.libs.phpParserData = ' . FormatJson::encode( $phpParserData, true ) . ";\n";
 
index 498acc1..90dc1b2 100644 (file)
@@ -2,7 +2,7 @@
 // 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 Fri, 10 Jul 2015 11:44:08 +0000
-//jscs:disable
+/* eslint-disable */
 
 mediaWiki.libs.phpParserData = {
     "messages": {
index 0b28684..cef5c15 100644 (file)
@@ -1,8 +1,8 @@
-/*global CompletenessTest, sinon */
+/* global CompletenessTest, sinon */
 ( function ( $, mw, QUnit ) {
        'use strict';
 
-       var mwTestIgnore, mwTester, addons;
+       var mwTestIgnore, addons;
 
        /**
         * Add bogus to url to prevent IE crazy caching
@@ -26,6 +26,7 @@
        QUnit.config.testTimeout = 60 * 1000;
 
        // Reduce default animation duration from 400ms to 0ms for unit tests
+       // eslint-disable-next-line no-underscore-dangle
        $.fx.speeds._default = 0;
 
        // Add a checkbox to QUnit header to toggle MediaWiki ResourceLoader debug mode.
                        return false;
                };
 
-               mwTester = new CompletenessTest( mw, mwTestIgnore );
+               // eslint-disable-next-line no-new
+               new CompletenessTest( mw, mwTestIgnore );
        }
 
        /**
                }
 
                function freshMessagesCopy( custom ) {
-                       return $.extend( /*deep=*/true, {}, liveMessages.get(), custom );
+                       return $.extend( /* deep */true, {}, liveMessages.get(), custom );
                }
 
                /**
                }
        } ) );
 
-       QUnit.test( 'Setup', 3, function ( assert ) {
+       QUnit.test( 'Setup', function ( assert ) {
                assert.equal( mw.html.escape( 'foo' ), 'mocked', 'setup() callback was ran.' );
                assert.equal( mw.config.get( 'testVar' ), 'foo', 'config object applied' );
                assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object applied' );
                mw.messages.set( 'testMsg', 'Bar.' );
        } );
 
-       QUnit.test( 'Teardown', 2, function ( assert ) {
+       QUnit.test( 'Teardown', function ( assert ) {
                assert.equal( mw.config.get( 'testVar' ), 'foo', 'config object restored and re-applied after test()' );
                assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object restored and re-applied after test()' );
        } );
 
-       QUnit.test( 'Loader status', 2, function ( assert ) {
+       QUnit.test( 'Loader status', function ( assert ) {
                var i, len, state,
                        modules = mw.loader.getModuleNames(),
                        error = [],
                assert.deepEqual( missing, [], 'Modules in missing state' );
        } );
 
-       QUnit.test( 'htmlEqual', 8, function ( assert ) {
+       QUnit.test( 'htmlEqual', function ( assert ) {
                assert.htmlEqual(
                        '<div><p class="some classes" data-length="10">Child paragraph with <a href="http://example.com">A link</a></p>Regular text<span>A span</span></div>',
                        '<div><p data-length=\'10\'  class=\'some classes\'>Child paragraph with <a href=\'http://example.com\' >A link</a></p>Regular text<span>A span</span></div>',
 
        QUnit.module( 'test.mediawiki.qunit.testrunner-after', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Teardown', 3, function ( assert ) {
+       QUnit.test( 'Teardown', function ( assert ) {
                assert.equal( mw.html.escape( '<' ), '&lt;', 'teardown() callback was ran.' );
                assert.equal( mw.config.get( 'testVar' ), null, 'config object restored to live in next module()' );
                assert.equal( mw.messages.get( 'testMsg' ), null, 'messages object restored to live in next module()' );
index 0fb7d9a..e4b6157 100644 (file)
@@ -1,4 +1,6 @@
 ( function ( $ ) {
+       var getAccessKeyPrefixTestData, updateTooltipAccessKeysTestData;
+
        QUnit.module( 'jquery.accessKeyLabel', QUnit.newMwEnvironment( {
                messages: {
                        brackets: '[$1]',
@@ -6,47 +8,47 @@
                }
        } ) );
 
-       var getAccessKeyPrefixTestData = [
-                       // ua string, platform string, expected prefix
-                       // Internet Explorer
-                       [ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Win64', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', 'Win64', 'alt-' ],
-                       // Firefox
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19', 'MacIntel', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17', 'Linux i686', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Win32', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1', 'Linux 1686', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Windows NT 5.2; U; de; rv:1.8.0) Gecko/20060728 Firefox/1.5.0', 'Win32', 'alt-' ],
-                       // Safari / Konqueror
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; de-de) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.28.3', 'MacIntel', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9', 'Linux i686', 'ctrl-' ],
-                       // Opera
-                       [ 'Opera/9.80 (Windows NT 5.1)', 'Win32', 'shift-esc-' ],
-                       [ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130', 'Win32', 'alt-shift-' ],
-                       // Chrome
-                       [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ],
-                       // Unknown! Note: These aren't necessarily *right*, this is just
-                       // testing that we're getting the expected output based on the
-                       // platform.
-                       [ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6', 'MacPPC', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5', 'Linux i686', 'alt-' ]
-               ],
-               // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
-               updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
+       getAccessKeyPrefixTestData = [
+               // ua string, platform string, expected prefix
+               // Internet Explorer
+               [ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Win64', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', 'Win64', 'alt-' ],
+               // Firefox
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19', 'MacIntel', 'ctrl-' ],
+               [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17', 'Linux i686', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Win32', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1', 'Linux 1686', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Windows NT 5.2; U; de; rv:1.8.0) Gecko/20060728 Firefox/1.5.0', 'Win32', 'alt-' ],
+               // Safari / Konqueror
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; de-de) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.28.3', 'MacIntel', 'ctrl-' ],
+               [ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9', 'Linux i686', 'ctrl-' ],
+               // Opera
+               [ 'Opera/9.80 (Windows NT 5.1)', 'Win32', 'shift-esc-' ],
+               [ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130', 'Win32', 'alt-shift-' ],
+               // Chrome
+               [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ],
+               // Unknown! Note: These aren't necessarily *right*, this is just
+               // testing that we're getting the expected output based on the
+               // platform.
+               [ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6', 'MacPPC', 'ctrl-' ],
+               [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5', 'Linux i686', 'alt-' ]
+       ];
+       // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
+       updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
 
        function makeInput( title, accessKey ) {
                // The properties aren't escaped, so make sure you don't call this function with values that need to be escaped!
                return '<input title="' + title + '" ' + ( accessKey ? 'accessKey="' + accessKey + '" ' : '' ) + ' />';
        }
 
-       QUnit.test( 'getAccessKeyPrefix', getAccessKeyPrefixTestData.length, function ( assert ) {
+       QUnit.test( 'getAccessKeyPrefix', function ( assert ) {
                var i;
                for ( i = 0; i < getAccessKeyPrefixTestData.length; i++ ) {
                        assert.equal( $.fn.updateTooltipAccessKeys.getAccessKeyPrefix( {
@@ -56,7 +58,7 @@
                }
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - current browser', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys - current browser', function ( assert ) {
                var title = $( makeInput( 'Title', 'a' ) ).updateTooltipAccessKeys().prop( 'title' ),
                        // The new title should be something like "Title [alt-a]", but the exact label will depend on the browser.
                        // The "a" could be capitalized, and the prefix could be anything, e.g. a simple "^" for ctrl-
@@ -66,7 +68,7 @@
                assert.notEqual( result[ 1 ], 'test-', 'Prefix used for testing shouldn\'t be used in production.' );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - no access key', updateTooltipAccessKeysTestData.length, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys - no access key', function ( assert ) {
                var i, oldTitle, $input, newTitle;
                for ( i = 0; i < updateTooltipAccessKeysTestData.length; i++ ) {
                        oldTitle = 'Title' + updateTooltipAccessKeysTestData[ i ];
@@ -77,9 +79,9 @@
                }
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - with access key', updateTooltipAccessKeysTestData.length, function ( assert ) {
-               $.fn.updateTooltipAccessKeys.setTestMode( true );
+       QUnit.test( 'updateTooltipAccessKeys - with access key', function ( assert ) {
                var i, oldTitle, $input, newTitle;
+               $.fn.updateTooltipAccessKeys.setTestMode( true );
                for ( i = 0; i < updateTooltipAccessKeysTestData.length; i++ ) {
                        oldTitle = 'Title' + updateTooltipAccessKeysTestData[ i ];
                        $input = $( makeInput( oldTitle, 'a' ) );
                $.fn.updateTooltipAccessKeys.setTestMode( false );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys with label element', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys with label element', function ( assert ) {
+               var html, $label, $input;
                $.fn.updateTooltipAccessKeys.setTestMode( true );
-               var html = '<label for="testInput" title="Title">Label</label><input id="testInput" accessKey="a" />',
-                       $label, $input;
+               html = '<label for="testInput" title="Title">Label</label><input id="testInput" accessKey="a" />';
                $( '#qunit-fixture' ).html( html );
                $label = $( '#qunit-fixture label' );
                $input = $( '#qunit-fixture input' );
                $.fn.updateTooltipAccessKeys.setTestMode( false );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys with label element as parent', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys with label element as parent', function ( assert ) {
+               var html, $label, $input;
                $.fn.updateTooltipAccessKeys.setTestMode( true );
-               var html = '<label title="Title">Label<input id="testInput" accessKey="a" /></label>',
-               $label, $input;
+               html = '<label title="Title">Label<input id="testInput" accessKey="a" /></label>';
                $( '#qunit-fixture' ).html( html );
                $label = $( '#qunit-fixture label' );
                $input = $( '#qunit-fixture input' );
index a1b2e5c..c3521ba 100644 (file)
@@ -17,7 +17,7 @@
                return i;
        }
 
-       QUnit.test( 'Position right', 4, function ( assert ) {
+       QUnit.test( 'Position right', function ( assert ) {
                // We need this thing to be visible, so append it to the DOM
                var $span, spanText, d, spanTextNew,
                        origText = 'This is a really long random string and there is no way it fits in 100 pixels.',
index e6aa3aa..558e641 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.byteLength', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Simple text', 5, function ( assert ) {
+       QUnit.test( 'Simple text', function ( assert ) {
                var azLc = 'abcdefghijklmnopqrstuvwxyz',
                        azUc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                        num = '0123456789',
@@ -16,7 +16,7 @@
 
        } );
 
-       QUnit.test( 'Special text', 4, function ( assert ) {
+       QUnit.test( 'Special text', function ( assert ) {
                // https://en.wikipedia.org/wiki/UTF-8
                var u0024 = '$',
                        // Cent symbol
index 5c2a06c..c7b7cc0 100644 (file)
                        expected: ''
                }, options );
 
-               QUnit.asyncTest( opt.description, 1, function ( assert ) {
-                       setTimeout( function () {
-                               opt.$input.appendTo( '#qunit-fixture' );
+               QUnit.test( opt.description, function ( assert ) {
+                       opt.$input.appendTo( '#qunit-fixture' );
 
-                               // Simulate pressing keys for each of the sample characters
-                               addChars( opt.$input, opt.sample );
+                       // Simulate pressing keys for each of the sample characters
+                       addChars( opt.$input, opt.sample );
 
-                               assert.equal(
-                                       opt.$input.val(),
-                                       opt.expected,
-                                       'New value matches the expected string'
-                               );
-
-                               QUnit.start();
-                       } );
+                       assert.equal(
+                               opt.$input.val(),
+                               opt.expected,
+                               'New value matches the expected string'
+                       );
                } );
        }
 
                expected: ''
        } );
 
-       QUnit.test( 'Confirm properties and attributes set', 4, function ( assert ) {
-               var $el, $elA, $elB;
+       QUnit.test( 'Confirm properties and attributes set', function ( assert ) {
+               var $el;
 
                $el = $( '<input>' ).attr( 'type', 'text' )
                        .attr( 'maxlength', '7' )
 
                assert.strictEqual( $el.attr( 'maxlength' ), undefined, 'maxlength attribute removed for limit with callback' );
 
-               $elA = $( '<input>' ).attr( 'type', 'text' )
+               $( '<input>' ).attr( 'type', 'text' )
                        .addClass( 'mw-test-byteLimit-foo' )
                        .attr( 'maxlength', '7' )
                        .appendTo( '#qunit-fixture' );
 
-               $elB = $( '<input>' ).attr( 'type', 'text' )
+               $( '<input>' ).attr( 'type', 'text' )
                        .addClass( 'mw-test-byteLimit-foo' )
                        .attr( 'maxlength', '12' )
                        .appendTo( '#qunit-fixture' );
                $el.byteLimit();
        } );
 
-       QUnit.test( 'Trim from insertion when limit exceeded', 2, function ( assert ) {
+       QUnit.test( 'Trim from insertion when limit exceeded', function ( assert ) {
                var $el;
 
-               // Use a new <input /> because the bug only occurs on the first time
+               // Use a new <input> because the bug only occurs on the first time
                // the limit it reached (T42850)
                $el = $( '<input>' ).attr( 'type', 'text' )
                        .appendTo( '#qunit-fixture' )
index 00de895..d6208e9 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.colorUtil', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'getRGB', 18, function ( assert ) {
+       QUnit.test( 'getRGB', function ( assert ) {
                assert.strictEqual( $.colorUtil.getRGB(), undefined, 'No arguments' );
                assert.strictEqual( $.colorUtil.getRGB( '' ), undefined, 'Empty string' );
                assert.deepEqual( $.colorUtil.getRGB( [ 0, 100, 255 ] ), [ 0, 100, 255 ], 'Parse array of rgb values' );
@@ -26,7 +26,7 @@
                assert.strictEqual( $.colorUtil.getRGB( 'mediaWiki' ), undefined, 'Inexisting color name' );
        } );
 
-       QUnit.test( 'rgbToHsl', 1, function ( assert ) {
+       QUnit.test( 'rgbToHsl', function ( assert ) {
                var hsl, ret;
 
                // Cross-browser differences in decimals...
@@ -42,7 +42,7 @@
                assert.deepEqual( ret, [ 0.33, 0.73, 0.75 ], 'rgb(144, 238, 144): hsl(0.33, 0.73, 0.75)' );
        } );
 
-       QUnit.test( 'hslToRgb', 1, function ( assert ) {
+       QUnit.test( 'hslToRgb', function ( assert ) {
                var rgb, ret;
                rgb = $.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
 
@@ -52,7 +52,7 @@
                assert.deepEqual( ret, [ 183, 240, 168 ], 'hsl(0.3, 0.7, 0.8): rgb(183, 240, 168)' );
        } );
 
-       QUnit.test( 'getColorBrightness', 2, function ( assert ) {
+       QUnit.test( 'getColorBrightness', function ( assert ) {
                var a, b;
                a = $.colorUtil.getColorBrightness( 'red', +0.1 );
                assert.equal( a, 'rgb(255,50,50)', 'Start with named color "red", brighten 10%' );
index ca3f418..74d8509 100644 (file)
@@ -1,10 +1,10 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.getAttrs', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'getAttrs()', 1, function ( assert ) {
+       QUnit.test( 'getAttrs()', function ( assert ) {
                var attrs = {
                                foo: 'bar',
-                               'class': 'lorem',
+                               class: 'lorem',
                                'data-foo': 'data value'
                        },
                        $el = $( '<div>' ).attr( attrs );
index 8c62876..6a265eb 100644 (file)
@@ -1,17 +1,17 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.hidpi', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'devicePixelRatio', 1, function ( assert ) {
+       QUnit.test( 'devicePixelRatio', function ( assert ) {
                var devicePixelRatio = $.devicePixelRatio();
                assert.equal( typeof devicePixelRatio, 'number', '$.devicePixelRatio() returns a number' );
        } );
 
-       QUnit.test( 'bracketedDevicePixelRatio', 1, function ( assert ) {
-               var devicePixelRatio = $.devicePixelRatio();
-               assert.equal( typeof devicePixelRatio, 'number', '$.bracketedDevicePixelRatio() returns a number' );
+       QUnit.test( 'bracketedDevicePixelRatio', function ( assert ) {
+               var ratio = $.bracketedDevicePixelRatio();
+               assert.equal( typeof ratio, 'number', '$.bracketedDevicePixelRatio() returns a number' );
        } );
 
-       QUnit.test( 'bracketDevicePixelRatio', 8, function ( assert ) {
+       QUnit.test( 'bracketDevicePixelRatio', function ( assert ) {
                assert.equal( $.bracketDevicePixelRatio( 0.75 ), 1, '0.75 gives 1' );
                assert.equal( $.bracketDevicePixelRatio( 1 ), 1, '1 gives 1' );
                assert.equal( $.bracketDevicePixelRatio( 1.25 ), 1.5, '1.25 gives 1.5' );
@@ -22,7 +22,7 @@
                assert.equal( $.bracketDevicePixelRatio( 3 ), 2, '3 gives 2' );
        } );
 
-       QUnit.test( 'matchSrcSet', 6, function ( assert ) {
+       QUnit.test( 'matchSrcSet', function ( assert ) {
                var srcset = 'onefive.png 1.5x, two.png 2x';
 
                // Nice exact matches
index e1fb96d..0dac22e 100644 (file)
        QUnit.module( 'jquery.highlightText', QUnit.newMwEnvironment() );
 
        QUnit.test( 'Check', function ( assert ) {
-               var $fixture, cases = [
-                       {
-                               desc: 'Test 001',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 002',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue ',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 003',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue Ö',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
-                       },
-                       {
-                               desc: 'Test 004',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue Öy',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
-                       },
-                       {
-                               desc: 'Test 005',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 006',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue ',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 007',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue Ö',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
-                       },
-                       {
-                               desc: 'Test 008',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue Öy',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
-                       },
-                       {
-                               desc: 'Test 009: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Österreich',
-                               expected: '<span class="highlight">Österreich</span>'
-                       },
-                       {
-                               desc: 'Test 010: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Ö',
-                               expected: '<span class="highlight">Ö</span>sterreich'
-                       },
-                       {
-                               desc: 'Test 011: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Öst',
-                               expected: '<span class="highlight">Öst</span>erreich'
-                       },
-                       {
-                               desc: 'Test 012: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Oe',
-                               expected: 'Österreich'
-                       },
-                       {
-                               desc: 'Test 013: Highlighter broken on punctuation mark?',
-                               text: 'So good. To be there',
-                               highlight: 'good',
-                               expected: 'So <span class="highlight">good</span>. To be there'
-                       },
-                       {
-                               desc: 'Test 014: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: 'be',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 015: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: ' be',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 016: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: 'be ',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 017: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: ' be ',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 018: en de Highlighter broken on special character at the end?',
-                               text: 'So good. xbß',
-                               highlight: 'xbß',
-                               expected: 'So good. <span class="highlight">xbß</span>'
-                       },
-                       {
-                               desc: 'Test 019: en de Highlighter broken on special character at the end?',
-                               text: 'So good. xbß.',
-                               highlight: 'xbß.',
-                               expected: 'So good. <span class="highlight">xbß.</span>'
-                       },
-                       {
-                               desc: 'Test 020: RTL he Hebrew',
-                               text: 'חסיד אומות העולם',
-                               highlight: 'חסיד אומות העולם',
-                               expected: '<span class="highlight">חסיד</span> <span class="highlight">אומות</span> <span class="highlight">העולם</span>'
-                       },
-                       {
-                               desc: 'Test 021: RTL he Hebrew',
-                               text: 'חסיד אומות העולם',
-                               highlight: 'חסי',
-                               expected: '<span class="highlight">חסי</span>ד אומות העולם'
-                       },
-                       {
-                               desc: 'Test 022: ja Japanese',
-                               text: '諸国民の中の正義の人',
-                               highlight: '諸国民の中の正義の人',
-                               expected: '<span class="highlight">諸国民の中の正義の人</span>'
-                       },
-                       {
-                               desc: 'Test 023: ja Japanese',
-                               text: '諸国民の中の正義の人',
-                               highlight: '諸国',
-                               expected: '<span class="highlight">諸国</span>民の中の正義の人'
-                       },
-                       {
-                               desc: 'Test 024: fr French text and « french quotes » (guillemets)',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L\'oiseau est sur l’île »',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L\'oiseau</span> <span class="highlight">est</span> <span class="highlight">sur</span> <span class="highlight">l’île</span> <span class="highlight">»</span>'
-                       },
-                       {
-                               desc: 'Test 025: fr French text and « french quotes » (guillemets)',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L\'oise',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L\'oise</span>au est sur l’île »'
-                       },
-                       {
-                               desc: 'Test 025a: fr French text and « french quotes » (guillemets) - does it match the single strings "«" and "L" separately?',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L</span>\'oiseau est sur <span class="highlight">l</span>’île »'
-                       },
-                       {
-                               desc: 'Test 026: ru Russian',
-                               text: 'Праведники мира',
-                               highlight: 'Праведники мира',
-                               expected: '<span class="highlight">Праведники</span> <span class="highlight">мира</span>'
-                       },
-                       {
-                               desc: 'Test 027: ru Russian',
-                               text: 'Праведники мира',
-                               highlight: 'Праве',
-                               expected: '<span class="highlight">Праве</span>дники мира'
-                       },
-                       {
-                               desc: 'Test 028 ka Georgian',
-                               text: 'მთავარი გვერდი',
-                               highlight: 'მთავარი გვერდი',
-                               expected: '<span class="highlight">მთავარი</span> <span class="highlight">გვერდი</span>'
-                       },
-                       {
-                               desc: 'Test 029 ka Georgian',
-                               text: 'მთავარი გვერდი',
-                               highlight: 'მთა',
-                               expected: '<span class="highlight">მთა</span>ვარი გვერდი'
-                       },
-                       {
-                               desc: 'Test 030 hy Armenian',
-                               text: 'Նոնա Գափրինդաշվիլի',
-                               highlight: 'Նոնա Գափրինդաշվիլի',
-                               expected: '<span class="highlight">Նոնա</span> <span class="highlight">Գափրինդաշվիլի</span>'
-                       },
-                       {
-                               desc: 'Test 031 hy Armenian',
-                               text: 'Նոնա Գափրինդաշվիլի',
-                               highlight: 'Նոն',
-                               expected: '<span class="highlight">Նոն</span>ա Գափրինդաշվիլի'
-                       },
-                       {
-                               desc: 'Test 032: th Thai',
-                               text: 'พอล แอร์ดิช',
-                               highlight: 'พอล แอร์ดิช',
-                               expected: '<span class="highlight">พอล</span> <span class="highlight">แอร์ดิช</span>'
-                       },
-                       {
-                               desc: 'Test 033: th Thai',
-                               text: 'พอล แอร์ดิช',
-                               highlight: 'พอ',
-                               expected: '<span class="highlight">พอ</span>ล แอร์ดิช'
-                       },
-                       {
-                               desc: 'Test 034: RTL ar Arabic',
-                               text: 'بول إيردوس',
-                               highlight: 'بول إيردوس',
-                               expected: '<span class="highlight">بول</span> <span class="highlight">إيردوس</span>'
-                       },
-                       {
-                               desc: 'Test 035: RTL ar Arabic',
-                               text: 'بول إيردوس',
-                               highlight: 'بو',
-                               expected: '<span class="highlight">بو</span>ل إيردوس'
-                       }
-               ];
-               QUnit.expect( cases.length );
+               var $fixture,
+                       cases = [
+                               {
+                                       desc: 'Test 001',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 002',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue ',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 003',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue Ö',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+                               },
+                               {
+                                       desc: 'Test 004',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue Öy',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+                               },
+                               {
+                                       desc: 'Test 005',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 006',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue ',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 007',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue Ö',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+                               },
+                               {
+                                       desc: 'Test 008',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue Öy',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+                               },
+                               {
+                                       desc: 'Test 009: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Österreich',
+                                       expected: '<span class="highlight">Österreich</span>'
+                               },
+                               {
+                                       desc: 'Test 010: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Ö',
+                                       expected: '<span class="highlight">Ö</span>sterreich'
+                               },
+                               {
+                                       desc: 'Test 011: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Öst',
+                                       expected: '<span class="highlight">Öst</span>erreich'
+                               },
+                               {
+                                       desc: 'Test 012: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Oe',
+                                       expected: 'Österreich'
+                               },
+                               {
+                                       desc: 'Test 013: Highlighter broken on punctuation mark?',
+                                       text: 'So good. To be there',
+                                       highlight: 'good',
+                                       expected: 'So <span class="highlight">good</span>. To be there'
+                               },
+                               {
+                                       desc: 'Test 014: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: 'be',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 015: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: ' be',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 016: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: 'be ',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 017: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: ' be ',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 018: en de Highlighter broken on special character at the end?',
+                                       text: 'So good. xbß',
+                                       highlight: 'xbß',
+                                       expected: 'So good. <span class="highlight">xbß</span>'
+                               },
+                               {
+                                       desc: 'Test 019: en de Highlighter broken on special character at the end?',
+                                       text: 'So good. xbß.',
+                                       highlight: 'xbß.',
+                                       expected: 'So good. <span class="highlight">xbß.</span>'
+                               },
+                               {
+                                       desc: 'Test 020: RTL he Hebrew',
+                                       text: 'חסיד אומות העולם',
+                                       highlight: 'חסיד אומות העולם',
+                                       expected: '<span class="highlight">חסיד</span> <span class="highlight">אומות</span> <span class="highlight">העולם</span>'
+                               },
+                               {
+                                       desc: 'Test 021: RTL he Hebrew',
+                                       text: 'חסיד אומות העולם',
+                                       highlight: 'חסי',
+                                       expected: '<span class="highlight">חסי</span>ד אומות העולם'
+                               },
+                               {
+                                       desc: 'Test 022: ja Japanese',
+                                       text: '諸国民の中の正義の人',
+                                       highlight: '諸国民の中の正義の人',
+                                       expected: '<span class="highlight">諸国民の中の正義の人</span>'
+                               },
+                               {
+                                       desc: 'Test 023: ja Japanese',
+                                       text: '諸国民の中の正義の人',
+                                       highlight: '諸国',
+                                       expected: '<span class="highlight">諸国</span>民の中の正義の人'
+                               },
+                               {
+                                       desc: 'Test 024: fr French text and « french quotes » (guillemets)',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L\'oiseau est sur l’île »',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L\'oiseau</span> <span class="highlight">est</span> <span class="highlight">sur</span> <span class="highlight">l’île</span> <span class="highlight">»</span>'
+                               },
+                               {
+                                       desc: 'Test 025: fr French text and « french quotes » (guillemets)',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L\'oise',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L\'oise</span>au est sur l’île »'
+                               },
+                               {
+                                       desc: 'Test 025a: fr French text and « french quotes » (guillemets) - does it match the single strings "«" and "L" separately?',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L</span>\'oiseau est sur <span class="highlight">l</span>’île »'
+                               },
+                               {
+                                       desc: 'Test 026: ru Russian',
+                                       text: 'Праведники мира',
+                                       highlight: 'Праведники мира',
+                                       expected: '<span class="highlight">Праведники</span> <span class="highlight">мира</span>'
+                               },
+                               {
+                                       desc: 'Test 027: ru Russian',
+                                       text: 'Праведники мира',
+                                       highlight: 'Праве',
+                                       expected: '<span class="highlight">Праве</span>дники мира'
+                               },
+                               {
+                                       desc: 'Test 028 ka Georgian',
+                                       text: 'მთავარი გვერდი',
+                                       highlight: 'მთავარი გვერდი',
+                                       expected: '<span class="highlight">მთავარი</span> <span class="highlight">გვერდი</span>'
+                               },
+                               {
+                                       desc: 'Test 029 ka Georgian',
+                                       text: 'მთავარი გვერდი',
+                                       highlight: 'მთა',
+                                       expected: '<span class="highlight">მთა</span>ვარი გვერდი'
+                               },
+                               {
+                                       desc: 'Test 030 hy Armenian',
+                                       text: 'Նոնա Գափրինդաշվիլի',
+                                       highlight: 'Նոնա Գափրինդաշվիլի',
+                                       expected: '<span class="highlight">Նոնա</span> <span class="highlight">Գափրինդաշվիլի</span>'
+                               },
+                               {
+                                       desc: 'Test 031 hy Armenian',
+                                       text: 'Նոնա Գափրինդաշվիլի',
+                                       highlight: 'Նոն',
+                                       expected: '<span class="highlight">Նոն</span>ա Գափրինդաշվիլի'
+                               },
+                               {
+                                       desc: 'Test 032: th Thai',
+                                       text: 'พอล แอร์ดิช',
+                                       highlight: 'พอล แอร์ดิช',
+                                       expected: '<span class="highlight">พอล</span> <span class="highlight">แอร์ดิช</span>'
+                               },
+                               {
+                                       desc: 'Test 033: th Thai',
+                                       text: 'พอล แอร์ดิช',
+                                       highlight: 'พอ',
+                                       expected: '<span class="highlight">พอ</span>ล แอร์ดิช'
+                               },
+                               {
+                                       desc: 'Test 034: RTL ar Arabic',
+                                       text: 'بول إيردوس',
+                                       highlight: 'بول إيردوس',
+                                       expected: '<span class="highlight">بول</span> <span class="highlight">إيردوس</span>'
+                               },
+                               {
+                                       desc: 'Test 035: RTL ar Arabic',
+                                       text: 'بول إيردوس',
+                                       highlight: 'بو',
+                                       expected: '<span class="highlight">بو</span>ل إيردوس'
+                               }
+                       ];
 
                $.each( cases, function ( i, item ) {
                        $fixture = $( '<p>' ).text( item.text ).highlightText( item.highlight );
index c503fc9..a3e46ab 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $, mw ) {
        QUnit.module( 'jquery.localize', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Handle basic replacements', 4, function ( assert ) {
+       QUnit.test( 'Handle basic replacements', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'basic', 'Basic stuff' );
 
@@ -30,7 +30,7 @@
                assert.strictEqual( $lc.attr( 'placeholder' ), 'Basic stuff', 'Attribute: placeholder-msg' );
        } );
 
-       QUnit.test( 'Proper escaping', 2, function ( assert ) {
+       QUnit.test( 'Proper escaping', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'properfoo', '<proper esc="test">' );
 
@@ -50,7 +50,8 @@
                assert.strictEqual( $lc.attr( 'title' ), mw.msg( 'properfoo' ), 'Attributes are not inserted raw.' );
        } );
 
-       QUnit.test( 'Options', 7, function ( assert ) {
+       QUnit.test( 'Options', function ( assert ) {
+               var html, $lc, x, sitename = 'Wikipedia';
                mw.messages.set( {
                        'foo-lorem': 'Lorem',
                        'foo-ipsum': 'Ipsum',
@@ -60,7 +61,6 @@
                        'foo-bazz-label': 'The Bazz ($1)',
                        'foo-welcome': 'Welcome to $1! (last visit: $2)'
                } );
-               var html, $lc, x, sitename = 'Wikipedia';
 
                // Message key prefix
                html = '<div><span title-msg="lorem"><html:msg key="ipsum" /></span></div>';
                assert.strictEqual( $lc.attr( 'title' ), 'Read more about bazz at Wikipedia (last modified: 3 minutes ago)', 'Combination of options prefix, params and keys - attr' );
        } );
 
-       QUnit.test( 'Handle data text', 2, function ( assert ) {
+       QUnit.test( 'Handle data text', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'option-one', 'Item 1' );
                mw.messages.set( 'option-two', 'Item 2' );
                assert.strictEqual( $lc.eq( 1 ).text(), mw.msg( 'option-two' ), 'data-msg-text becomes text of options' );
        } );
 
-       QUnit.test( 'Handle data html', 2, function ( assert ) {
+       QUnit.test( 'Handle data html', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'html', 'behold... there is a <a>link</a> here!!' );
                html = '<div><div data-msg-html="html"></div></div>';
index 9c7660f..4e77d72 100644 (file)
@@ -11,9 +11,8 @@
        }
 
        // This test is first because if it fails, then almost all of the latter tests are meaningless.
-       QUnit.test( 'testing hooks/triggers', 4, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'testing hooks/triggers', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $content = $collapsible.find( '.mw-collapsible-content' ),
@@ -44,9 +43,8 @@
                $toggle.trigger( 'click' );
        } );
 
-       QUnit.test( 'basic operation (<div>)', 5, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'basic operation (<div>)', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $content = $collapsible.find( '.mw-collapsible-content' ),
@@ -70,9 +68,8 @@
                $toggle.trigger( 'click' );
        } );
 
-       QUnit.test( 'basic operation (<table>)', 7, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'basic operation (<table>)', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<table class="mw-collapsible">' +
                                        '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
                                        '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
                $toggle.trigger( 'click' );
        }
 
-       QUnit.test( 'basic operation (<table> with caption)', 10, function ( assert ) {
+       QUnit.test( 'basic operation (<table> with caption)', function ( assert ) {
                tableWithCaptionTest( prepareCollapsible(
                        '<table class="mw-collapsible">' +
                                '<caption>' + loremIpsum + '</caption>' +
                ), this, assert );
        } );
 
-       QUnit.test( 'basic operation (<table> with caption and <thead>)', 10, function ( assert ) {
+       QUnit.test( 'basic operation (<table> with caption and <thead>)', function ( assert ) {
                tableWithCaptionTest( prepareCollapsible(
                        '<table class="mw-collapsible">' +
                                '<caption>' + loremIpsum + '</caption>' +
                $toggle.trigger( 'click' );
        }
 
-       QUnit.test( 'basic operation (<ul>)', 7, function ( assert ) {
+       QUnit.test( 'basic operation (<ul>)', function ( assert ) {
                listTest( 'ul', this, assert );
        } );
 
-       QUnit.test( 'basic operation (<ol>)', 7, function ( assert ) {
+       QUnit.test( 'basic operation (<ol>)', function ( assert ) {
                listTest( 'ol', this, assert );
        } );
 
-       QUnit.test( 'basic operation when synchronous (options.instantHide)', 2, function ( assert ) {
+       QUnit.test( 'basic operation when synchronous (options.instantHide)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { instantHide: true }
                assert.assertTrue( $content.is( ':hidden' ), 'after collapsing: content is hidden' );
        } );
 
-       QUnit.test( 'mw-made-collapsible data added', 1, function ( assert ) {
+       QUnit.test( 'mw-made-collapsible data added', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div>' + loremIpsum + '</div>'
                        );
                assert.equal( $collapsible.data( 'mw-made-collapsible' ), true, 'mw-made-collapsible data present' );
        } );
 
-       QUnit.test( 'mw-collapsible added when missing', 1, function ( assert ) {
+       QUnit.test( 'mw-collapsible added when missing', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div>' + loremIpsum + '</div>'
                        );
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
        } );
 
-       QUnit.test( 'mw-collapsed added when missing', 1, function ( assert ) {
+       QUnit.test( 'mw-collapsed added when missing', function ( assert ) {
                var $collapsible = prepareCollapsible(
                        '<div>' + loremIpsum + '</div>',
                                { collapsed: true }
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
        } );
 
-       QUnit.test( 'initial collapse (mw-collapsed class)', 2, function ( assert ) {
+       QUnit.test( 'initial collapse (mw-collapsed class)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible mw-collapsed">' + loremIpsum + '</div>'
                        ),
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'initial collapse (options.collapsed)', 2, function ( assert ) {
+       QUnit.test( 'initial collapse (options.collapsed)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { collapsed: true }
                $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)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' +
                                        '<div class="mw-collapsible-toggle">' +
                assert.assertTrue( $content.is( ':hidden' ), 'click event on non-link inside toggle toggles content' );
        } );
 
-       QUnit.test( 'collapse/expand text (data-collapsetext, data-expandtext)', 2, function ( assert ) {
+       QUnit.test( 'collapse/expand text (data-collapsetext, data-expandtext)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
                                        loremIpsum +
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert ) {
+       QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { collapseText: 'Collapse me!', expandText: 'Expand me!' }
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'cloned collapsibles can be made collapsible again', 2, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'cloned collapsibles can be made collapsible again', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $clone = $collapsible.clone() // clone without data and events
index 029edd5..aeda516 100644 (file)
@@ -10,7 +10,7 @@
                }
        } ) );
 
-       QUnit.test( 'String functions', 7, function ( assert ) {
+       QUnit.test( 'String functions', function ( assert ) {
                assert.equal( $.trimLeft( '  foo bar  ' ), 'foo bar  ', 'trimLeft' );
                assert.equal( $.trimRight( '  foo bar  ' ), '  foo bar', 'trimRight' );
                assert.equal( $.ucFirst( 'foo' ), 'Foo', 'ucFirst' );
@@ -24,7 +24,7 @@
                assert.equal( $.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
        } );
 
-       QUnit.test( 'isDomElement', 6, function ( assert ) {
+       QUnit.test( 'isDomElement', function ( assert ) {
                assert.strictEqual( $.isDomElement( document.createElement( 'div' ) ), true,
                        'isDomElement: HTMLElement' );
                assert.strictEqual( $.isDomElement( document.createTextNode( '' ) ), true,
@@ -39,7 +39,7 @@
                        'isDomElement: Plain Object' );
        } );
 
-       QUnit.test( 'isEmpty', 7, function ( assert ) {
+       QUnit.test( 'isEmpty', function ( assert ) {
                assert.strictEqual( $.isEmpty( 'string' ), false, 'isEmpty: "string"' );
                assert.strictEqual( $.isEmpty( '0' ), true, 'isEmpty: "0"' );
                assert.strictEqual( $.isEmpty( '' ), true, 'isEmpty: ""' );
@@ -51,7 +51,7 @@
                assert.strictEqual( $.isEmpty( { length: 0 } ), true, 'isEmpty: { length: 0 }' );
        } );
 
-       QUnit.test( 'Comparison functions', 5, function ( assert ) {
+       QUnit.test( 'Comparison functions', function ( assert ) {
                assert.ok( $.compareArray( [ 0, 'a', [], [ 2, 'b' ] ], [ 0, 'a', [], [ 2, 'b' ] ] ),
                        'compareArray: Two deep arrays that are excactly the same' );
                assert.ok( !$.compareArray( [ 1 ], [ 2 ] ), 'compareArray: Two different arrays (false)' );
index 5d0ddeb..dd7666b 100644 (file)
@@ -1,8 +1,9 @@
 ( function ( $ ) {
+       var html, testElement;
 
        QUnit.module( 'jquery.placeholder', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'caches results of feature tests', 2, function ( assert ) {
+       QUnit.test( 'caches results of feature tests', function ( assert ) {
                assert.strictEqual( typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input' );
                assert.strictEqual( typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea' );
        } );
                return;
        }
 
-       var html = '<form>' +
-                       '<input id="input-type-search" type="search" placeholder="Search this site...">' +
-                       '<input id="input-type-text" type="text" placeholder="e.g. John Doe">' +
-                       '<input id="input-type-email" type="email" placeholder="e.g. address@example.ext">' +
-                       '<input id="input-type-url" type="url" placeholder="e.g. http://mathiasbynens.be/">' +
-                       '<input id="input-type-tel" type="tel" placeholder="e.g. +32 472 77 69 88">' +
-                       '<input id="input-type-password" type="password" placeholder="e.g. hunter2">' +
-                       '<textarea id="textarea" name="message" placeholder="Your message goes here"></textarea>' +
-               '</form>',
+       html = '<form>' +
+               '<input id="input-type-search" type="search" placeholder="Search this site...">' +
+               '<input id="input-type-text" type="text" placeholder="e.g. John Doe">' +
+               '<input id="input-type-email" type="email" placeholder="e.g. address@example.ext">' +
+               '<input id="input-type-url" type="url" placeholder="e.g. http://mathiasbynens.be/">' +
+               '<input id="input-type-tel" type="tel" placeholder="e.g. +32 472 77 69 88">' +
+               '<input id="input-type-password" type="password" placeholder="e.g. hunter2">' +
+               '<textarea id="textarea" name="message" placeholder="Your message goes here"></textarea>' +
+       '</form>';
        testElement = function ( $el, assert ) {
-
                var el = $el[ 0 ],
                        placeholder = el.getAttribute( 'placeholder' );
 
                $el.placeholder( placeholder );
        };
 
-       QUnit.test( 'emulates placeholder for <input type=text>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=text>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-text' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=search>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=search>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-search' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=email>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=email>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-email' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=url>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=url>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-url' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=tel>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=tel>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-tel' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=password>', 13, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=password>', function ( assert ) {
+               var $el, el, placeholder, selector = '#input-type-password';
+
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
 
-               var selector = '#input-type-password',
-                       $el = $( selector ),
-                       el = $el[ 0 ],
-                       placeholder = el.getAttribute( 'placeholder' );
+               $el = $( selector );
+               el = $el[ 0 ];
+               placeholder = el.getAttribute( 'placeholder' );
 
                assert.strictEqual( $el.placeholder(), $el, 'should be chainable' );
 
 
        } );
 
-       QUnit.test( 'emulates placeholder for <textarea></textarea>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <textarea>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#textarea' ), assert );
        } );
index 1213793..ec3539b 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.tabIndex', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'firstTabIndex', 2, function ( assert ) {
+       QUnit.test( 'firstTabIndex', function ( assert ) {
                var html, $testA, $testB;
                html = '<form>' +
                        '<input tabindex="7" />' +
@@ -17,7 +17,7 @@
                assert.strictEqual( $testB.firstTabIndex(), null, 'Return null if none available.' );
        } );
 
-       QUnit.test( 'lastTabIndex', 2, function ( assert ) {
+       QUnit.test( 'lastTabIndex', function ( assert ) {
                var html, $testA, $testB;
                html = '<form>' +
                        '<input tabindex="7" />' +
index 01ff45f..c0b1657 100644 (file)
                                                'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
                                },
                                names: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                genitive: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                abbrev: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
+                                       'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
                        };
                },
                teardown: function () {
@@ -54,7 +54,7 @@
         * @param {function($table)} callback something to do before we start the testcase
         */
        function parserTest( msg, parserId, data, callback ) {
-               QUnit.test( msg, data.length * 2, function ( assert ) {
+               QUnit.test( msg, function ( assert ) {
                        var extractedR, extractedF, parser;
 
                        if ( callback !== undefined ) {
@@ -73,7 +73,7 @@
                } );
        }
 
-       text  = [
+       text = [
                [ 'Mars', true, 'mars', 'Simple text' ],
                [ 'Mẘas', true, 'mẘas', 'Non ascii character' ],
                [ 'A sentence', true, 'a sentence', 'A sentence with space chars' ]
index dffd67a..5b973f6 100644 (file)
                                                'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
                                },
                                names: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                genitive: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                abbrev: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
+                                       'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
                        };
                },
                teardown: function () {
                $tr.appendTo( $thead );
 
                for ( i = 0; i < data.length; i++ ) {
-                       /*jshint loopfunc: true */
                        $tr = $( '<tr>' );
+                       // eslint-disable-next-line no-loop-func
                        $.each( data[ i ], function ( j, str ) {
                                var $td = $( '<td>' );
                                $td.text( str ).appendTo( $tr );
                simple,
                simpleAsc,
                function ( $table ) {
+                       var event;
                        $table.tablesorter(
                                { sortList: [ { 0: 'desc' }, { 1: 'desc' } ] }
                        );
                        $table.find( '.headerSort:eq(0)' ).click();
 
                        // Pretend to click while pressing the multi-sort key
-                       var event = $.Event( 'click' );
+                       event = $.Event( 'click' );
                        event[ $table.data( 'tablesorter' ).config.sortMultiSortKey ] = true;
                        $table.find( '.headerSort:eq(1)' ).trigger( event );
                }
        );
-       QUnit.test( 'Reset sorting making table appear unsorted', 3, function ( assert ) {
+       QUnit.test( 'Reset sorting making table appear unsorted', function ( assert ) {
                var $table = tableCreate( header, simple );
                $table.tablesorter(
                        { sortList: [
                }
        );
 
-       QUnit.test( 'Basic planet table: one unsortable column', 3, function ( assert ) {
+       QUnit.test( 'Basic planet table: one unsortable column', function ( assert ) {
                var $table = tableCreate( header, planets ),
                        $cell;
                $table.find( 'tr:eq(0) > th:eq(0)' ).addClass( 'unsortable' );
                }
        );
 
-       QUnit.test( 'Rowspan not exploded on init', 1, function ( assert ) {
+       QUnit.test( 'Rowspan not exploded on init', function ( assert ) {
                var $table = tableCreate( header, planets );
 
                // Modify the table to have a multiple-row-spanning cell:
                }
        );
 
-       QUnit.test( 'Test detection routine', 1, function ( assert ) {
+       QUnit.test( 'Test detection routine', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable">' +
        } );
 
        /** FIXME: the diff output is not very readeable. */
-       QUnit.test( 'T34047 - caption must be before thead', 1, function ( assert ) {
+       QUnit.test( 'T34047 - caption must be before thead', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable">' +
                );
        } );
 
-       QUnit.test( 'data-sort-value attribute, when available, should override sorting position', 3, function ( assert ) {
+       QUnit.test( 'data-sort-value attribute, when available, should override sorting position', function ( assert ) {
                var $table, data;
 
                // Example 1: All cells except one cell without data-sort-value,
        );
        // TODO add numbers sorting tests for T10115 with a different language
 
-       QUnit.test( 'T34888 - Tables inside a tableheader cell', 2, function ( assert ) {
+       QUnit.test( 'T34888 - Tables inside a tableheader cell', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable" id="mw-bug-32888">' +
                }
        );
 
-       QUnit.test( 'Sorting images using alt text', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'Sorting images using alt text (complex)', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text (complex)', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'Sorting images using alt text (with format autodetection)', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text (with format autodetection)', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'T40911 - The row with the largest amount of columns should receive the sort indicators', 3, function ( assert ) {
+       QUnit.test( 'T40911 - The row with the largest amount of columns should receive the sort indicators', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       QUnit.test( 'rowspans in table headers should prefer the last row when rows are equal in length', 2, function ( assert ) {
+       QUnit.test( 'rowspans in table headers should prefer the last row when rows are equal in length', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       QUnit.test( 'holes in the table headers should not throw JS errors', 2, function ( assert ) {
+       QUnit.test( 'holes in the table headers should not throw JS errors', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
        } );
 
        // T55527
-       QUnit.test( 'td cells in thead should not be taken into account for longest row calculation', 2, function ( assert ) {
+       QUnit.test( 'td cells in thead should not be taken into account for longest row calculation', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
 
        // T55211 - exploding rowspans in more complex cases
        QUnit.test(
-               'Rowspan exploding with row headers and colspans', 1, function ( assert ) {
+               'Rowspan exploding with row headers and colspans', function ( assert ) {
                        var $table = $( '<table class="sortable">' +
                                '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
                                '<tr><th>foo</th><th>bar</th></tr></thead>' +
                ]
        );
 
-       QUnit.test( 'T105731 - incomplete rows in table body', 3, function ( assert ) {
+       QUnit.test( 'T105731 - incomplete rows in table body', function ( assert ) {
                var $table, parsers;
                $table = $(
                        '<table class="sortable">' +
                );
        } );
 
-       QUnit.test( 'bug T114721 - use of expand-child class', 2, function ( assert ) {
+       QUnit.test( 'bug T114721 - use of expand-child class', function ( assert ) {
                var $table, parsers;
                $table = $(
                        '<table class="sortable">' +
index c28d3ce..f958e09 100644 (file)
@@ -1,4 +1,28 @@
 ( function ( $ ) {
+       var caretSample,
+               sig = {
+                       pre: '--~~~~'
+               },
+               bold = {
+                       pre: '\'\'\'',
+                       peri: 'Bold text',
+                       post: '\'\'\''
+               },
+               h2 = {
+                       pre: '== ',
+                       peri: 'Heading 2',
+                       post: ' ==',
+                       regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/,
+                       regexReplace: '$1==$3==$4',
+                       ownline: true
+               },
+               ulist = {
+                       pre: '* ',
+                       peri: 'Bulleted list item',
+                       post: '',
+                       ownline: true,
+                       splitlines: true
+               };
 
        QUnit.module( 'jquery.textSelection', QUnit.newMwEnvironment() );
 
                }, opt.after );
 
                QUnit.test( opt.description, function ( assert ) {
-                       var $textarea, start, end, options, text, selected,
-                               tests = 1;
-                       if ( opt.after.selected !== null ) {
-                               tests++;
-                       }
-                       QUnit.expect( tests );
+                       var $textarea, start, end, options, text, selected;
 
                        $textarea = $( '<textarea>' );
 
                } );
        }
 
-       var caretSample,
-               sig = {
-                       pre: '--~~~~'
-               },
-               bold = {
-                       pre: '\'\'\'',
-                       peri: 'Bold text',
-                       post: '\'\'\''
-               },
-               h2 = {
-                       pre: '== ',
-                       peri: 'Heading 2',
-                       post: ' ==',
-                       regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/,
-                       regexReplace: '$1==$3==$4',
-                       ownline: true
-               },
-               ulist = {
-                       pre: '* ',
-                       peri: 'Bulleted list item',
-                       post: '',
-                       ownline: true,
-                       splitlines: true
-               };
-
        encapsulateTest( {
                description: 'Adding sig to end of text',
                before: {
        } );
 
        function caretTest( options ) {
-               QUnit.test( options.description, 2, function ( assert ) {
+               QUnit.test( options.description, function ( assert ) {
                        var pos,
                                $textarea = $( '<textarea>' ).text( options.text );
 
index 1676130..69ab797 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( 'origin is included in GET requests', 1, function ( assert ) {
+       QUnit.test( 'origin is included in GET requests', function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
@@ -17,7 +17,7 @@
                return api.get( {} );
        } );
 
-       QUnit.test( 'origin is included in POST requests', 2, function ( assert ) {
+       QUnit.test( 'origin is included in POST requests', function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
index a79bff6..8ad1290 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( '.getCategoriesByPrefix()', 1, function ( assert ) {
+       QUnit.test( '.getCategoriesByPrefix()', function ( assert ) {
                this.server.respondWith( [ 200, { 'Content-Type': 'application/json' },
                        '{ "query": { "allpages": [ ' +
                                '{ "title": "Category:Food" },' +
index f83f66c..13d7dcc 100644 (file)
@@ -15,7 +15,7 @@
                                                pages: [ {
                                                        pageid: 1,
                                                        ns: 0,
-                                                       title:  'Sandbox',
+                                                       title: 'Sandbox',
                                                        revisions: [ {
                                                                timestamp: '2016-01-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
@@ -56,7 +56,7 @@
                                                pages: [ {
                                                        pageid: 4,
                                                        ns: 0,
-                                                       title:  'Async',
+                                                       title: 'Async',
                                                        revisions: [ {
                                                                timestamp: '2016-02-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
@@ -97,7 +97,7 @@
                                                pages: [ {
                                                        pageid: 3,
                                                        ns: 0,
-                                                       title:  'Param',
+                                                       title: 'Param',
                                                        revisions: [ {
                                                                timestamp: '2016-03-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
                        if ( /edit.+text=Sand/.test( req.requestBody ) ) {
                                req.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( {
                                        edit: {
-                                               'new': true,
+                                               new: true,
                                                result: 'Success',
                                                newrevid: 41,
                                                newtimestamp: '2016-04-01T12:00:00Z'
index d8b5db8..7282b3f 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( '.getMessages()', 1, function ( assert ) {
+       QUnit.test( '.getMessages()', function ( assert ) {
                this.server.respondWith( /ammessages=foo%7Cbaz/, [
                        200,
                        { 'Content-Type': 'application/json' },
index 7ed1875..854e4b1 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( 'saveOption', 2, function ( assert ) {
+       QUnit.test( 'saveOption', function ( assert ) {
                var api = new mw.Api(),
                        stub = this.sandbox.stub( mw.Api.prototype, 'saveOptions' );
 
@@ -16,7 +16,7 @@
                assert.deepEqual( stub.getCall( 0 ).args, [ { foo: 'bar' } ], '#saveOptions called correctly' );
        } );
 
-       QUnit.test( 'saveOptions without Unit Separator', 13, function ( assert ) {
+       QUnit.test( 'saveOptions without Unit Separator', function ( assert ) {
                var api = new mw.Api( { useUS: false } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
 
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
-                       switch ( request.requestBody ) {
+                       if ( $.inArray( request.requestBody, [
                                // simple
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
                                // two options
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
                                // not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&change=baz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&change=baz%3Dquux&token=%2B%5C',
                                // reset an option
-                               case 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
                                // reset an option, not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C':
-                                       assert.ok( true, 'Repond to ' + request.requestBody );
-                                       request.respond( 200, { 'Content-Type': 'application/json' },
-                                               '{ "options": "success" }' );
-                                       break;
-                               default:
-                                       assert.ok( false, 'Unexpected request: ' + request.requestBody );
+                               'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
+                       ] ) !== -1 ) {
+                               assert.ok( true, 'Repond to ' + request.requestBody );
+                               request.respond( 200, { 'Content-Type': 'application/json' },
+                                       '{ "options": "success" }' );
+                       } else {
+                               assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
 
@@ -74,7 +74,7 @@
                );
        } );
 
-       QUnit.test( 'saveOptions with Unit Separator', 14, function ( assert ) {
+       QUnit.test( 'saveOptions with Unit Separator', function ( assert ) {
                var api = new mw.Api( { useUS: true } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
 
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
-                       switch ( request.requestBody ) {
+                       if ( $.inArray( request.requestBody, [
                                // simple
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
                                // two options
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
                                // bundleable with unit separator
-                               case 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc%1Fbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc%1Fbaz%3Dquux&token=%2B%5C',
                                // not bundleable with unit separator
-                               case 'action=options&format=json&formatversion=2&optionname=baz%3Dbaz&optionvalue=quux&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&optionname=baz%3Dbaz&optionvalue=quux&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc&token=%2B%5C',
                                // reset an option
-                               case 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
                                // reset an option, not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C':
-                                       assert.ok( true, 'Repond to ' + request.requestBody );
-                                       request.respond( 200, { 'Content-Type': 'application/json' },
+                               'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
+                       ] ) !== -1 ) {
+                               assert.ok( true, 'Repond to ' + request.requestBody );
+                               request.respond( 200, { 'Content-Type': 'application/json' },
                                                '{ "options": "success" }' );
-                                       break;
-                               default:
-                                       assert.ok( false, 'Unexpected request: ' + request.requestBody );
+                       } else {
+                               assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
 
index 7d27352..74da009 100644 (file)
@@ -39,7 +39,7 @@
                ] );
 
                return new mw.Api().parse( new mw.Title( 'Earth' ) ).done( function ( html ) {
-                       assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object'  );
+                       assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object' );
                } );
        } );
 }( mediaWiki ) );
index 44d2209..e10a7fa 100644 (file)
 
                return api.postWithToken( 'testassertpost', { action: 'example', key: 'foo', assert: 'user' } )
                        // Cast error to success and vice versa
-                       .then( function ( ) {
+                       .then( function () {
                                return $.Deferred().reject( 'Unexpected success' );
                        }, function ( errorCode ) {
                                assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
                this.server.respond( [ 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' ] );
 
                return api.postWithToken( 'csrf',
-                               { action: 'example' },
-                               {
-                                       headers: {
-                                               'X-Foo': 'Bar'
-                                       }
+                       { action: 'example' },
+                       {
+                               headers: {
+                                       'X-Foo': 'Bar'
                                }
-                       )
-                       .then( function () {
-                               assert.equal( test.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
+                       }
+               )
+               .then( function () {
+                       assert.equal( test.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
 
-                               return api.postWithToken( 'csrf',
-                                       { action: 'example' },
-                                       function () {
-                                               assert.ok( false, 'This parameter cannot be a callback' );
-                                       }
-                               );
-                       } )
-                       .then( function ( data ) {
-                               assert.equal( data.example, 'quux' );
+                       return api.postWithToken( 'csrf',
+                               { action: 'example' },
+                               function () {
+                                       assert.ok( false, 'This parameter cannot be a callback' );
+                               }
+                       );
+               } )
+               .then( function ( data ) {
+                       assert.equal( data.example, 'quux' );
 
-                               assert.equal( test.server.requests.length, 2, 'Request made' );
-                       } );
+                       assert.equal( test.server.requests.length, 2, 'Request made' );
+               } );
        } );
 
        QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
                }
        } );
 
-       QUnit.test( '#abort', 3, function ( assert ) {
+       QUnit.test( '#abort', function ( assert ) {
                this.api.get( {
                        a: 1
                } );
index b1bd12b..bfaf7f2 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.api.upload', QUnit.newMwEnvironment( {} ) );
 
-       QUnit.test( 'Basic functionality', 2, function ( assert ) {
+       QUnit.test( 'Basic functionality', function ( assert ) {
                var api = new mw.Api();
                assert.ok( api.upload );
                assert.throws( function () {
@@ -9,7 +9,7 @@
                } );
        } );
 
-       QUnit.test( 'Set up iframe upload', 5, function ( assert ) {
+       QUnit.test( 'Set up iframe upload', function ( assert ) {
                var $iframe, $form, $input,
                        api = new mw.Api();
 
index 49a5b18..a5b12c9 100644 (file)
                                hidefilter4: 0,
                                hidefilter5: 0,
                                hidefilter6: 0,
-                               group3: 'all',
+                               group3: 'all'
                        },
                        'Unselected filters return all parameters falsey or \'all\'.'
                );
                                        filters: [
                                                { name: 'filter1' },
                                                { name: 'filter2' },
-                                               { name: 'filter3' },
+                                               { name: 'filter3' }
                                        ]
                                },
                                group2: {
                                        filters: [
                                                { name: 'filter4' },
                                                { name: 'filter5' },
-                                               { name: 'filter6' },
+                                               { name: 'filter6' }
                                        ]
                                }
                        },
+                       model = new mw.rcfilters.dm.FiltersViewModel(),
                        isCapsuleItemMuted = function ( filterName ) {
                                var itemModel = model.getItemByName( filterName ),
                                        groupModel = itemModel.getGroupModel();
                                filter4: false,
                                filter5: false,
                                filter6: false
-                       },
-                       model = new mw.rcfilters.dm.FiltersViewModel();
+                       };
 
                model.initializeFilters( definition );
 
                                                        conflicts: [ 'filter3' ]
                                                },
                                                {
-                                                       name: 'filter6',
+                                                       name: 'filter6'
                                                }
                                        ]
                                }
                        $.extend( true, {}, baseFullState, {
                                filter1: { selected: true },
                                filter2: { conflicted: true },
-                               filter4: { conflicted: true },
+                               filter4: { conflicted: true }
                        } ),
                        'Selecting a filter set its conflicts list as "conflicted".'
                );
                        $.extend( true, {}, baseFullState, {
                                filter1: { selected: true, conflicted: true },
                                filter2: { conflicted: true },
-                               filter4: { selected: true, conflicted: true },
+                               filter4: { selected: true, conflicted: true }
                        } ),
                        'Selecting a conflicting filter sets both sides to conflicted and selected.'
                );
index edc2716..35b6b71 100644 (file)
@@ -3,7 +3,7 @@
 
        // TODO: verify checkboxes == [ 'nsassociated', 'nsinvert' ]
 
-       QUnit.test( '"all" namespace disable checkboxes', 8, function ( assert ) {
+       QUnit.test( '"all" namespace disable checkboxes', function ( assert ) {
                var selectHtml, $env, $options,
                        rc = require( 'mediawiki.special.recentchanges' );
 
index 2388497..97c82fb 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.RegExp' );
 
-       QUnit.test( 'escape', 16, function ( assert ) {
+       QUnit.test( 'escape', function ( assert ) {
                var specials, normal;
 
                specials = [
index 31a1a28..1bc4c06 100644 (file)
@@ -1,79 +1,80 @@
 ( function ( mw, $ ) {
+       /* eslint-disable camelcase */
        var repeat = function ( input, multiplier ) {
-               return new Array( multiplier + 1 ).join( input );
-       },
-       cases = {
+                       return new Array( multiplier + 1 ).join( input );
+               },
                // See also TitleTest.php#testSecureAndSplit
-               valid: [
-                       'Sandbox',
-                       'A "B"',
-                       'A \'B\'',
-                       '.com',
-                       '~',
-                       '"',
-                       '\'',
-                       'Talk:Sandbox',
-                       'Talk:Foo:Sandbox',
-                       'File:Example.svg',
-                       'File_talk:Example.svg',
-                       'Foo/.../Sandbox',
-                       'Sandbox/...',
-                       'A~~',
-                       ':A',
-                       // Length is 256 total, but only title part matters
-                       'Category:' + repeat( 'x', 248 ),
-                       repeat( 'x', 252 )
-               ],
-               invalid: [
-                       '',
-                       ':',
-                       '__  __',
-                       '  __  ',
-                       // Bad characters forbidden regardless of wgLegalTitleChars
-                       'A [ B',
-                       'A ] B',
-                       'A { B',
-                       'A } B',
-                       'A < B',
-                       'A > B',
-                       'A | B',
-                       'A \t B',
-                       'A \n B',
-                       // URL encoding
-                       'A%20B',
-                       'A%23B',
-                       'A%2523B',
-                       // XML/HTML character entity references
-                       // Note: The ones with # are commented out as those are interpreted as fragment and
-                       // as such end up being valid.
-                       'A &eacute; B',
-                       // 'A &#233; B',
-                       // 'A &#x00E9; B',
-                       // Subject of NS_TALK does not roundtrip to NS_MAIN
-                       'Talk:File:Example.svg',
-                       // Directory navigation
-                       '.',
-                       '..',
-                       './Sandbox',
-                       '../Sandbox',
-                       'Foo/./Sandbox',
-                       'Foo/../Sandbox',
-                       'Sandbox/.',
-                       'Sandbox/..',
-                       // Tilde
-                       'A ~~~ Name',
-                       'A ~~~~ Signature',
-                       'A ~~~~~ Timestamp',
-                       repeat( 'x', 256 ),
-                       // Extension separation is a js invention, for length
-                       // purposes it is part of the title
-                       repeat( 'x', 252 ) + '.json',
-                       // Namespace prefix without actual title
-                       'Talk:',
-                       'Category: ',
-                       'Category: #bar'
-               ]
-       };
+               cases = {
+                       valid: [
+                               'Sandbox',
+                               'A "B"',
+                               'A \'B\'',
+                               '.com',
+                               '~',
+                               '"',
+                               '\'',
+                               'Talk:Sandbox',
+                               'Talk:Foo:Sandbox',
+                               'File:Example.svg',
+                               'File_talk:Example.svg',
+                               'Foo/.../Sandbox',
+                               'Sandbox/...',
+                               'A~~',
+                               ':A',
+                               // Length is 256 total, but only title part matters
+                               'Category:' + repeat( 'x', 248 ),
+                               repeat( 'x', 252 )
+                       ],
+                       invalid: [
+                               '',
+                               ':',
+                               '__  __',
+                               '  __  ',
+                               // Bad characters forbidden regardless of wgLegalTitleChars
+                               'A [ B',
+                               'A ] B',
+                               'A { B',
+                               'A } B',
+                               'A < B',
+                               'A > B',
+                               'A | B',
+                               'A \t B',
+                               'A \n B',
+                               // URL encoding
+                               'A%20B',
+                               'A%23B',
+                               'A%2523B',
+                               // XML/HTML character entity references
+                               // Note: The ones with # are commented out as those are interpreted as fragment and
+                               // as such end up being valid.
+                               'A &eacute; B',
+                               // 'A &#233; B',
+                               // 'A &#x00E9; B',
+                               // Subject of NS_TALK does not roundtrip to NS_MAIN
+                               'Talk:File:Example.svg',
+                               // Directory navigation
+                               '.',
+                               '..',
+                               './Sandbox',
+                               '../Sandbox',
+                               'Foo/./Sandbox',
+                               'Foo/../Sandbox',
+                               'Sandbox/.',
+                               'Sandbox/..',
+                               // Tilde
+                               'A ~~~ Name',
+                               'A ~~~~ Signature',
+                               'A ~~~~~ Timestamp',
+                               repeat( 'x', 256 ),
+                               // Extension separation is a js invention, for length
+                               // purposes it is part of the title
+                               repeat( 'x', 252 ) + '.json',
+                               // Namespace prefix without actual title
+                               'Talk:',
+                               'Category: ',
+                               'Category: #bar'
+                       ]
+               };
 
        QUnit.module( 'mediawiki.Title', QUnit.newMwEnvironment( {
                // mw.Title relies on these three config vars
                                // testing custom / localized namespace
                                100: 'Penguins'
                        },
-                       // jscs: disable requireCamelCaseOrUpperCaseIdentifiers
                        wgNamespaceIds: {
                                media: -2,
                                special: -1,
                                penguins: 100,
                                antarctic_waterfowl: 100
                        },
-                       // jscs: enable requireCamelCaseOrUpperCaseIdentifiers
                        wgCaseSensitiveNamespaces: []
                }
        } ) );
 
-       QUnit.test( 'constructor', cases.invalid.length, function ( assert ) {
+       QUnit.test( 'constructor', function ( assert ) {
                var i, title;
                for ( i = 0; i < cases.valid.length; i++ ) {
                        title = new mw.Title( cases.valid[ i ] );
                }
                for ( i = 0; i < cases.invalid.length; i++ ) {
-                       /*jshint loopfunc:true */
                        title = cases.invalid[ i ];
+                       // eslint-disable-next-line no-loop-func
                        assert.throws( function () {
                                return new mw.Title( title );
                        }, cases.invalid[ i ] );
                }
        } );
 
-       QUnit.test( 'newFromText', cases.valid.length + cases.invalid.length, function ( assert ) {
+       QUnit.test( 'newFromText', function ( assert ) {
                var i;
                for ( i = 0; i < cases.valid.length; i++ ) {
                        assert.equal(
                }
        } );
 
-       QUnit.test( 'makeTitle', 6, function ( assert ) {
+       QUnit.test( 'makeTitle', function ( assert ) {
                var cases, i, title, expected,
                        NS_MAIN = 0,
                        NS_TALK = 1,
                }
        } );
 
-       QUnit.test( 'Basic parsing', 21, function ( assert ) {
+       QUnit.test( 'Basic parsing', function ( assert ) {
                var title;
                title = new mw.Title( 'File:Foo_bar.JPG' );
 
                assert.equal( title.getPrefixedText(), '.foo' );
        } );
 
-       QUnit.test( 'Transformation', 12, function ( assert ) {
+       QUnit.test( 'Transformation', function ( assert ) {
                var title;
 
                title = new mw.Title( 'File:quux pif.jpg' );
                assert.equal( title.getFragment(), ' foo bar baz', 'Fragment' );
        } );
 
-       QUnit.test( 'Namespace detection and conversion', 10, function ( assert ) {
+       QUnit.test( 'Namespace detection and conversion', function ( assert ) {
                var title;
 
                title = new mw.Title( 'File:User:Example' );
                assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
        } );
 
-       QUnit.test( 'Throw error on invalid title', 1, function ( assert ) {
+       QUnit.test( 'Throw error on invalid title', function ( assert ) {
                assert.throws( function () {
                        return new mw.Title( '' );
                }, 'Throw error on empty string' );
        } );
 
-       QUnit.test( 'Case-sensivity', 5, function ( assert ) {
+       QUnit.test( 'Case-sensivity', function ( assert ) {
                var title;
 
                // Default config
                assert.equal( title.toString(), 'User:John', '$wgCapitalLinks=false: User namespace is insensitive, first-letter becomes uppercase' );
        } );
 
-       QUnit.test( 'toString / toText', 2, function ( assert ) {
+       QUnit.test( 'toString / toText', function ( assert ) {
                var title = new mw.Title( 'Some random page' );
 
                assert.equal( title.toString(), title.getPrefixedDb() );
                assert.equal( title.toText(), title.getPrefixedText() );
        } );
 
-       QUnit.test( 'getExtension', 7, function ( assert ) {
+       QUnit.test( 'getExtension', function ( assert ) {
                function extTest( pagename, ext, description ) {
                        var title = new mw.Title( pagename );
                        assert.equal( title.getExtension(), ext, description || pagename );
                // extTest( '.NET', null, 'Leading dot is (or is not?) an extension' );
        } );
 
-       QUnit.test( 'exists', 3, function ( assert ) {
+       QUnit.test( 'exists', function ( assert ) {
                var title;
 
                // Empty registry, checks default to null
 
        } );
 
-       QUnit.test( 'getUrl', 4, function ( assert ) {
+       QUnit.test( 'getUrl', function ( assert ) {
                var title;
                mw.config.set( {
                        wgScript: '/w/index.php',
                assert.equal( title.getUrl( { meme: true } ), '/w/index.php?title=User_talk:John_Cena&meme=true#And_His_Name_Is', 'title with fragment and query parameter' );
        } );
 
-       QUnit.test( 'newFromImg', 44, function ( assert ) {
+       QUnit.test( 'newFromImg', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'getRelativeText', 5, function ( assert ) {
+       QUnit.test( 'getRelativeText', function ( assert ) {
                var i, thisCase, title,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'normalizeExtension', 5, function ( assert ) {
+       QUnit.test( 'normalizeExtension', function ( assert ) {
                var extension, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'newFromUserInput', 12, function ( assert ) {
+       QUnit.test( 'newFromUserInput', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'newFromFileName', 54, function ( assert ) {
+       QUnit.test( 'newFromFileName', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
index ef0d5e5..e56c933 100644 (file)
@@ -11,7 +11,7 @@
        } ) );
 
        $.each( [ true, false ], function ( i, strictMode ) {
-               QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', 2, function ( assert ) {
+               QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', function ( assert ) {
                        var uriString, uri;
                        uriString = 'http://www.ietf.org/rfc/rfc2396.txt';
                        uri = new mw.Uri( uriString, {
@@ -59,7 +59,7 @@
                } );
        } );
 
-       QUnit.test( 'Constructor( String[, Object ] )', 11, function ( assert ) {
+       QUnit.test( 'Constructor( String[, Object ] )', function ( assert ) {
                var uri;
 
                uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
                } );
                assert.equal( uri.toString(), 'http://example.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
 
-               /*jshint -W001 */
                uri = new mw.Uri( 'http://example.com/index.php?key=key&hasOwnProperty=hasOwnProperty&constructor=constructor&watch=watch' );
                assert.deepEqual(
                        uri.query,
                        },
                        'Keys in query strings support names of Object prototypes (bug T114344)'
                );
-               /*jshint +W001 */
        } );
 
-       QUnit.test( 'Constructor( Object )', 3, function ( assert ) {
+       QUnit.test( 'Constructor( Object )', function ( assert ) {
                var uri = new mw.Uri( {
                        protocol: 'http',
                        host: 'www.foo.local',
                );
        } );
 
-       QUnit.test( 'Constructor( empty[, Object ] )', 5, function ( assert ) {
+       QUnit.test( 'Constructor( empty[, Object ] )', function ( assert ) {
                var testuri, MyUri, uri;
 
                testuri = 'http://example.org/w/index.php?a=1&a=2';
                assert.deepEqual( uri.query, { a: '2' }, 'null, with options' );
        } );
 
-       QUnit.test( 'Properties', 8, function ( assert ) {
+       QUnit.test( 'Properties', function ( assert ) {
                var uriBase, uri;
 
                uriBase = new mw.Uri( 'http://en.wiki.local/w/api.php' );
                assert.ok( uri.toString().indexOf( 'pif=paf' ) >= 0, 'extend query arguments' );
        } );
 
-       QUnit.test( '.getQueryString()', 2, function ( assert ) {
+       QUnit.test( '.getQueryString()', function ( assert ) {
                var uri = new mw.Uri( 'http://search.example.com/?q=uri' );
 
                assert.deepEqual(
 
        } );
 
-       QUnit.test( '.clone()', 6, function ( assert ) {
+       QUnit.test( '.clone()', function ( assert ) {
                var original, clone;
 
                original = new mw.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
                );
        } );
 
-       QUnit.test( '.toString() after query manipulation', 8, function ( assert ) {
+       QUnit.test( '.toString() after query manipulation', function ( assert ) {
                var uri;
 
                uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
                assert.equal( uri.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' );
        } );
 
-       QUnit.test( 'Variable defaultUri', 2, function ( assert ) {
+       QUnit.test( 'Variable defaultUri', function ( assert ) {
                var uri,
                        href = 'http://example.org/w/index.php#here',
                        UriClass = mw.UriRelative( function () {
                );
        } );
 
-       QUnit.test( 'Advanced URL', 11, function ( assert ) {
+       QUnit.test( 'Advanced URL', function ( assert ) {
                var uri, queryString, relativePath;
 
                uri = new mw.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
                assert.ok( relativePath.indexOf( uri.fragment ) >= 0, 'fragment in relative path' );
        } );
 
-       QUnit.test( 'Parse a uri with an @ symbol in the path and query', 1, function ( assert ) {
+       QUnit.test( 'Parse a uri with an @ symbol in the path and query', function ( assert ) {
                var uri = new mw.Uri( 'http://www.example.com/test@test?x=@uri&y@=uri&z@=@' );
 
                assert.deepEqual(
                );
        } );
 
-       QUnit.test( 'Handle protocol-relative URLs', 5, function ( assert ) {
+       QUnit.test( 'Handle protocol-relative URLs', function ( assert ) {
                var UriRel, uri;
 
                UriRel = mw.UriRelative( 'glork://en.wiki.local/foo.php' );
                assert.equal( uri.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in strict mode' );
        } );
 
-       QUnit.test( 'T37658', 2, function ( assert ) {
+       QUnit.test( 'T37658', function ( assert ) {
                var testProtocol, testServer, testPort, testPath, UriClass, uri, href;
 
                testProtocol = 'https://';
index 399db91..4170897 100644 (file)
@@ -1,6 +1,4 @@
 ( function ( mw, $ ) {
-       QUnit.module( 'mediawiki.cldr', QUnit.newMwEnvironment() );
-
        var pluralTestcases = {
                /*
                 * Sample:
                ]
        };
 
+       QUnit.module( 'mediawiki.cldr', QUnit.newMwEnvironment() );
+
        function pluralTest( langCode, tests ) {
-               QUnit.test( 'Plural Test for ' + langCode, tests.length, function ( assert ) {
-                       for ( var i = 0; i < tests.length; i++ ) {
+               QUnit.test( 'Plural Test for ' + langCode, function ( assert ) {
+                       var i;
+                       for ( i = 0; i < tests.length; i++ ) {
                                assert.equal(
                                        mw.language.convertPlural( tests[ i ][ 0 ], tests[ i ][ 1 ] ),
                                        tests[ i ][ 2 ],
index 7a13f0f..59bf737 100644 (file)
@@ -20,7 +20,7 @@
                }
        } ) );
 
-       QUnit.test( 'set( key, value )', 7, function ( assert ) {
+       QUnit.test( 'set( key, value )', function ( assert ) {
                var call;
 
                // Simple case
@@ -53,7 +53,7 @@
                assert.strictEqual( call[ 1 ], '0', '0 is value' );
        } );
 
-       QUnit.test( 'set( key, value, expires )', 6, function ( assert ) {
+       QUnit.test( 'set( key, value, expires )', function ( assert ) {
                var date, options;
 
                date = new Date();
@@ -91,7 +91,7 @@
                assert.strictEqual( options.expires, date, 'custom expiration (with wgCookieExpiration=0)' );
        } );
 
-       QUnit.test( 'set( key, value, options )', 4, function ( assert ) {
+       QUnit.test( 'set( key, value, options )', function ( assert ) {
                var date, call;
 
                mw.cookie.set( 'foo', 'bar', {
                }, 'Options (incl. expires)' );
        } );
 
-       QUnit.test( 'get( key ) - no values', 6, function ( assert ) {
+       QUnit.test( 'get( key ) - no values', function ( assert ) {
                var key, value;
 
                mw.cookie.get( 'foo' );
                assert.strictEqual( value, 'bar', 'Custom default value' );
        } );
 
-       QUnit.test( 'get( key ) - with value', 1, function ( assert ) {
+       QUnit.test( 'get( key ) - with value', function ( assert ) {
                var value;
 
                $.cookie.returns( 'bar' );
                assert.strictEqual( value, 'bar', 'Return value of cookie' );
        } );
 
-       QUnit.test( 'get( key, prefix )', 1, function ( assert ) {
+       QUnit.test( 'get( key, prefix )', function ( assert ) {
                var key;
 
                mw.cookie.get( 'foo', 'bar' );
index 587c893..46d7837 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $, mw ) {
        QUnit.module( 'mediawiki.errorLogger', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'installGlobalHandler', 7, function ( assert ) {
+       QUnit.test( 'installGlobalHandler', function ( assert ) {
                var w = {},
                        errorMessage = 'Foo',
                        errorUrl = 'http://example.com',
@@ -24,7 +24,7 @@
                w.onerror( errorMessage, errorUrl, errorLine, errorColumn, errorObject );
                sinon.assert.calledWithExactly( mw.track, 'global.error',
                        sinon.match( { errorMessage: errorMessage, url: errorUrl, lineNumber: errorLine,
-                       columnNumber: errorColumn, errorObject: errorObject } ) );
+                               columnNumber: errorColumn, errorObject: errorObject } ) );
 
                w = { onerror: oldHandler };
 
index 774b205..177c358 100644 (file)
@@ -17,7 +17,7 @@
 
        QUnit.module( 'mediawiki.experiments' );
 
-       QUnit.test( 'getBucket( experiment, token )', 4, function ( assert ) {
+       QUnit.test( 'getBucket( experiment, token )', function ( assert ) {
                var experiment = createExperiment(),
                        token = '123457890';
 
index b4028ec..16f8cf3 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw ) {
        QUnit.module( 'mediawiki.html' );
 
-       QUnit.test( 'escape', 2, function ( assert ) {
+       QUnit.test( 'escape', function ( assert ) {
                assert.throws(
                        function () {
                                mw.html.escape();
@@ -17,7 +17,7 @@
                );
        } );
 
-       QUnit.test( 'element()', 1, function ( assert ) {
+       QUnit.test( 'element()', function ( assert ) {
                assert.equal(
                        mw.html.element(),
                        '<undefined/>',
                );
        } );
 
-       QUnit.test( 'element( tagName )', 1, function ( assert ) {
+       QUnit.test( 'element( tagName )', function ( assert ) {
                assert.equal( mw.html.element( 'div' ), '<div/>', 'DIV' );
        } );
 
-       QUnit.test( 'element( tagName, attrs )', 2, function ( assert ) {
+       QUnit.test( 'element( tagName, attrs )', function ( assert ) {
                assert.equal( mw.html.element( 'div', {} ), '<div/>', 'DIV' );
 
                assert.equal(
@@ -43,7 +43,7 @@
                );
        } );
 
-       QUnit.test( 'element( tagName, attrs, content )', 8, function ( assert ) {
+       QUnit.test( 'element( tagName, attrs, content )', function ( assert ) {
 
                assert.equal( mw.html.element( 'div', {}, '' ), '<div></div>', 'DIV with empty attributes and content' );
 
index f848f3e..3b549bd 100644 (file)
@@ -1,4 +1,5 @@
 ( function ( mw, $ ) {
+       /* eslint-disable camelcase */
        var formatText, formatParse, formatnumTests, specialCharactersPageName, expectedListUsers,
                expectedListUsersSitename, expectedLinkPagenamee, expectedEntrypoints,
                mwLanguageCache = {},
@@ -45,7 +46,6 @@
                },
                config: {
                        wgArticlePath: '/wiki/$1',
-                       // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                        wgNamespaceIds: {
                                template: 10,
                                template_talk: 11,
@@ -53,7 +53,6 @@
                                szablon: 10,
                                dyskusja_szablonu: 11
                        },
-                       // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                        wgFormattedNamespaces: {
                                // Localised
                                10: 'Szablon',
         *  that may be asynchronous. Invoke the callback parameter when done.
         */
        function process( tasks ) {
-               /*jshint latedef:false */
                function abort() {
                        tasks.splice( 0, tasks.length );
+                       // eslint-disable-next-line no-use-before-define
                        next();
                }
                function next() {
+                       var task;
                        if ( !tasks ) {
                                // This happens if after the process is completed, one of our callbacks is
                                // invoked. This can happen if a test timed out but the process was still
                                // running. In that case, ignore it. Don't invoke complete() a second time.
                                return;
                        }
-                       var task = tasks.shift();
+                       task = tasks.shift();
                        if ( task ) {
                                task( next, abort );
                        } else {
                next();
        }
 
-       QUnit.test( 'Replace', 15, function ( assert ) {
+       QUnit.test( 'Replace', function ( assert ) {
                mw.messages.set( 'simple', 'Foo $1 baz $2' );
 
                assert.equal( formatParse( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
                );
        } );
 
-       QUnit.test( 'Plural', 9, function ( assert ) {
+       QUnit.test( 'Plural', function ( assert ) {
                assert.equal( formatParse( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
                assert.equal( formatParse( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
                assert.equal( formatParse( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
                assert.equal( formatParse( 'plural-empty-explicit-form', 2 ), 'There is me and other people.' );
        } );
 
-       QUnit.test( 'Gender', 15, function ( assert ) {
+       QUnit.test( 'Gender', function ( assert ) {
                var originalGender = mw.user.options.get( 'gender' );
 
                // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg
                mw.user.options.set( 'gender', originalGender );
        } );
 
-       QUnit.test( 'Case changing', 8, function ( assert ) {
+       QUnit.test( 'Case changing', function ( assert ) {
                mw.messages.set( 'to-lowercase', '{{lc:thIS hAS MEsSed uP CapItaliZatiON}}' );
                assert.equal( formatParse( 'to-lowercase' ), 'this has messed up capitalization', 'To lowercase' );
 
                assert.equal( formatParse( 'all-caps-except-first' ), 'tHIS HAS MESSED UP CAPITALIZATION', 'To opposite sentence case' );
        } );
 
-       QUnit.test( 'Grammar', 2, function ( assert ) {
+       QUnit.test( 'Grammar', function ( assert ) {
                assert.equal( formatParse( 'grammar-msg' ), 'Przeszukaj Wiki', 'Grammar Test with sitename' );
 
                mw.messages.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' );
                assert.equal( formatParse( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ', 'Grammar Test with wrong grammar template syntax' );
        } );
 
-       QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
+       QUnit.test( 'Match PHP parser', function ( assert ) {
+               var tasks;
                mw.messages.set( mw.libs.phpParserData.messages );
-               var tasks = $.map( mw.libs.phpParserData.tests, function ( test ) {
+               tasks = $.map( mw.libs.phpParserData.tests, function ( test ) {
                        var done = assert.async();
                        return function ( next, abort ) {
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
+                                               var parser;
                                                mw.config.set( 'wgUserLanguage', test.lang );
-                                               var parser = new mw.jqueryMsg.parser( { language: langClass } );
+                                               // eslint-disable-next-line new-cap
+                                               parser = new mw.jqueryMsg.parser( { language: langClass } );
                                                assert.equal(
                                                        parser.parse( test.key, test.args ).html(),
                                                        test.result,
                process( tasks );
        } );
 
-       QUnit.test( 'Links', 15, function ( assert ) {
+       QUnit.test( 'Links', function ( assert ) {
                var testCases,
                        expectedDisambiguationsText,
                        expectedMultipleBars,
                } );
        } );
 
-       QUnit.test( 'Replacements in links', 14, function ( assert ) {
+       QUnit.test( 'Replacements in links', function ( assert ) {
                var testCases = [
                        [
                                'extlink-param-href-full',
        } );
 
        // Tests that {{-transformation vs. general parsing are done as requested
-       QUnit.test( 'Curly brace transformation', 16, function ( assert ) {
+       QUnit.test( 'Curly brace transformation', function ( assert ) {
                var oldUserLang = mw.config.get( 'wgUserLanguage' );
 
                assertBothModes( assert, [ 'gender-msg', 'Bob', 'male' ], 'Bob: blue', 'gender is resolved' );
                mw.config.set( 'wgUserLanguage', oldUserLang );
        } );
 
-       QUnit.test( 'Int', 4, function ( assert ) {
+       QUnit.test( 'Int', function ( assert ) {
                var newarticletextSource = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the [[{{Int:Foobar}}|foobar]] for more info). If you are here by mistake, click your browser\'s back button.',
                        expectedNewarticletext,
                        helpPageTitle = 'Help:Foobar';
                );
        } );
 
-       QUnit.test( 'Ns', 4, function ( assert ) {
+       QUnit.test( 'Ns', function ( assert ) {
                mw.messages.set( 'ns-template-talk', '{{ns:Template talk}}' );
                assert.equal(
                        formatParse( 'ns-template-talk' ),
 
        // Tests that getMessageFunction is used for non-plain messages with curly braces or
        // square brackets, but not otherwise.
-       QUnit.test( 'mw.Message.prototype.parser monkey-patch', 22, function ( assert ) {
+       QUnit.test( 'mw.Message.prototype.parser monkey-patch', function ( assert ) {
                var oldGMF, outerCalled, innerCalled;
 
                mw.messages.set( {
                }
        ];
 
-       QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
+       QUnit.test( 'formatnum', function ( assert ) {
+               var queue;
                mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
                mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
-               var queue = $.map( formatnumTests, function ( test ) {
+               queue = $.map( formatnumTests, function ( test ) {
                        var done = assert.async();
                        return function ( next, abort ) {
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
+                                               var parser;
                                                mw.config.set( 'wgUserLanguage', test.lang );
-                                               var parser = new mw.jqueryMsg.parser( { language: langClass } );
+                                               // eslint-disable-next-line new-cap
+                                               parser = new mw.jqueryMsg.parser( { language: langClass } );
                                                assert.equal(
                                                        parser.parse( test.integer ? 'formatnum-msg-int' : 'formatnum-msg',
                                                                [ test.number ] ).html(),
        } );
 
        // HTML in wikitext
-       QUnit.test( 'HTML', 33, function ( assert ) {
+       QUnit.test( 'HTML', function ( assert ) {
                mw.messages.set( 'jquerymsg-italics-msg', '<i>Very</i> important' );
 
                assertBothModes( assert, [ 'jquerymsg-italics-msg' ], mw.messages.get( 'jquerymsg-italics-msg' ), 'Simple italics unchanged' );
                );
        } );
 
-       QUnit.test( 'Nowiki', 3, function ( assert ) {
+       QUnit.test( 'Nowiki', function ( assert ) {
                mw.messages.set( 'jquerymsg-nowiki-link', 'Foo <nowiki>[[bar]]</nowiki> baz.' );
                assert.equal(
                        formatParse( 'jquerymsg-nowiki-link' ),
                );
        } );
 
-       QUnit.test( 'Behavior in case of invalid wikitext', 3, function ( assert ) {
+       QUnit.test( 'Behavior in case of invalid wikitext', function ( assert ) {
+               var logSpy;
                mw.messages.set( 'invalid-wikitext', '<b>{{FAIL}}</b>' );
 
                this.suppressWarnings();
-               var logSpy = this.sandbox.spy( mw.log, 'warn' );
+               logSpy = this.sandbox.spy( mw.log, 'warn' );
 
                assert.equal(
                        formatParse( 'invalid-wikitext' ),
                assert.equal( logSpy.callCount, 2, 'mw.log.warn calls' );
        } );
 
-       QUnit.test( 'Integration', 5, function ( assert ) {
+       QUnit.test( 'Integration', function ( assert ) {
                var expected, logSpy, msg;
 
                expected = '<b><a title="Bold" href="/wiki/Bold">Bold</a>!</b>';
index 34fe9bf..b0b2e7a 100644 (file)
@@ -5,7 +5,7 @@
 ( function ( $ ) {
        QUnit.module( 'mediawiki.jscompat', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Variable with Unicode letter in name', 3, function ( assert ) {
+       QUnit.test( 'Variable with Unicode letter in name', function ( assert ) {
                var orig, ŝablono;
 
                orig = 'some token';
@@ -44,7 +44,6 @@
                        expected, $textarea;
 
                maxn = 4;
-               QUnit.expect( maxn * 2 );
 
                function repeat( str, n ) {
                        var out;
index 2171f34..b965079 100644 (file)
@@ -1,6 +1,8 @@
 ( function ( mw, $ ) {
        'use strict';
 
+       var grammarTests;
+
        QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment( {
                setup: function () {
                        this.liveLangData = mw.language.data;
@@ -17,7 +19,7 @@
                }
        } ) );
 
-       QUnit.test( 'mw.language getData and setData', 3, function ( assert ) {
+       QUnit.test( 'mw.language getData and setData', function ( assert ) {
                mw.language.setData( 'en', 'testkey', 'testvalue' );
                assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
                assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
@@ -25,7 +27,7 @@
                assert.equal( mw.language.getData( 'en-US', 'testkey' ), 'testvalue', 'Case insensitive test for mw.language' );
        } );
 
-       QUnit.test( 'mw.language.commafy test', 9, function ( assert ) {
+       QUnit.test( 'mw.language.commafy test', function ( assert ) {
                mw.language.setData( 'en', 'digitGroupingPattern', null );
                mw.language.setData( 'en', 'digitTransformTable', null );
                mw.language.setData( 'en', 'separatorTransformTable', null );
                assert.equal( mw.language.commafy( 123456789.567, '###,###,#0.00' ), '1,234,567,89.56', 'Decimal part as group of 3 and last one 2' );
        } );
 
-       QUnit.test( 'mw.language.convertNumber', 2, function ( assert ) {
+       QUnit.test( 'mw.language.convertNumber', function ( assert ) {
                mw.language.setData( 'en', 'digitGroupingPattern', null );
                mw.language.setData( 'en', 'digitTransformTable', null );
                mw.language.setData( 'en', 'separatorTransformTable', { ',': '.', '.': ',' } );
                mw.config.set( 'wgUserLanguage', 'en' );
+               mw.config.set( 'wgTranslateNumerals', true );
 
                assert.equal( mw.language.convertNumber( 1800 ), '1.800', 'formatting' );
                assert.equal( mw.language.convertNumber( '1.800', true ), '1800', 'unformatting' );
        } );
 
+       QUnit.test( 'mw.language.convertNumber - digitTransformTable', function ( assert ) {
+               mw.config.set( 'wgUserLanguage', 'hi' );
+               mw.config.set( 'wgTranslateNumerals', true );
+               mw.language.setData( 'hi', 'digitGroupingPattern', null );
+               mw.language.setData( 'hi', 'separatorTransformTable', { ',': '.', '.': ',' } );
+
+               // Example from Hindi (MessagesHi.php)
+               mw.language.setData( 'hi', 'digitTransformTable', {
+                       0: '०',
+                       1: '१',
+                       2: '२'
+               } );
+
+               assert.equal( mw.language.convertNumber( 1200 ), '१.२००', 'format' );
+               assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform' );
+               assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain' );
+
+               mw.config.set( 'wgTranslateNumerals', false );
+
+               assert.equal( mw.language.convertNumber( 1200 ), '1.200', 'format (digit transform disabled)' );
+               assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform (when disabled)' );
+               assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain (digit transform disabled)' );
+       } );
+
        function grammarTest( langCode, test ) {
                // The test works only if the content language is opt.language
                // because it requires [lang].js to be loaded.
                QUnit.test( 'Grammar test for lang=' + langCode, function ( assert ) {
-                       QUnit.expect( test.length );
-
-                       for ( var i = 0; i < test.length; i++ ) {
+                       var i;
+                       for ( i = 0; i < test.length; i++ ) {
                                assert.equal(
                                        mw.language.convertGrammar( test[ i ].word, test[ i ].grammarForm ),
                                        test[ i ].expected,
@@ -70,7 +96,7 @@
        }
 
        // These tests run only for the current UI language.
-       var grammarTests = {
+       grammarTests = {
                bs: [
                        {
                                word: 'word',
                }
        } );
 
-       QUnit.test( 'List to text test', 4, function ( assert ) {
+       QUnit.test( 'List to text test', function ( assert ) {
                assert.equal( mw.language.listToText( [] ), '', 'Blank list' );
                assert.equal( mw.language.listToText( [ 'a' ] ), 'a', 'Single item' );
                assert.equal( mw.language.listToText( [ 'a', 'b' ] ), 'a and b', 'Two items' );
index fcf80bd..6f9af76 100644 (file)
 
                function isCssImportApplied() {
                        // Trigger reflow, repaint, redraw, whatever (cross-browser)
-                       var x = $element.css( 'height' );
-                       x = el.innerHTML;
+                       $element.css( 'height' );
+                       el.innerHTML;
                        el.className = el.className;
-                       x = document.documentElement.clientHeight;
+                       document.documentElement.clientHeight;
 
                        return $element.css( prop ) === val;
                }
@@ -75,7 +75,7 @@
                );
        }
 
-       QUnit.test( 'Basic', 2, function ( assert ) {
+       QUnit.test( 'Basic', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
@@ -94,7 +94,7 @@
                } );
        } );
 
-       QUnit.test( 'Object method as module name', 2, function ( assert ) {
+       QUnit.test( 'Object method as module name', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
                } );
        } );
 
-       QUnit.test( '.using( .. ) Promise', 2, function ( assert ) {
+       QUnit.test( '.using( .. ) Promise', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
                ).always( done );
        } );
 
-       QUnit.test( '.load() - Error: Unregistered (ignored)', 0, function ( assert ) {
+       QUnit.test( '.load() - Error: Unregistered (ignored)', function ( assert ) {
+               assert.expect( 0 );
                mw.loader.load( 'test.using.unreg2' );
        } );
 
-       QUnit.test( '.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
+       QUnit.test( '.implement( styles={ "css": [text, ..] } )', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
                return mw.loader.using( 'test.implement.a' );
        } );
 
-       QUnit.test( '.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
+       QUnit.test( '.implement( styles={ "url": { <media>: [url, ..] } } )', function ( assert ) {
                var $element1 = $( '<div class="mw-test-implement-b1"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-b2"></div>' ).appendTo( '#qunit-fixture' ),
                        $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' ),
        } );
 
        // Backwards compatibility
-       QUnit.test( '.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
+       QUnit.test( '.implement( styles={ <media>: text } ) (back-compat)', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-c"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
        } );
 
        // Backwards compatibility
-       QUnit.test( '.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
+       QUnit.test( '.implement( styles={ <media>: [url, ..] } ) (back-compat)', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-d"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' ),
                        done = assert.async();
        } );
 
        // @import (T33676)
-       QUnit.test( '.implement( styles has @import )', 7, function ( assert ) {
+       QUnit.test( '.implement( styles has @import )', function ( assert ) {
                var isJsExecuted, $element,
                        done = assert.async();
 
                } );
        } );
 
-       QUnit.test( '.implement( dependency with styles )', 4, function ( assert ) {
+       QUnit.test( '.implement( dependency with styles )', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-e"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-e2"></div>' ).appendTo( '#qunit-fixture' );
 
                return mw.loader.using( 'test.implement.e' );
        } );
 
-       QUnit.test( '.implement( only scripts )', 1, function ( assert ) {
+       QUnit.test( '.implement( only scripts )', function ( assert ) {
                mw.loader.implement( 'test.onlyscripts', function () {} );
                assert.strictEqual( mw.loader.getState( 'test.onlyscripts' ), 'ready' );
        } );
 
-       QUnit.test( '.implement( only messages )', 2, function ( assert ) {
+       QUnit.test( '.implement( only messages )', function ( assert ) {
                assert.assertFalse( mw.messages.exists( 'T31107' ), 'Verify that the test message doesn\'t exist yet' );
 
                mw.loader.implement( 'test.implement.msgs', [], {}, { T31107: 'loaded' } );
                } );
        } );
 
-       QUnit.test( '.implement( empty )', 1, function ( assert ) {
+       QUnit.test( '.implement( empty )', function ( assert ) {
                mw.loader.implement( 'test.empty' );
                assert.strictEqual( mw.loader.getState( 'test.empty' ), 'ready' );
        } );
 
-       QUnit.test( 'Broken indirect dependency', 4, function ( assert ) {
+       QUnit.test( 'Broken indirect dependency', function ( assert ) {
                // don't emit an error event
                this.sandbox.stub( mw, 'track' );
 
                assert.strictEqual( mw.track.callCount, 1 );
        } );
 
-       QUnit.test( 'Out-of-order implementation', 9, function ( assert ) {
+       QUnit.test( 'Out-of-order implementation', function ( assert ) {
                mw.loader.register( [
                        [ 'test.module4', '0' ],
                        [ 'test.module5', '0', [ 'test.module4' ] ],
                assert.strictEqual( mw.loader.getState( 'test.module6' ), 'ready', 'Expected "ready" state for test.module6' );
        } );
 
-       QUnit.test( 'Missing dependency', 13, function ( assert ) {
+       QUnit.test( 'Missing dependency', function ( assert ) {
                mw.loader.register( [
                        [ 'test.module7', '0' ],
                        [ 'test.module8', '0', [ 'test.module7' ] ],
                );
        } );
 
-       QUnit.test( 'Dependency handling', 5, function ( assert ) {
+       QUnit.test( 'Dependency handling', function ( assert ) {
                var done = assert.async();
                mw.loader.register( [
                        // [module, version, dependencies, group, source]
                );
        } );
 
-       QUnit.test( 'Skip-function handling', 5, function ( assert ) {
+       QUnit.test( 'Skip-function handling', function ( assert ) {
                mw.loader.register( [
                        // [module, version, dependencies, group, source, skip]
                        [ 'testSkipped', '1', [], null, 'testloader', 'return true;' ],
                );
        } );
 
-       QUnit.asyncTest( '.load( "//protocol-relative" ) - T32825', 2, function ( assert ) {
+       QUnit.asyncTest( '.load( "//protocol-relative" ) - T32825', function ( assert ) {
                // This bug was actually already fixed in 1.18 and later when discovered in 1.17.
                // Test is for regressions!
 
                mw.loader.load( target );
        } );
 
-       QUnit.asyncTest( '.load( "/absolute-path" )', 2, function ( assert ) {
+       QUnit.asyncTest( '.load( "/absolute-path" )', function ( assert ) {
                // Forge a URL to the test callback script
                var target = QUnit.fixurl(
                        mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/qunitOkCall.js'
                } );
        } );
 
-       QUnit.test( 'Executing race - T112232', 2, function ( assert ) {
+       QUnit.test( 'Executing race - T112232', function ( assert ) {
                var done = false;
 
                // The red herring schedules its CSS buffer first. In T112232, a bug in the
                        } );
        } );
 
-       QUnit.test( 'require()', 6, function ( assert ) {
+       QUnit.test( 'require()', function ( assert ) {
                mw.loader.register( [
                        [ 'test.require1', '0' ],
                        [ 'test.require2', '0' ],
index b3c4bee..923f97d 100644 (file)
@@ -7,7 +7,7 @@
                }
        } ) );
 
-       QUnit.test( 'register', 2, function ( assert ) {
+       QUnit.test( 'register', function ( assert ) {
                var testMessagePosterConstructor = function () {};
 
                mw.messagePoster.factory.register( TEST_MODEL, testMessagePosterConstructor );
index 38ae5e4..cb583e7 100644 (file)
@@ -10,7 +10,7 @@
                }
        } );
 
-       QUnit.test( 'render', 2, function ( assert ) {
+       QUnit.test( 'render', function ( assert ) {
                var html, htmlPartial, data, partials,
                        template = mw.template.get( 'stub', 'test_greeting.mustache' ),
                        partial = mw.template.get( 'stub', 'test_greeting_suffix.mustache' );
index 86fd828..a282325 100644 (file)
@@ -24,7 +24,7 @@
                }
        } );
 
-       QUnit.test( 'add', 1, function ( assert ) {
+       QUnit.test( 'add', function ( assert ) {
                assert.throws(
                        function () {
                                mw.template.add( 'module', 'test_templates_foo', 'hello' );
@@ -33,7 +33,7 @@
                );
        } );
 
-       QUnit.test( 'compile', 1, function ( assert ) {
+       QUnit.test( 'compile', function ( assert ) {
                assert.throws(
                        function () {
                                mw.template.compile( '{{foo}}', 'rainbow' );
@@ -42,7 +42,7 @@
                );
        } );
 
-       QUnit.test( 'get', 4, function ( assert ) {
+       QUnit.test( 'get', function ( assert ) {
                assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.xyz' ), 'xyz compiler' );
                assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.abc' ), 'abc default compiler' );
                assert.throws(
index 65b7263..d3e73ae 100644 (file)
@@ -31,7 +31,7 @@
                }
        } ) );
 
-       QUnit.test( 'Initial check', 8, function ( assert ) {
+       QUnit.test( 'Initial check', function ( assert ) {
                assert.ok( window.jQuery, 'jQuery defined' );
                assert.ok( window.$, '$ defined' );
                assert.strictEqual( window.$, window.jQuery, '$ alias to jQuery' );
@@ -51,7 +51,7 @@
                this.restoreWarnings();
        } );
 
-       QUnit.test( 'mw.format', 2, function ( assert ) {
+       QUnit.test( 'mw.format', function ( assert ) {
                assert.equal(
                        mw.format( 'Format $1 $2', 'foo', 'bar' ),
                        'Format foo bar',
 
        } );
 
-       QUnit.test( 'mw.msg', 14, function ( assert ) {
+       QUnit.test( 'mw.msg', function ( assert ) {
                assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
                assert.equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'Gets message with default options (existing message)' );
                assert.equal( mw.msg( 'goodbye' ), '⧼goodbye⧽', 'Gets message with default options (nonexistent message)' );
                assert.equal( mw.msg( 'int-msg' ), 'Some Other Message', 'int is resolved' );
        } );
 
-       QUnit.test( 'mw.hook', 13, function ( assert ) {
+       QUnit.test( 'mw.hook', function ( assert ) {
                var hook, add, fire, chars, callback;
 
                mw.hook( 'test.hook.unfired' ).add( function () {
index 89eb45f..297f0fd 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.asyncTest( 'toggleToc', 4, function ( assert ) {
+       QUnit.asyncTest( 'toggleToc', function ( assert ) {
                var tocHtml, $toggleLink, $tocList;
 
                assert.strictEqual( $( '#toc' ).length, 0, 'There is no table of contents on the page at the beginning' );
index 5329be6..6c27c5b 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw ) {
        QUnit.module( 'mediawiki.track' );
 
-       QUnit.test( 'track', 1, function ( assert ) {
+       QUnit.test( 'track', function ( assert ) {
                var sequence = [];
                mw.trackSubscribe( 'simple', function ( topic, data ) {
                        sequence.push( [ topic, data ] );
@@ -15,7 +15,7 @@
                ], 'Events after subscribing' );
        } );
 
-       QUnit.test( 'trackSubscribe', 4, function ( assert ) {
+       QUnit.test( 'trackSubscribe', function ( assert ) {
                var now,
                        sequence = [];
                mw.track( 'before', { key: 1 } );
@@ -40,7 +40,7 @@
                } );
        } );
 
-       QUnit.test( 'trackUnsubscribe', 1, function ( assert ) {
+       QUnit.test( 'trackUnsubscribe', function ( assert ) {
                var sequence = [];
                function unsubber( topic, data ) {
                        sequence.push( [ topic, data ] );
index 88052de..01665e5 100644 (file)
@@ -29,7 +29,7 @@
                        [ false, ':::' ],
                        [ false, '::0:', 'IPv6 ending in a lone ":"' ],
 
-                       [ true,  '::', 'IPv6 zero address' ],
+                       [ true, '::', 'IPv6 zero address' ],
 
                        [ false, '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' ],
                        [ false, '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' ],
                        [ false, 'fc::100:', 'IPv6 ending with lone ":"' ],
                        [ false, 'fc:::100', 'IPv6 with ":::" in the middle' ],
 
-                       [ true,  'fc::100', 'IPv6 with "::" and 2 words' ],
-                       [ true,  'fc::100:a', 'IPv6 with "::" and 3 words' ],
-                       [ true,  'fc::100:a:d', 'IPv6 with "::" and 4 words' ],
-                       [ true,  'fc::100:a:d:1', 'IPv6 with "::" and 5 words' ],
-                       [ true,  'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words' ],
-                       [ true,  'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words' ],
-                       [ true,  '2001::df', 'IPv6 with "::" and 2 words' ],
-                       [ true,  '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words' ],
-                       [ true,  '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words' ],
+                       [ true, 'fc::100', 'IPv6 with "::" and 2 words' ],
+                       [ true, 'fc::100:a', 'IPv6 with "::" and 3 words' ],
+                       [ true, 'fc::100:a:d', 'IPv6 with "::" and 4 words' ],
+                       [ true, 'fc::100:a:d:1', 'IPv6 with "::" and 5 words' ],
+                       [ true, 'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words' ],
+                       [ true, 'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words' ],
+                       [ true, '2001::df', 'IPv6 with "::" and 2 words' ],
+                       [ true, '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words' ],
+                       [ true, '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words' ],
 
                        [ false, 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' ],
                        [ false, 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' ]
                }
        } ) );
 
-       QUnit.test( 'rawurlencode', 1, function ( assert ) {
+       QUnit.test( 'rawurlencode', function ( assert ) {
                assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
        } );
 
-       QUnit.test( 'escapeId', 17, function ( assert ) {
+       QUnit.test( 'escapeId', function ( assert ) {
                mw.config.set( 'wgExperimentalHtmlIds', false );
                $.each( {
                        '+': '.2B',
                } );
        } );
 
-       QUnit.test( 'wikiUrlencode', 11, function ( assert ) {
+       QUnit.test( 'wikiUrlencode', function ( assert ) {
                assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
                // See also wfUrlencodeTest.php#provideURLS
                $.each( {
                } );
        } );
 
-       QUnit.test( 'getUrl', 14, function ( assert ) {
+       QUnit.test( 'getUrl', function ( assert ) {
                var href;
                mw.config.set( {
                        wgScript: '/w/index.php',
                assert.equal( href, '/w/index.php?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
        } );
 
-       QUnit.test( 'wikiScript', 4, function ( assert ) {
+       QUnit.test( 'wikiScript', function ( assert ) {
                mw.config.set( {
                        // customized wgScript for T41103
                        wgScript: '/w/i.php',
                assert.equal( mw.util.wikiScript( 'api' ), '/w/api.php', 'API path' );
        } );
 
-       QUnit.test( 'addCSS', 3, function ( assert ) {
+       QUnit.test( 'addCSS', function ( assert ) {
                var $el, style;
                $el = $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
 
                $( style.ownerNode ).remove();
        } );
 
-       QUnit.test( 'getParamValue', 5, function ( assert ) {
+       QUnit.test( 'getParamValue', function ( assert ) {
                var url;
 
                url = 'http://example.org/?foo=wrong&foo=right#&foo=bad';
                assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c d', 'T32441: getParamValue must understand "+" encoding of space (multiple spaces)' );
        } );
 
-       QUnit.test( '$content', 2, function ( assert ) {
+       QUnit.test( '$content', function ( assert ) {
                assert.ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
                assert.strictEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
        } );
         * Previously, test elements where invisible to the selector since only
         * one element can have a given id.
         */
-       QUnit.test( 'addPortletLink', 13, function ( assert ) {
+       QUnit.test( 'addPortletLink', function ( assert ) {
                var pTestTb, pCustom, vectorTabs, tbRL, cuQuux, $cuQuux, tbMW, $tbMW, tbRLDM, caFoo,
                        addedAfter, tbRLDMnonexistentid, tbRLDMemptyjquery;
 
                assert.equal( tbRLDMemptyjquery, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
        } );
 
-       QUnit.test( 'validateEmail', 6, function ( assert ) {
+       QUnit.test( 'validateEmail', function ( assert ) {
                assert.strictEqual( mw.util.validateEmail( '' ), null, 'Should return null for empty string ' );
                assert.strictEqual( mw.util.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
 
                assert.strictEqual( mw.util.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
        } );
 
-       QUnit.test( 'isIPv6Address', 40, function ( assert ) {
+       QUnit.test( 'isIPv6Address', function ( assert ) {
                $.each( IPV6_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv6Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
        } );
 
-       QUnit.test( 'isIPv4Address', 11, function ( assert ) {
+       QUnit.test( 'isIPv4Address', function ( assert ) {
                $.each( IPV4_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv4Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
        } );
 
-       QUnit.test( 'isIPAddress', 51, function ( assert ) {
+       QUnit.test( 'isIPAddress', function ( assert ) {
                $.each( IPV4_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv4Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
index f404294..9864166 100644 (file)
@@ -25,7 +25,7 @@
                }
        } ) );
 
-       QUnit.test( 'isElementInViewport', 6, function ( assert ) {
+       QUnit.test( 'isElementInViewport', function ( assert ) {
                var viewport = $.extend( {}, DEFAULT_VIEWPORT );
                assert.ok( mw.viewport.isElementInViewport( this.el, viewport ),
                        'It should return true when the element is fully enclosed in the viewport' );
@@ -60,7 +60,7 @@
                        'It should default to the window object if no viewport is given' );
        } );
 
-       QUnit.test( 'isElementInViewport with scrolled page', 1, function ( assert ) {
+       QUnit.test( 'isElementInViewport with scrolled page', function ( assert ) {
                var viewport = {
                                top: 2000,
                                left: 0,
@@ -83,7 +83,7 @@
                window.scrollTo( 0, 0 );
        } );
 
-       QUnit.test( 'isElementCloseToViewport', 3, function ( assert ) {
+       QUnit.test( 'isElementCloseToViewport', function ( assert ) {
                var
                        viewport = {
                                top: 90,
index e6e798b..02ca243 100644 (file)
@@ -1,4 +1,4 @@
-/*global isCompatible: true */
+/* global isCompatible: true */
 ( function ( $ ) {
        var testcases = {
                tested: [
 
        QUnit.module( 'startup', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'isCompatible( featureTestable )', testcases.tested.length, function ( assert ) {
+       QUnit.test( 'isCompatible( featureTestable )', function ( assert ) {
                $.each( testcases.tested, function ( i, ua ) {
-                               assert.strictEqual( isCompatible( ua ), true, ua );
-                       }
-               );
+                       assert.strictEqual( isCompatible( ua ), true, ua );
+               } );
        } );
 
-       QUnit.test( 'isCompatible( blacklisted )', testcases.blacklisted.length, function ( assert ) {
+       QUnit.test( 'isCompatible( blacklisted )', function ( assert ) {
                $.each( testcases.blacklisted, function ( i, ua ) {
-                               assert.strictEqual( isCompatible( ua ), false, ua );
-                       }
-               );
+                       assert.strictEqual( isCompatible( ua ), false, ua );
+               } );
        } );
 }( jQuery ) );