Merge "DefaultSettings: Fix doxygen warning for missing @endcond"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 2 Apr 2015 22:29:02 +0000 (22:29 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 2 Apr 2015 22:29:02 +0000 (22:29 +0000)
118 files changed:
RELEASE-NOTES-1.25
StartProfiler.sample
autoload.php
docs/hooks.txt
includes/CategoryViewer.php
includes/DefaultSettings.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/Html.php
includes/MediaWiki.php
includes/Message.php
includes/MessageBlobStore.php
includes/OutputPage.php
includes/Revision.php
includes/User.php
includes/WebRequest.php
includes/WebStart.php
includes/Xml.php
includes/actions/InfoAction.php
includes/api/ApiQuery.php
includes/api/i18n/fr.json
includes/cache/LocalisationCache.php
includes/cache/MessageCache.php
includes/db/Database.php
includes/db/LoadBalancer.php
includes/diff/DifferenceEngine.php
includes/exception/MWExceptionHandler.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/i18n/mk.json
includes/json/FormatJson.php
includes/libs/XmlTypeCheck.php
includes/logging/LogFormatter.php
includes/media/BitmapMetadataHandler.php
includes/media/JpegMetadataExtractor.php
includes/media/XMP.php
includes/page/WikiPage.php
includes/parser/CoreParserFunctions.php
includes/parser/DateFormatter.php
includes/parser/Parser.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/profiler/Profiler.php
includes/profiler/ProfilerStub.php
includes/profiler/TransactionProfiler.php
includes/profiler/output/ProfilerOutputStats.php [new file with mode: 0644]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderImageModule.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUserlogin.php
includes/upload/UploadBase.php
languages/i18n/bho.json
languages/i18n/br.json
languages/i18n/cs.json
languages/i18n/cv.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/egl.json
languages/i18n/en.json
languages/i18n/es.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hu.json
languages/i18n/it.json
languages/i18n/ka.json
languages/i18n/kiu.json
languages/i18n/ku-latn.json
languages/i18n/lrc.json
languages/i18n/mk.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/ne.json
languages/i18n/pms.json
languages/i18n/qqq.json
languages/i18n/sl.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/uz.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesArc.php
languages/messages/MessagesAz.php
languages/messages/MessagesAzb.php
languages/messages/MessagesCkb.php
languages/messages/MessagesDv.php
languages/messages/MessagesFa.php
languages/messages/MessagesHe.php
languages/messages/MessagesKhw.php
languages/messages/MessagesKk_arab.php
languages/messages/MessagesKs_arab.php
languages/messages/MessagesMzn.php
languages/messages/MessagesNds.php
languages/messages/MessagesUr.php
resources/Resources.php
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/data/xmp/doctype-included.result.php [new file with mode: 0644]
tests/phpunit/data/xmp/doctype-included.xmp [new file with mode: 0644]
tests/phpunit/data/xmp/doctype-not-included.xmp [new file with mode: 0644]
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/libs/XmlTypeCheckTest.php
tests/phpunit/includes/media/XMPTest.php
tests/phpunit/includes/upload/UploadBaseTest.php
tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js

index 0bf7a80..a31461c 100644 (file)
@@ -408,6 +408,8 @@ changes to languages because of Bugzilla reports.
   addSecondaryDataUpdate throwing an exception. These functions will be removed in 1.26,
   since they interfere with caching of ParserOutput objects.
 * Introduced new hook 'SecondaryDataUpdates' that allows extensions to inject custom updates.
+* Introduced new hook 'OpportunisticLinksUpdate' that allows extensions to perform
+  updates when a page is re-rendered.
 * EditPage::attemptSave has been modified not to call handleStatus itself and
   instead just returns the Status object. Extension calling it should be aware of
   this.
index 6681b87..7a88957 100644 (file)
@@ -4,30 +4,35 @@
  * To use a profiler, copy this file to StartProfiler.php and add:
  *  $wgProfiler['class'] = 'ProfilerXhprof';
  *
- * For output, add:
- *  $wgProfiler['output'] = array( 'text' );
- *    'text' can be one (or more) of 'text' 'udp' 'db' or 'dump'
- *    'db' requires creating the profiling table, see patch-profiling.sql
+ * For output, set the 'output' key to an array of class names, one for each
+ * output type you want the profiler to generate. For example:
+ *  $wgProfiler['output'] = array( 'ProfilerOutputText' );
  *
- * The 'text' output will be added to the output page in a comment approriate
- * to the output's mime type. For a text/html page, this display can be
- * changed to a preformatted text block by setting the 'visible' configuration
- * flag:
+ * The output classes available to you by default are ProfilerOutputDb,
+ * ProfilerOutputDump, ProfilerOutputStats, ProfilerOutputText, and
+ * ProfilerOutputUdp.
+ *
+ * ProfilerOutputStats outputs profiling data as StatsD metrics. It expects
+ * that you have set the $wgStatsdServer configuration variable to the host (or
+ * host:port) of your statsd server.
+ *
+ * ProfilerOutputText will output profiling data in the page body as a comment.
+ * You can make the profiling data in HTML render as part of the page content
+ * by setting the 'visible' configuration flag:
  *  $wgProfiler['visible'] = true;
  *
- * The 'db' output expects a database table that can be created by applying
+ * 'ProfilerOutputDb' expects a database table that can be created by applying
  * maintenance/archives/patch-profiling.sql to your database.
  *
- * The 'dump' output expects a $wgProfiler['outputDir'] telling it where to
+ * 'ProfilerOutputDump' expects a $wgProfiler['outputDir'] telling it where to
  * write dump files. The files produced are compatible with the XHProf gui.
- *
  * For a rudimentary sampling profiler:
  *   $wgProfiler['class'] = 'ProfilerXhprof';
- *   $wgProfiler['output'] = array( 'db' );
+ *   $wgProfiler['output'] = array( 'ProfilingOutputDb' );
  *   $wgProfiler['sampling'] = 50; // one every 50 requests
  * This will use ProfilerStub for non-sampled cases.
  *
- * For performance, the profiler is always disabled for CLI scripts
- * as they could be long running and the data would accumulate. Use
- * the --profiler parameter of maintenance scripts to override this.
+ * For performance, the profiler is always disabled for CLI scripts as they
+ * could be long running and the data would accumulate. Use the '--profiler'
+ * parameter of maintenance scripts to override this.
  */
index dcd7879..da661a2 100644 (file)
@@ -910,6 +910,7 @@ $wgAutoloadLocalClasses = array(
        'ProfilerOutput' => __DIR__ . '/includes/profiler/output/ProfilerOutput.php',
        'ProfilerOutputDb' => __DIR__ . '/includes/profiler/output/ProfilerOutputDb.php',
        'ProfilerOutputDump' => __DIR__ . '/includes/profiler/output/ProfilerOutputDump.php',
+       'ProfilerOutputStats' => __DIR__ . '/includes/profiler/output/ProfilerOutputStats.php',
        'ProfilerOutputText' => __DIR__ . '/includes/profiler/output/ProfilerOutputText.php',
        'ProfilerOutputUdp' => __DIR__ . '/includes/profiler/output/ProfilerOutputUdp.php',
        'ProfilerSectionOnly' => __DIR__ . '/includes/profiler/ProfilerSectionOnly.php',
index f2c47ca..877b7ed 100644 (file)
@@ -2012,6 +2012,17 @@ return false to omit the line from RecentChanges and Watchlist special pages.
 can alter or append to the array of URLs for search & suggestion formats.
 &$urls: array of associative arrays with Url element attributes
 
+'OpportunisticLinksUpdate': Called by WikiPage::triggerOpportunisticLinksUpdate
+when a page view triggers a re-rendering of the page. This may happen
+particularly if the parser cache is split by user language, and no cached
+rendering of the page exists in the user's language. The hook is called
+before checking whether page_links_updated indicates that the links are up
+to date. Returning false will cause triggerOpportunisticLinksUpdate() to abort
+without triggering any updates.
+$page: the Page that was rendered.
+$title: the Title of the rendered page.
+$parserOutput: ParserOutput resulting from rendering the page.
+
 'OtherBlockLogLink': Get links to the block log from extensions which blocks
 users and/or IP addresses too.
 $otherBlockLink: An array with links to other block logs
index 48436c5..66079c0 100644 (file)
@@ -603,7 +603,7 @@ class CategoryViewer extends ContextSource {
         * @return string HTML
         */
        private function pagingLinks( $first, $last, $type = '' ) {
-               $prevLink = $this->msg( 'prevn' )->numParams( $this->limit )->escaped();
+               $prevLink = $this->msg( 'prev-page' )->text();
 
                if ( $first != '' ) {
                        $prevQuery = $this->query;
@@ -617,7 +617,7 @@ class CategoryViewer extends ContextSource {
                        );
                }
 
-               $nextLink = $this->msg( 'nextn' )->numParams( $this->limit )->escaped();
+               $nextLink = $this->msg( 'next-page' )->text();
 
                if ( $last != '' ) {
                        $lastQuery = $this->query;
index 99acd3f..ef80c63 100644 (file)
@@ -4228,6 +4228,18 @@ $wgPasswordSalt = true;
  */
 $wgMinimalPasswordLength = 1;
 
+/**
+ * Specifies the maximal length of a user password (T64685).
+ *
+ * It is not recommended to make this greater than the default, as it can
+ * allow DoS attacks by users setting really long passwords. In addition,
+ * this should not be lowered too much, as it enforces weak passwords.
+ *
+ * @warning Unlike other password settings, user with passwords greater than
+ *      the maximum will not be able to log in.
+ */
+$wgMaximalPasswordLength = 4096;
+
 /**
  * Specifies if users should be sent to a password-reset form on login, if their
  * password doesn't meet the requirements of User::isValidPassword().
@@ -5413,6 +5425,7 @@ $wgDeprecationReleaseLimit = false;
 
 /**
  * Only record profiling info for pages that took longer than this
+ * @deprecated since 1.25: set $wgProfiler['threshold'] instead.
  */
 $wgProfileLimit = 0.0;
 
index a5994e7..e113426 100644 (file)
@@ -2670,19 +2670,21 @@ class EditPage {
                                                array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() )
                                        );
                                }
-                               if ( $this->formtype !== 'preview' ) {
-                                       if ( $this->isCssSubpage && $wgAllowUserCss ) {
-                                               $wgOut->wrapWikiMsg(
-                                                       "<div id='mw-usercssyoucanpreview'>\n$1\n</div>",
-                                                       array( 'usercssyoucanpreview' )
-                                               );
-                                       }
+                               if ( $this->getTitle()->isSubpageOf( $wgUser->getUserPage() ) ) {
+                                       if ( $this->formtype !== 'preview' ) {
+                                               if ( $this->isCssSubpage && $wgAllowUserCss ) {
+                                                       $wgOut->wrapWikiMsg(
+                                                               "<div id='mw-usercssyoucanpreview'>\n$1\n</div>",
+                                                               array( 'usercssyoucanpreview' )
+                                                       );
+                                               }
 
-                                       if ( $this->isJsSubpage && $wgAllowUserJs ) {
-                                               $wgOut->wrapWikiMsg(
-                                                       "<div id='mw-userjsyoucanpreview'>\n$1\n</div>",
-                                                       array( 'userjsyoucanpreview' )
-                                               );
+                                               if ( $this->isJsSubpage && $wgAllowUserJs ) {
+                                                       $wgOut->wrapWikiMsg(
+                                                               "<div id='mw-userjsyoucanpreview'>\n$1\n</div>",
+                                                               array( 'userjsyoucanpreview' )
+                                                       );
+                                               }
                                        }
                                }
                        }
index bc3a46b..24a3c33 100644 (file)
@@ -1237,10 +1237,15 @@ function wfErrorLog( $text, $file, array $context = array() ) {
  * @todo document
  */
 function wfLogProfilingData() {
-       global $wgRequestTime, $wgDebugLogGroups, $wgDebugRawPage;
-       global $wgProfileLimit, $wgUser, $wgRequest;
+       global $wgDebugLogGroups, $wgDebugRawPage;
 
        $context = RequestContext::getMain();
+       $request = $context->getRequest();
+
+       $profiler = Profiler::instance();
+       $profiler->setContext( $context );
+       $profiler->logData();
+
        $config = $context->getConfig();
        if ( $config->has( 'StatsdServer' ) ) {
                $statsdServer = explode( ':', $config->get( 'StatsdServer' ) );
@@ -1251,22 +1256,11 @@ function wfLogProfilingData() {
                $statsdClient->send( $context->getStats()->getBuffer() );
        }
 
-       $profiler = Profiler::instance();
-
        # Profiling must actually be enabled...
        if ( $profiler instanceof ProfilerStub ) {
                return;
        }
 
-       // Get total page request time and only show pages that longer than
-       // $wgProfileLimit time (default is 0)
-       $elapsed = microtime( true ) - $wgRequestTime;
-       if ( $elapsed <= $wgProfileLimit ) {
-               return;
-       }
-
-       $profiler->logData();
-
        if ( isset( $wgDebugLogGroups['profileoutput'] )
                && $wgDebugLogGroups['profileoutput'] === false
        ) {
@@ -1277,7 +1271,7 @@ function wfLogProfilingData() {
                return;
        }
 
-       $ctx = array( 'elapsed' => $elapsed );
+       $ctx = array( 'elapsed' => $request->getElapsedTime() );
        if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
                $ctx['forwarded_for'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
@@ -1296,16 +1290,13 @@ function wfLogProfilingData() {
        // Don't load $wgUser at this late stage just for statistics purposes
        // @todo FIXME: We can detect some anons even if it is not loaded.
        // See User::getId()
-       if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
-               $ctx['anon'] = true;
-       } else {
-               $ctx['anon'] = false;
-       }
+       $user = $context->getUser();
+       $ctx['anon'] = $user->isItemLoaded( 'id' ) && $user->isAnon();
 
        // Command line script uses a FauxRequest object which does not have
        // any knowledge about an URL and throw an exception instead.
        try {
-               $ctx['url'] = urldecode( $wgRequest->getRequestURL() );
+               $ctx['url'] = urldecode( $request->getRequestURL() );
        } catch ( Exception $ignored ) {
                // no-op
        }
index 4b69885..effc488 100644 (file)
@@ -600,17 +600,20 @@ class Html {
                        } else {
                                // Apparently we need to entity-encode \n, \r, \t, although the
                                // spec doesn't mention that.  Since we're doing strtr() anyway,
-                               // and we don't need <> escaped here, we may as well not call
-                               // htmlspecialchars().
+                               // we may as well not call htmlspecialchars().
                                // @todo FIXME: Verify that we actually need to
                                // escape \n\r\t here, and explain why, exactly.
                                #
                                // We could call Sanitizer::encodeAttribute() for this, but we
                                // don't because we're stubborn and like our marginal savings on
                                // byte size from not having to encode unnecessary quotes.
+                               // The only difference between this transform and the one by
+                               // Sanitizer::encodeAttribute() is '<' is only encoded here if
+                               // $wgWellFormedXml is set, and ' is not encoded.
                                $map = array(
                                        '&' => '&amp;',
                                        '"' => '&quot;',
+                                       '>' => '&gt;',
                                        "\n" => '&#10;',
                                        "\r" => '&#13;',
                                        "\t" => '&#9;'
index c086a39..c4af16d 100644 (file)
@@ -478,6 +478,7 @@ class MediaWiki {
                $wgTitle = $title;
 
                $trxProfiler = Profiler::instance()->getTransactionProfiler();
+               $trxProfiler->setLogger( MWLoggerFactory::getInstance( 'DBPerformance' ) );
 
                // Aside from rollback, master queries should not happen on GET requests.
                // Periodic or "in passing" updates on GET should use the job queue.
index 49437f4..134af0e 100644 (file)
@@ -249,7 +249,7 @@ class Message implements MessageSpecifier {
                $this->key = reset( $this->keysToTry );
 
                $this->parameters = array_values( $params );
-               $this->language = $language ? $language : $wgLang;
+               $this->language = $language ?: $wgLang;
        }
 
        /**
index c384188..011cae6 100644 (file)
@@ -36,15 +36,12 @@ class MessageBlobStore {
         * Get the singleton instance
         *
         * @since 1.24
+        * @deprecated since 1.25
         * @return MessageBlobStore
         */
        public static function getInstance() {
-               static $instance = null;
-               if ( $instance === null ) {
-                       $instance = new self;
-               }
-
-               return $instance;
+               wfDeprecated( __METHOD__, '1.25' );
+               return new self;
        }
 
        /**
index edeae0d..cac89f4 100644 (file)
@@ -3106,7 +3106,7 @@ class OutputPage extends ContextSource {
                // This also enforces $.isReady to be true at </body> which fixes the
                // mw.loader bug in Firefox with using document.write between </body>
                // and the DOMContentReady event (bug 47457).
-               $html = Html::inlineScript( 'window.jQuery && jQuery.ready();' );
+               $html = Html::inlineScript( 'if(window.jQuery)jQuery.ready();' );
 
                if ( !$this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
                        $html .= $this->getScriptsForBottomQueue( false );
@@ -3288,6 +3288,10 @@ class OutputPage extends ContextSource {
                if ( !$this->getTitle()->isJsSubpage() && !$this->getTitle()->isCssSubpage() ) {
                        return false;
                }
+               if ( !$this->getTitle()->isSubpageOf( $this->getUser()->getUserPage() ) ) {
+                       // Don't execute another user's CSS or JS on preview (T85855)
+                       return false;
+               }
 
                return !count( $this->getTitle()->getUserPermissionsErrors( 'edit', $this->getUser() ) );
        }
index 356cd32..a13499a 100644 (file)
@@ -297,7 +297,10 @@ class Revision implements IDBAccessObject {
        }
 
        /**
-        * Given a set of conditions, fetch a revision.
+        * Given a set of conditions, fetch a revision
+        *
+        * This method is used then a revision ID is qualified and
+        * will incorporate some basic slave/master fallback logic
         *
         * @param array $conditions
         * @param int $flags (optional)
@@ -305,10 +308,24 @@ class Revision implements IDBAccessObject {
         */
        private static function newFromConds( $conditions, $flags = 0 ) {
                $db = wfGetDB( ( $flags & self::READ_LATEST ) ? DB_MASTER : DB_SLAVE );
+
                $rev = self::loadFromConds( $db, $conditions, $flags );
+               // Make sure new pending/committed revision are visibile later on
+               // within web requests to certain avoid bugs like T93866 and T94407.
+               if ( !$rev
+                       && !( $flags & self::READ_LATEST )
+                       && wfGetLB()->getServerCount() > 1
+                       && wfGetLB()->hasOrMadeRecentMasterChanges()
+               ) {
+                       $flags = self::READ_LATEST;
+                       $db = wfGetDB( DB_MASTER );
+                       $rev = self::loadFromConds( $db, $conditions, $flags );
+               }
+
                if ( $rev ) {
                        $rev->mQueryFlags = $flags;
                }
+
                return $rev;
        }
 
@@ -1481,9 +1498,9 @@ class Revision implements IDBAccessObject {
         * @return string|bool The revision's text, or false on failure
         */
        protected function loadText() {
-
                // Caching may be beneficial for massive use of external storage
                global $wgRevisionCacheExpiry, $wgMemc;
+
                $textId = $this->getTextId();
                $key = wfMemcKey( 'revisiontext', 'textid', $textId );
                if ( $wgRevisionCacheExpiry ) {
index 89ff299..322f8af 100644 (file)
@@ -826,15 +826,24 @@ class User implements IDBAccessObject {
        }
 
        /**
-        * Check if this is a valid password for this user. Status will be good if
-        * the password is valid, or have an array of error messages if not.
+        * Check if this is a valid password for this user
+        *
+        * Create a Status object based on the password's validity.
+        * The Status should be set to fatal if the user should not
+        * be allowed to log in, and should have any errors that
+        * would block changing the password.
+        *
+        * If the return value of this is not OK, the password
+        * should not be checked. If the return value is not Good,
+        * the password can be checked, but the user should not be
+        * able to set their password to this.
         *
         * @param string $password Desired password
         * @return Status
         * @since 1.23
         */
        public function checkPasswordValidity( $password ) {
-               global $wgMinimalPasswordLength, $wgContLang;
+               global $wgMinimalPasswordLength, $wgMaximalPasswordLength, $wgContLang;
 
                static $blockedLogins = array(
                        'Useruser' => 'Passpass', 'Useruser1' => 'Passpass1', # r75589
@@ -854,6 +863,10 @@ class User implements IDBAccessObject {
                        if ( strlen( $password ) < $wgMinimalPasswordLength ) {
                                $status->error( 'passwordtooshort', $wgMinimalPasswordLength );
                                return $status;
+                       } elseif ( strlen( $password ) > $wgMaximalPasswordLength ) {
+                               // T64685: Password too long, might cause DoS attack
+                               $status->fatal( 'passwordtoolong', $wgMaximalPasswordLength );
+                               return $status;
                        } elseif ( $wgContLang->lc( $password ) == $wgContLang->lc( $this->mName ) ) {
                                $status->error( 'password-name-match' );
                                return $status;
@@ -2382,17 +2395,9 @@ class User implements IDBAccessObject {
                                throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
                        }
 
-                       if ( !$this->isValidPassword( $str ) ) {
-                               global $wgMinimalPasswordLength;
-                               $valid = $this->getPasswordValidity( $str );
-                               if ( is_array( $valid ) ) {
-                                       $message = array_shift( $valid );
-                                       $params = $valid;
-                               } else {
-                                       $message = $valid;
-                                       $params = array( $wgMinimalPasswordLength );
-                               }
-                               throw new PasswordError( wfMessage( $message, $params )->text() );
+                       $status = $this->checkPasswordValidity( $str );
+                       if ( !$status->isGood() ) {
+                               throw new PasswordError( $status->getMessage()->text() );
                        }
                }
 
@@ -2701,7 +2706,9 @@ class User implements IDBAccessObject {
                $token = $this->getOption( $oname );
                if ( !$token ) {
                        $token = $this->resetTokenFromOption( $oname );
-                       $this->saveSettings();
+                       if ( !wfReadOnly() ) {
+                               $this->saveSettings();
+                       }
                }
                return $token;
        }
@@ -3495,7 +3502,9 @@ class User implements IDBAccessObject {
                        // Simply by setting every cell in the user_token column to NULL and letting them be
                        // regenerated as users log back into the wiki.
                        $this->setToken();
-                       $this->saveSettings();
+                       if ( !wfReadOnly() ) {
+                               $this->saveSettings();
+                       }
                }
                $session = array(
                        'wsUserID' => $this->mId,
@@ -3576,11 +3585,12 @@ class User implements IDBAccessObject {
        public function saveSettings() {
                global $wgAuth;
 
-               $this->load();
-               $this->loadPasswords();
                if ( wfReadOnly() ) {
                        return; // @TODO: caller should deal with this instead!
                }
+
+               $this->load();
+               $this->loadPasswords();
                if ( 0 == $this->mId ) {
                        return;
                }
@@ -3900,6 +3910,13 @@ class User implements IDBAccessObject {
 
                $this->loadPasswords();
 
+               // Some passwords will give a fatal Status, which means there is
+               // some sort of technical or security reason for this password to
+               // be completely invalid and should never be checked (e.g., T64685)
+               if ( !$this->checkPasswordValidity( $password )->isOK() ) {
+                       return false;
+               }
+
                // Certain authentication plugins do NOT want to save
                // domain passwords in a mysql database, so we should
                // check this (in case $wgAuth->strict() is false).
@@ -3927,7 +3944,7 @@ class User implements IDBAccessObject {
                }
 
                $passwordFactory = self::getPasswordFactory();
-               if ( $passwordFactory->needsUpdate( $this->mPassword ) ) {
+               if ( $passwordFactory->needsUpdate( $this->mPassword ) && !wfReadOnly() ) {
                        $this->mPassword = $passwordFactory->newFromPlaintext( $password );
                        $this->saveSettings();
                }
index df88b35..054eceb 100644 (file)
@@ -50,6 +50,12 @@ class WebRequest {
         */
        private $ip;
 
+       /**
+        * The timestamp of the start of the request, with microsecond precision.
+        * @var float
+        */
+       protected $requestTime;
+
        /**
         * Cached URL protocol
         * @var string
@@ -57,9 +63,8 @@ class WebRequest {
        protected $protocol;
 
        public function __construct() {
-               if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
-                       throw new MWException( "MediaWiki does not function when magic quotes are enabled." );
-               }
+               $this->requestTime = isset( $_SERVER['REQUEST_TIME_FLOAT'] )
+                       ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime( true );
 
                // POST overrides GET data
                // We don't use $_REQUEST here to avoid interference from cookies...
@@ -216,6 +221,17 @@ class WebRequest {
                }
        }
 
+       /**
+        * Get the number of seconds to have elapsed since request start,
+        * in fractional seconds, with microsecond resolution.
+        *
+        * @return float
+        * @since 1.25
+        */
+       public function getElapsedTime() {
+               return microtime( true ) - $this->requestTime;
+       }
+
        /**
         * Get the current URL protocol (http or https)
         * @return string
@@ -1274,6 +1290,8 @@ class FauxRequest extends WebRequest {
        public function __construct( $data = array(), $wasPosted = false,
                $session = null, $protocol = 'http'
        ) {
+               $this->requestTime = microtime( true );
+
                if ( is_array( $data ) ) {
                        $this->data = $data;
                } else {
@@ -1497,4 +1515,8 @@ class DerivativeRequest extends FauxRequest {
        public function getProtocol() {
                return $this->base->getProtocol();
        }
+
+       public function getElapsedTime() {
+               return $this->base->getElapsedTime();
+       }
 }
index da4bc87..9c71f3e 100644 (file)
@@ -34,12 +34,30 @@ if ( ini_get( 'register_globals' ) ) {
                . 'for help on how to disable it.' );
 }
 
+if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
+       die( 'MediaWiki does not function when magic quotes are enabled. '
+               . 'Please see the <a href="https://php.net/manual/security.magicquotes.disabling.php">PHP Manual</a> '
+               . 'for help on how to disable magic quotes.' );
+}
+
+
 # bug 15461: Make IE8 turn off content sniffing. Everybody else should ignore this
 # We're adding it here so that it's *always* set, even for alternate entry
 # points and when $wgOut gets disabled or overridden.
 header( 'X-Content-Type-Options: nosniff' );
 
-$wgRequestTime = microtime( true );
+# Approximate $_SERVER['REQUEST_TIME_FLOAT'] for PHP<5.4
+if ( !isset( $_SERVER['REQUEST_TIME_FLOAT'] ) ) {
+       $_SERVER['REQUEST_TIME_FLOAT'] = microtime( true );
+}
+
+/**
+ * @var float Request start time as fractional seconds since epoch
+ * @deprecated since 1.25; use $_SERVER['REQUEST_TIME_FLOAT'] or
+ *   WebRequest::getElapsedTime() instead.
+ */
+$wgRequestTime = $_SERVER['REQUEST_TIME_FLOAT'];
+
 unset( $IP );
 
 # Valid web server entry point, enable includes.
index 78b8715..f0bd70b 100644 (file)
@@ -703,13 +703,15 @@ class Xml {
        /**
         * Check if a string is well-formed XML.
         * Must include the surrounding tag.
+        * This function is a DoS vector if an attacker can define
+        * entities in $text.
         *
         * @param string $text String to test.
         * @return bool
         *
         * @todo Error position reporting return
         */
-       public static function isWellFormed( $text ) {
+       private static function isWellFormed( $text ) {
                $parser = xml_parser_create( "UTF-8" );
 
                # case folding violates XML standard, turn it off
index 338d939..b5a7391 100644 (file)
@@ -65,8 +65,8 @@ class InfoAction extends FormlessAction {
         */
        public static function invalidateCache( Title $title ) {
                global $wgMemc;
-               // Clear page info.
-               $revision = WikiPage::factory( $title )->getRevision();
+
+               $revision = Revision::newFromTitle( $title, 0, Revision::READ_LATEST );
                if ( $revision !== null ) {
                        $key = wfMemcKey( 'infoaction', sha1( $title->getPrefixedText() ), $revision->getId() );
                        $wgMemc->delete( $key );
index f4b64a3..ac89419 100644 (file)
@@ -249,16 +249,6 @@ class ApiQuery extends ApiBase {
        public function execute() {
                $this->mParams = $this->extractRequestParams();
 
-               if ( $this->mParams['continue'] === null && !$this->mParams['rawcontinue'] ) {
-                       $this->logFeatureUsage( 'action=query&!rawcontinue&!continue' );
-                       $this->setWarning(
-                               'Formatting of continuation data will be changing soon. ' .
-                               'To continue using the current formatting, use the \'rawcontinue\' parameter. ' .
-                               'To begin using the new format, pass an empty string for \'continue\' ' .
-                               'in the initial query.'
-                       );
-               }
-
                // Instantiate requested modules
                $allModules = array();
                $this->instantiateModules( $allModules, 'prop' );
@@ -304,6 +294,18 @@ class ApiQuery extends ApiBase {
                $this->getResult()->endContinuation(
                        $this->mParams['continue'] === null ? 'raw' : 'standard'
                );
+
+               if ( $this->mParams['continue'] === null && !$this->mParams['rawcontinue'] &&
+                       array_key_exists( 'query-continue', $this->getResult()->getData() )
+               ) {
+                       $this->logFeatureUsage( 'action=query&!rawcontinue&!continue' );
+                       $this->setWarning(
+                               'Formatting of continuation data will be changing soon. ' .
+                               'To continue using the current formatting, use the \'rawcontinue\' parameter. ' .
+                               'To begin using the new format, pass an empty string for \'continue\' ' .
+                               'in the initial query.'
+                       );
+               }
        }
 
        /**
index 6b269e8..114e36c 100644 (file)
@@ -10,7 +10,8 @@
                        "Linedwell",
                        "Nicolapps",
                        "Raulel",
-                       "Arkanosis"
+                       "Arkanosis",
+                       "Ltrlg"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentation]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un en-tête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet en-tête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:API:Errors_and_warnings|API: Errors and warnings]].",
        "apihelp-yaml-description": "Extraire les données au format YAML.",
        "apihelp-yamlfm-description": "Extraire les données YAML (affiché proprement en HTML).",
        "api-format-title": "Résultat de l’API de MédiaWiki",
-       "api-format-prettyprint-header": "Voici la représentation HTML du format $1. HTML est utile pour le débogage, mais inapproprié pour être utilisé dans une application.$2\n\nSpécifiez le paramètre <var>format</var> pour modifier le format de sortie. Pour voir la représentation non HTML du format $1, mettez <kbd>format=$2</kbd>.\n\nVoyez la [[mw:API|documentation complète]], ou l’ [[Special:ApiHelp/main|aide de l’API]] pour plus d’information.",
+       "api-format-prettyprint-header": "Voici la représentation HTML du format $1. HTML est utile pour le débogage, mais inapproprié pour être utilisé dans une application.\n\nSpécifiez le paramètre <var>format</var> pour modifier le format de sortie. Pour voir la représentation non HTML du format $1, mettez <kbd>format=$2</kbd>.\n\nVoyez la [[mw:API|documentation complète]], ou l’[[Special:ApiHelp/main|aide de l’API]] pour plus d’information.",
        "api-orm-param-props": "Champs à rechercher.",
        "api-orm-param-limit": "Nombre maximal de lignes à renvoyer.",
        "api-pageset-param-titles": "Une liste des titres sur lesquels travailler.",
index e270f5f..dc5a2eb 100644 (file)
@@ -1020,7 +1020,8 @@ class LocalisationCache {
                # HACK: If using a null (i.e. disabled) storage backend, we
                # can't write to the MessageBlobStore either
                if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
-                       MessageBlobStore::getInstance()->clear();
+                       $blobStore = new MessageBlobStore();
+                       $blobStore->clear();
                }
 
        }
index 04f5887..82919c7 100644 (file)
@@ -562,7 +562,8 @@ class MessageCache {
 
                // Update the message in the message blob store
                global $wgContLang;
-               MessageBlobStore::getInstance()->updateMessage( $wgContLang->lcfirst( $msg ) );
+               $blobStore = new MessageBlobStore();
+               $blobStore->updateMessage( $wgContLang->lcfirst( $msg ) );
 
                Hooks::run( 'MessageCacheReplace', array( $title, $text ) );
 
index b3c81f9..cbd8be5 100644 (file)
@@ -3611,6 +3611,7 @@ abstract class DatabaseBase implements IDatabase {
                        $this->runOnTransactionPreCommitCallbacks();
                        $this->doCommit( $fname );
                        if ( $this->mTrxDoneWrites ) {
+                               $this->mDoneWrites = microtime( true );
                                $this->getTransactionProfiler()->transactionWritingOut(
                                        $this->mServer, $this->mDBname, $this->mTrxShortId );
                        }
@@ -3691,6 +3692,7 @@ abstract class DatabaseBase implements IDatabase {
                $this->runOnTransactionPreCommitCallbacks();
                $this->doCommit( $fname );
                if ( $this->mTrxDoneWrites ) {
+                       $this->mDoneWrites = microtime( true );
                        $this->getTransactionProfiler()->transactionWritingOut(
                                $this->mServer, $this->mDBname, $this->mTrxShortId );
                }
index 4e0a5b9..48c636e 100644 (file)
@@ -1022,8 +1022,7 @@ class LoadBalancer {
        }
 
        /**
-        * Determine if there are any pending changes that need to be rolled back
-        * or committed.
+        * Determine if there are pending changes in a transaction by this thread
         * @since 1.23
         * @return bool
         */
@@ -1044,6 +1043,42 @@ class LoadBalancer {
                return false;
        }
 
+       /**
+        * Get the timestamp of the latest write query done by this thread
+        * @since 1.25
+        * @return float|bool UNIX timestamp or false
+        */
+       public function lastMasterChangeTimestamp() {
+               $lastTime = false;
+               // Always 0, but who knows.. :)
+               $masterIndex = $this->getWriterIndex();
+               foreach ( $this->mConns as $conns2 ) {
+                       if ( empty( $conns2[$masterIndex] ) ) {
+                               continue;
+                       }
+                       /** @var DatabaseBase $conn */
+                       foreach ( $conns2[$masterIndex] as $conn ) {
+                               $lastTime = max( $lastTime, $conn->lastDoneWrites() );
+                       }
+               }
+               return $lastTime;
+       }
+
+       /**
+        * Check if this load balancer object had any recent or still
+        * pending writes issued against it by this PHP thread
+        *
+        * @param float $age How many seconds ago is "recent" [defaults to mWaitTimeout]
+        * @return bool
+        * @since 1.25
+        */
+       public function hasOrMadeRecentMasterChanges( $age = null ) {
+               $age = ( $age === null ) ? $this->mWaitTimeout : $age;
+
+               return ( $this->hasMasterChanges()
+                       || $this->lastMasterChangeTimestamp() > microtime( true ) - $age );
+       }
+
        /**
         * @param mixed $value
         * @return mixed
index de8dd43..77bbd36 100644 (file)
@@ -1233,12 +1233,6 @@ class DifferenceEngine extends ContextSource {
                // Load the new revision object
                if ( $this->mNewid ) {
                        $this->mNewRev = Revision::newFromId( $this->mNewid );
-
-                       if ( !$this->mNewRev && wfGetLB()->getServerCount() > 1 ) {
-                               // Try harder… This is being hit after a rollback where we show the
-                               // diff immediately after the edit happened. T93866
-                               $this->mNewRev = Revision::newFromId( $this->mNewid, Revision::READ_LATEST );
-                       }
                } else {
                        $this->mNewRev = Revision::newFromTitle(
                                $this->getTitle(),
index 7110361..ed0f3c2 100644 (file)
@@ -349,7 +349,7 @@ TXT;
         * returns the requested URL. Otherwise, returns false.
         *
         * @since 1.23
-        * @return string|bool
+        * @return string|false
         */
        public static function getURL() {
                global $wgRequest;
@@ -428,7 +428,7 @@ TXT;
         * @param Exception $e
         * @param bool $pretty Add non-significant whitespace to improve readability (default: false).
         * @param int $escaping Bitfield consisting of FormatJson::.*_OK class constants.
-        * @return string|bool JSON string if successful; false upon failure
+        * @return string|false JSON string if successful; false upon failure
         */
        public static function jsonSerializeException( Exception $e, $pretty = false, $escaping = 0 ) {
                global $wgLogExceptionBacktrace;
index b676f45..12ef91a 100644 (file)
@@ -932,7 +932,8 @@ abstract class DatabaseUpdater {
                if ( $wgLocalisationCacheConf['manualRecache'] ) {
                        $this->rebuildLocalisationCache();
                }
-               MessageBlobStore::getInstance()->clear();
+               $blobStore = new MessageBlobStore();
+               $blobStore->clear();
                $this->output( "done.\n" );
        }
 
index 4c31387..b40b3f1 100644 (file)
@@ -1436,13 +1436,16 @@ abstract class Installer {
                        return array();
                }
 
+               // extensions -> extension.json, skins -> skin.json
+               $jsonFile = substr( $directory, 0, strlen( $directory ) -1 ) . '.json';
+
                $dh = opendir( $extDir );
                $exts = array();
                while ( ( $file = readdir( $dh ) ) !== false ) {
                        if ( !is_dir( "$extDir/$file" ) ) {
                                continue;
                        }
-                       if ( file_exists( "$extDir/$file/$file.php" ) ) {
+                       if ( file_exists( "$extDir/$file/$jsonFile" ) || file_exists( "$extDir/$file/$file.php" ) ) {
                                $exts[] = $file;
                        }
                }
index 8724e0d..737c996 100644 (file)
@@ -34,6 +34,7 @@ class LocalSettingsGenerator {
        protected $groupPermissions = array();
        protected $dbSettings = '';
        protected $safeMode = false;
+       protected $IP;
 
        /**
         * @var Installer
@@ -50,6 +51,7 @@ class LocalSettingsGenerator {
 
                $this->extensions = $installer->getVar( '_Extensions' );
                $this->skins = $installer->getVar( '_Skins' );
+               $this->IP = $installer->getVar( 'IP' );
 
                $db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) );
 
@@ -143,8 +145,7 @@ class LocalSettingsGenerator {
 # The following skins were automatically enabled:\n";
 
                        foreach ( $this->skins as $skinName ) {
-                               $encSkinName = self::escapePhpString( $skinName );
-                               $localSettings .= "require_once \"\$IP/skins/$encSkinName/$encSkinName.php\";\n";
+                               $localSettings .= $this->generateExtEnableLine( 'skins', $skinName );
                        }
 
                        $localSettings .= "\n";
@@ -157,8 +158,7 @@ class LocalSettingsGenerator {
 # The following extensions were automatically enabled:\n";
 
                        foreach ( $this->extensions as $extName ) {
-                               $encExtName = self::escapePhpString( $extName );
-                               $localSettings .= "require_once \"\$IP/extensions/$encExtName/$encExtName.php\";\n";
+                               $localSettings .= $this->generateExtEnableLine( 'extensions', $extName );
                        }
 
                        $localSettings .= "\n";
@@ -171,6 +171,34 @@ class LocalSettingsGenerator {
                return $localSettings;
        }
 
+       /**
+        * Generate the appropriate line to enable the given extension or skin
+        *
+        * @param string $dir Either "extensions" or "skins"
+        * @param string $name Name of extension/skin
+        * @throws InvalidArgumentException
+        * @return string
+        */
+       private function generateExtEnableLine( $dir, $name ) {
+               if ( $dir === 'extensions' ) {
+                       $jsonFile = 'extension.json';
+                       $function = 'wfLoadExtension';
+               } elseif ( $dir === 'skins' ) {
+                       $jsonFile = 'skin.json';
+                       $function = 'wfLoadSkin';
+               } else {
+                       throw new InvalidArgumentException( '$dir was not "extensions" or "skins' );
+               }
+
+               $encName = self::escapePhpString( $name );
+
+               if ( file_exists( "{$this->IP}/$dir/$encName/$jsonFile" ) ) {
+                       return "$function( '$encName' );\n";
+               } else {
+                       return "require_once \"\$IP/$dir/$encName/$encName.php\";\n";
+               }
+       }
+
        /**
         * Write the generated LocalSettings to a file
         *
index 52d049b..8649484 100644 (file)
        "config-env-bad": "Околината е проверена.\nНе можете да го воспоставите МедијаВики.",
        "config-env-php": "PHP $1 е воспоставен.",
        "config-env-hhvm": "HHVM $1 е воспоставен.",
-       "config-unicode-using-utf8": "Со utf8_normalize.so за уникодна нормализација од Брајон Вибер (Brion Vibber).",
        "config-unicode-using-intl": "Со додатокот [http://pecl.php.net/intl intl PECL] за уникодна нормализација.",
        "config-unicode-pure-php-warning": "'''Предупредување''': Додатокот [http://pecl.php.net/intl intl PECL] не е достапен за врши уникодна нормализација, враќајќи се на бавна примена на чист PHP.\n\nАко имате високопрометно мрежно место, тогаш ќе треба да прочитате повеќе за [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations уникодната нормализација].",
        "config-unicode-update-warning": "'''Предупредување:''' Воспоставената верзија на обвивката за уникодна нормализација користи постара верзија на библиотеката на [http://site.icu-project.org/ проектот ICU].\nЗа да користите Уникод, ќе треба да направите [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations надградба].",
-       "config-no-db": "Не можев да најдам соодветен двигател за базата на податоци! Ќе треба да воспоставите двигател за PHP-база.\nПоддржани се следниве видови бази: $1.\n\nДоколку самите го срочивте овој PHP, овозможете го базниот клиент во поставките — на пр. со <code>./configure --with-mysqli</code>.\nАко овој PHP го воспоставите од пакет на Debian или Ubuntu, тогаш ќе треба исто така да го воспоставите, на пр., пакетот <code>php5-mysql</code>.",
+       "config-no-db": "Не можев да најдам соодветен двигател за базата на податоци! Ќе треба да воспоставите двигател за PHP-база.\n{{PLURAL:$2|Поддржан се следниов вид|Поддржани се следниве видови}} бази: $1.\n\nДоколку самите го срочивте овој PHP, овозможете го базниот клиент во поставките — на пр. со <code>./configure --with-mysqli</code>.\nАко овој PHP го воспоставите од пакет на Debian или Ubuntu, тогаш ќе треба исто така да го воспоставите, на пр., пакетот <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Предупредување''': имате SQLite $1. Најстарата допуштена верзија е $2. Затоа, SQLite ќе биде недостапен.",
        "config-no-fts3": "'''Предупредување''': SQLite iе составен без модулот [//sqlite.org/fts3.html FTS3] - за оваа база нема да има можност за пребарување.",
        "config-register-globals-error": "<strong>Грешка: Вклучена е можноста <code>[http://php.net/register_globals register_globals]</code> за PHP.\nМора да се исклучи за да продолжите со воспоставката.</strong>\nКако да го направите тоа можете да прочитате на [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
index f27194a..095811f 100644 (file)
@@ -122,7 +122,7 @@ class FormatJson {
         *   readability, using that string for indentation. If true, use the default indent
         *   string (four spaces).
         * @param int $escaping Bitfield consisting of _OK class constants
-        * @return string|bool: String if successful; false upon failure
+        * @return string|false String if successful; false upon failure
         */
        public static function encode( $value, $pretty = false, $escaping = 0 ) {
                if ( !is_string( $pretty ) ) {
@@ -232,7 +232,7 @@ class FormatJson {
         * @param mixed $value
         * @param string|bool $pretty
         * @param int $escaping
-        * @return string|bool
+        * @return string|false
         */
        private static function encode54( $value, $pretty, $escaping ) {
                static $bug66021;
@@ -284,7 +284,7 @@ class FormatJson {
         * @param mixed $value
         * @param string|bool $pretty
         * @param int $escaping
-        * @return string|bool
+        * @return string|false
         */
        private static function encode53( $value, $pretty, $escaping ) {
                $options = ( $escaping & self::XMLMETA_OK ) ? 0 : ( JSON_HEX_TAG | JSON_HEX_AMP );
index 0d6c3a6..6d01986 100644 (file)
@@ -2,6 +2,11 @@
 /**
  * XML syntax and type checker.
  *
+ * Since 1.24.2, it uses XMLReader instead of xml_parse, which gives us
+ * more control over the expansion of XML entities. When passed to the
+ * callback, entities will be fully expanded, but may report the XML is
+ * invalid if expanding the entities are likely to cause a DoS.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -25,7 +30,7 @@ class XmlTypeCheck {
         * Will be set to true or false to indicate whether the file is
         * well-formed XML. Note that this doesn't check schema validity.
         */
-       public $wellFormed = false;
+       public $wellFormed = null;
 
        /**
         * Will be set to true if the optional element filter returned
@@ -78,12 +83,7 @@ class XmlTypeCheck {
        function __construct( $input, $filterCallback = null, $isFile = true, $options = array() ) {
                $this->filterCallback = $filterCallback;
                $this->parserOptions = array_merge( $this->parserOptions, $options );
-
-               if ( $isFile ) {
-                       $this->validateFromFile( $input );
-               } else {
-                       $this->validateFromString( $input );
-               }
+               $this->validateFromInput( $input, $isFile );
        }
 
        /**
@@ -125,140 +125,211 @@ class XmlTypeCheck {
                return $this->rootElement;
        }
 
+
        /**
-        * Get an XML parser with the root element handler.
-        * @see XmlTypeCheck::rootElementOpen()
-        * @return resource a resource handle for the XML parser
+        * @param string $fname the filename
         */
-       private function getParser() {
-               $parser = xml_parser_create_ns( 'UTF-8' );
-               // case folding violates XML standard, turn it off
-               xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-               xml_set_element_handler( $parser, array( $this, 'rootElementOpen' ), false );
-               if ( $this->parserOptions['processing_instruction_handler'] ) {
-                       xml_set_processing_instruction_handler(
-                               $parser,
-                               array( $this, 'processingInstructionHandler' )
-                       );
+       private function validateFromInput( $xml, $isFile ) {
+               $reader = new XMLReader();
+               if ( $isFile ) {
+                       $s = $reader->open( $xml, null, LIBXML_NOERROR | LIBXML_NOWARNING );
+               } else {
+                       $s = $reader->XML( $xml, null, LIBXML_NOERROR | LIBXML_NOWARNING );
+               }
+               if ( $s !== true ) {
+                       // Couldn't open the XML
+                       $this->wellFormed = false;
+               } else {
+                       $oldDisable = libxml_disable_entity_loader( true );
+                       $reader->setParserProperty( XMLReader::SUBST_ENTITIES, true );
+                       try {
+                               $this->validate( $reader );
+                       } catch ( Exception $e ) {
+                               // Calling this malformed, because we didn't parse the whole
+                               // thing. Maybe just an external entity refernce.
+                               $this->wellFormed = false;
+                               $reader->close();
+                               libxml_disable_entity_loader( $oldDisable );
+                               throw $e;
+                       }
+                       $reader->close();
+                       libxml_disable_entity_loader( $oldDisable );
                }
-               return $parser;
        }
 
-       /**
-        * @param string $fname the filename
-        */
-       private function validateFromFile( $fname ) {
-               $parser = $this->getParser();
-
-               if ( file_exists( $fname ) ) {
-                       $file = fopen( $fname, "rb" );
-                       if ( $file ) {
-                               do {
-                                       $chunk = fread( $file, 32768 );
-                                       $ret = xml_parse( $parser, $chunk, feof( $file ) );
-                                       if ( $ret == 0 ) {
-                                               $this->wellFormed = false;
-                                               fclose( $file );
-                                               xml_parser_free( $parser );
-                                               return;
+       private function readNext( XMLReader $reader ) {
+               set_error_handler( array( $this, 'XmlErrorHandler' ) );
+               $ret = $reader->read();
+               restore_error_handler();
+               return $ret;
+       }
+
+       public function XmlErrorHandler( $errno, $errstr ) {
+               $this->wellFormed = false;
+       }
+
+       private function validate( $reader ) {
+
+               // First, move through anything that isn't an element, and
+               // handle any processing instructions with the callback
+               do {
+                       if( !$this->readNext( $reader ) ) {
+                               // Hit the end of the document before any elements
+                               $this->wellFormed = false;
+                               return;
+                       }
+                       if ( $reader->nodeType === XMLReader::PI ) {
+                               $this->processingInstructionHandler( $reader->name, $reader->value );
+                       }
+               } while ( $reader->nodeType != XMLReader::ELEMENT );
+
+               // Process the rest of the document
+               do {
+                       switch ( $reader->nodeType ) {
+                               case XMLReader::ELEMENT:
+                                       $name = $this->expandNS(
+                                               $reader->name,
+                                               $reader->namespaceURI
+                                       );
+                                       if ( $this->rootElement === '' ) {
+                                               $this->rootElement = $name;
                                        }
-                               } while ( !feof( $file ) );
+                                       $empty = $reader->isEmptyElement;
+                                       $attrs = $this->getAttributesArray( $reader );
+                                       $this->elementOpen( $name, $attrs );
+                                       if ( $empty ) {
+                                               $this->elementClose();
+                                       }
+                                       break;
+
+                               case XMLReader::END_ELEMENT:
+                                       $this->elementClose();
+                                       break;
+
+                               case XMLReader::WHITESPACE:
+                               case XMLReader::SIGNIFICANT_WHITESPACE:
+                               case XMLReader::CDATA:
+                               case XMLReader::TEXT:
+                                       $this->elementData( $reader->value );
+                                       break;
 
-                               fclose( $file );
+                               case XMLReader::ENTITY_REF:
+                                       // Unexpanded entity (maybe external?),
+                                       // don't send to the filter (xml_parse didn't)
+                                       break;
+
+                               case XMLReader::COMMENT:
+                                       // Don't send to the filter (xml_parse didn't)
+                                       break;
+
+                               case XMLReader::PI:
+                                       // Processing instructions can happen after the header too
+                                       $this->processingInstructionHandler(
+                                               $reader->name,
+                                               $reader->value
+                                       );
+                                       break;
+                               default:
+                                       // One of DOC, DOC_TYPE, ENTITY, END_ENTITY,
+                                       // NOTATION, or XML_DECLARATION
+                                       // xml_parse didn't send these to the filter, so we won't.
                        }
+
+               } while ( $this->readNext( $reader ) );
+
+               if ( $this->stackDepth !== 0 ) {
+                       $this->wellFormed = false;
+               } elseif ( $this->wellFormed === null ) {
+                       $this->wellFormed = true;
                }
-               $this->wellFormed = true;
 
-               xml_parser_free( $parser );
        }
 
        /**
-        *
-        * @param string $string the XML-input-string to be checked.
+        * Get all of the attributes for an XMLReader's current node
+        * @param $r XMLReader
+        * @return array of attributes
         */
-       private function validateFromString( $string ) {
-               $parser = $this->getParser();
-               $ret = xml_parse( $parser, $string, true );
-               xml_parser_free( $parser );
-               if ( $ret == 0 ) {
-                       $this->wellFormed = false;
-                       return;
+       private function getAttributesArray( XMLReader $r ) {
+               $attrs = array();
+               while ( $r->moveToNextAttribute() ) {
+                       if ( $r->namespaceURI === 'http://www.w3.org/2000/xmlns/' ) {
+                               // XMLReader treats xmlns attributes as normal
+                               // attributes, while xml_parse doesn't
+                               continue;
+                       }
+                       $name = $this->expandNS( $r->name, $r->namespaceURI );
+                       $attrs[$name] = $r->value;
                }
-               $this->wellFormed = true;
+               return $attrs;
        }
 
        /**
-        * @param $parser
-        * @param $name
-        * @param $attribs
+        * @param $name element or attribute name, maybe with a full or short prefix
+        * @param $namespaceURI the namespaceURI
+        * @return string the name prefixed with namespaceURI
         */
-       private function rootElementOpen( $parser, $name, $attribs ) {
-               $this->rootElement = $name;
-
-               if ( is_callable( $this->filterCallback ) ) {
-                       xml_set_element_handler(
-                               $parser,
-                               array( $this, 'elementOpen' ),
-                               array( $this, 'elementClose' )
-                       );
-                       xml_set_character_data_handler( $parser, array( $this, 'elementData' ) );
-                       $this->elementOpen( $parser, $name, $attribs );
-               } else {
-                       // We only need the first open element
-                       xml_set_element_handler( $parser, false, false );
+       private function expandNS( $name, $namespaceURI ) {
+               if ( $namespaceURI ) {
+                       $parts = explode( ':', $name );
+                       $localname = array_pop( $parts );
+                       return "$namespaceURI:$localname";
                }
+               return $name;
        }
 
        /**
-        * @param $parser
         * @param $name
         * @param $attribs
         */
-       private function elementOpen( $parser, $name, $attribs ) {
+       private function elementOpen( $name, $attribs ) {
                $this->elementDataContext[] = array( $name, $attribs );
                $this->elementData[] = '';
                $this->stackDepth++;
        }
 
        /**
-        * @param $parser
-        * @param $name
         */
-       private function elementClose( $parser, $name ) {
+       private function elementClose() {
                list( $name, $attribs ) = array_pop( $this->elementDataContext );
                $data = array_pop( $this->elementData );
                $this->stackDepth--;
 
-               if ( call_user_func(
-                       $this->filterCallback,
-                       $name,
-                       $attribs,
-                       $data
-               ) ) {
-                       // Filter hit!
+               if ( is_callable( $this->filterCallback )
+                       && call_user_func(
+                               $this->filterCallback,
+                               $name,
+                               $attribs,
+                               $data
+                       )
+               ) {
+                       // Filter hit
                        $this->filterMatch = true;
                }
        }
 
        /**
-        * @param $parser
         * @param $data
         */
-       private function elementData( $parser, $data ) {
-               // xml_set_character_data_handler breaks the data on & characters, so
-               // we collect any data here, and we'll run the callback in elementClose
+       private function elementData( $data ) {
+               // Collect any data here, and we'll run the callback in elementClose
                $this->elementData[ $this->stackDepth - 1 ] .= trim( $data );
        }
 
        /**
-        * @param $parser
         * @param $target
         * @param $data
         */
-       private function processingInstructionHandler( $parser, $target, $data ) {
-               if ( call_user_func( $this->parserOptions['processing_instruction_handler'], $target, $data ) ) {
-                       // Filter hit!
-                       $this->filterMatch = true;
+       private function processingInstructionHandler( $target, $data ) {
+               if ( $this->parserOptions['processing_instruction_handler'] ) {
+                       if ( call_user_func(
+                               $this->parserOptions['processing_instruction_handler'],
+                               $target,
+                               $data
+                       ) ) {
+                               // Filter hit!
+                               $this->filterMatch = true;
+                       }
                }
        }
 }
index 267a319..cf9fb53 100644 (file)
 
 /**
  * Implements the default log formatting.
- * Can be overridden by subclassing and setting
- * $wgLogActionsHandlers['type/subtype'] = 'class'; or
- * $wgLogActionsHandlers['type/*'] = 'class';
+ *
+ * Can be overridden by subclassing and setting:
+ *
+ *     $wgLogActionsHandlers['type/subtype'] = 'class'; or
+ *     $wgLogActionsHandlers['type/*'] = 'class';
+ *
  * @since 1.19
  */
 class LogFormatter {
index bb7a1e8..c8d37bb 100644 (file)
@@ -154,7 +154,7 @@ class BitmapMetadataHandler {
         * @throws MWException On invalid file.
         */
        static function Jpeg( $filename ) {
-               $showXMP = function_exists( 'xml_parser_create_ns' );
+               $showXMP = XMPReader::isSupported();
                $meta = new self();
 
                $seg = JpegMetadataExtractor::segmentSplitter( $filename );
@@ -196,7 +196,7 @@ class BitmapMetadataHandler {
         * @return array Array for storage in img_metadata.
         */
        public static function PNG( $filename ) {
-               $showXMP = function_exists( 'xml_parser_create_ns' );
+               $showXMP = XMPReader::isSupported();
 
                $meta = new self();
                $array = PNGMetadataExtractor::getMetadata( $filename );
@@ -236,7 +236,7 @@ class BitmapMetadataHandler {
                        $meta->addMetadata( array( 'GIFFileComment' => $baseArray['comment'] ), 'native' );
                }
 
-               if ( $baseArray['xmp'] !== '' && function_exists( 'xml_parser_create_ns' ) ) {
+               if ( $baseArray['xmp'] !== '' && XMPReader::isSupported() ) {
                        $xmp = new XMPReader();
                        $xmp->parse( $baseArray['xmp'] );
                        $xmpRes = $xmp->getResults();
index 0d8013d..ae4af8d 100644 (file)
@@ -48,7 +48,7 @@ class JpegMetadataExtractor {
         * @throws MWException If given invalid file.
         */
        static function segmentSplitter( $filename ) {
-               $showXMP = function_exists( 'xml_parser_create_ns' );
+               $showXMP = XMPReader::isSupported();
 
                $segmentCount = 0;
 
index 0d341aa..50f04ae 100644 (file)
@@ -80,6 +80,12 @@ class XMPReader {
        /** @var int */
        private $extendedXMPOffset = 0;
 
+       /** @var int Flag determining if the XMP is safe to parse **/
+       private $parsable = 0;
+
+       /** @var string Buffer of XML to parse **/
+       private $xmlParsableBuffer = '';
+
        /**
         * These are various mode constants.
         * they are used to figure out what to do
@@ -108,6 +114,12 @@ class XMPReader {
        const NS_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
        const NS_XML = 'http://www.w3.org/XML/1998/namespace';
 
+       // States used while determining if XML is safe to parse
+       const PARSABLE_UNKNOWN = 0;
+       const PARSABLE_OK = 1;
+       const PARSABLE_BUFFERING = 2;
+       const PARSABLE_NO = 3;
+
        /**
         * Constructor.
         *
@@ -145,6 +157,9 @@ class XMPReader {
                        array( $this, 'endElement' ) );
 
                xml_set_character_data_handler( $this->xmlParser, array( $this, 'char' ) );
+
+               $this->parsable = self::PARSABLE_UNKNOWN;
+               $this->xmlParsableBuffer = '';
        }
 
        /** Destroy the xml parser
@@ -156,6 +171,13 @@ class XMPReader {
                xml_parser_free( $this->xmlParser );
        }
 
+       /**
+        * Check if this instance supports using this class
+        */
+       public static function isSupported() {
+               return function_exists( 'xml_parser_create_ns' ) && class_exists( 'XMLReader' );
+       }
+
        /** Get the result array. Do some post-processing before returning
         * the array, and transform any metadata that is special-cased.
         *
@@ -305,6 +327,27 @@ class XMPReader {
                                wfRestoreWarnings();
                        }
 
+                       // Ensure the XMP block does not have an xml doctype declaration, which
+                       // could declare entities unsafe to parse with xml_parse (T85848/T71210).
+                       if ( $this->parsable !== self::PARSABLE_OK ) {
+                               if ( $this->parsable === self::PARSABLE_NO ) {
+                                       throw new Exception( 'Unsafe doctype declaration in XML.' );
+                               }
+
+                               $content = $this->xmlParsableBuffer . $content;
+                               if ( !$this->checkParseSafety( $content ) ) {
+                                       if ( !$allOfIt && $this->parsable !== self::PARSABLE_NO ) {
+                                               // parse wasn't Unsuccessful yet, so return true
+                                               // in this case.
+                                               return true;
+                                       }
+                                       $msg = ( $this->parsable === self::PARSABLE_NO ) ?
+                                               'Unsafe doctype declaration in XML.' :
+                                               'No root element found in XML.';
+                                       throw new Exception( $msg );
+                               }
+                       }
+
                        $ok = xml_parse( $this->xmlParser, $content, $allOfIt );
                        if ( !$ok ) {
                                $error = xml_error_string( xml_get_error_code( $this->xmlParser ) );
@@ -437,6 +480,62 @@ class XMPReader {
                }
        }
 
+       /**
+        * Check if a block of XML is safe to pass to xml_parse, i.e. doesn't
+        * contain a doctype declaration which could contain a dos attack if we
+        * parse it and expand internal entities (T85848).
+        *
+        * @param string $content xml string to check for parse safety
+        * @return bool true if the xml is safe to parse, false otherwise
+        */
+       private function checkParseSafety( $content ) {
+               $reader = new XMLReader();
+               $result = null;
+
+               // For XMLReader to parse incomplete/invalid XML, it has to be open()'ed
+               // instead of using XML().
+               $reader->open(
+                       'data://text/plain,' . urlencode( $content ),
+                       null,
+                       LIBXML_NOERROR | LIBXML_NOWARNING | LIBXML_NONET
+               );
+
+               $oldDisable = libxml_disable_entity_loader( true );
+               $reset = new ScopedCallback(
+                       'libxml_disable_entity_loader',
+                       array( $oldDisable )
+               );
+               $reader->setParserProperty( XMLReader::SUBST_ENTITIES, false );
+
+               // Even with LIBXML_NOWARNING set, XMLReader::read gives a warning
+               // when parsing truncated XML, which causes unit tests to fail.
+               wfSuppressWarnings();
+               while ( $reader->read() ) {
+                       if ( $reader->nodeType === XMLReader::ELEMENT ) {
+                               // Reached the first element without hitting a doctype declaration
+                               $this->parsable = self::PARSABLE_OK;
+                               $result = true;
+                               break;
+                       }
+                       if ( $reader->nodeType === XMLReader::DOC_TYPE ) {
+                               $this->parsable = self::PARSABLE_NO;
+                               $result = false;
+                               break;
+                       }
+               }
+               wfRestoreWarnings();
+
+               if ( !is_null( $result ) ) {
+                       return $result;
+               }
+
+               // Reached the end of the parsable xml without finding an element
+               // or doctype. Buffer and try again.
+               $this->parsable = self::PARSABLE_BUFFERING;
+               $this->xmlParsableBuffer = $content;
+               return false;
+       }
+
        /** When we hit a closing element in MODE_IGNORE
         * Check to see if this is the element we started to ignore,
         * in which case we get out of MODE_IGNORE
index 0452c41..d96e271 100644 (file)
@@ -3394,12 +3394,15 @@ class WikiPage implements Page, IDBAccessObject {
         * Opportunistically enqueue link update jobs given fresh parser output if useful
         *
         * @param ParserOutput $parserOutput Current version page output
-        * @return bool Whether a job was pushed
         * @since 1.25
         */
        public function triggerOpportunisticLinksUpdate( ParserOutput $parserOutput ) {
                if ( wfReadOnly() ) {
-                       return false;
+                       return;
+               }
+
+               if ( !Hooks::run( 'OpportunisticLinksUpdate', array( $this, $this->mTitle, $parserOutput ) ) ) {
+                       return;
                }
 
                if ( $this->mTitle->areRestrictionsCascading() ) {
@@ -3410,7 +3413,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $params = array();
                } else {
                        // If the inclusions are deterministic, the edit-triggered link jobs are enough
-                       return false;
+                       return;
                }
 
                // Check if the last link refresh was before page_touched
@@ -3418,10 +3421,10 @@ class WikiPage implements Page, IDBAccessObject {
                        JobQueueGroup::singleton()->push( EnqueueJob::newFromLocalJobs(
                                new JobSpecification( 'refreshLinks', $params, array(), $this->mTitle )
                        ) );
-                       return true;
+                       return;
                }
 
-               return false;
+               return;
        }
 
        /**
index 2b495b1..830a68f 100644 (file)
@@ -893,9 +893,17 @@ class CoreParserFunctions {
                }
        }
 
-       // Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}}
-       // or {{filepath|300|nowiki}} or {{filepath|300px}}, {{filepath|200x300px}},
-       // {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}.
+       /**
+        * Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}}
+        * or {{filepath|300|nowiki}} or {{filepath|300px}}, {{filepath|200x300px}},
+        * {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}.
+        *
+        * @param Parser $parser
+        * @param string $name
+        * @param string $argA
+        * @param string $argB
+        * @return array|string
+        */
        public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) {
                $file = wfFindFile( $name );
 
@@ -934,7 +942,7 @@ class CoreParserFunctions {
         * Parser function to extension tag adaptor
         * @param Parser $parser
         * @param PPFrame $frame
-        * @param array $args
+        * @param PPNode[] $args
         * @return string
         */
        public static function tagObj( $parser, $frame, $args ) {
index 3db8d1e..ef295ab 100644 (file)
@@ -33,7 +33,7 @@ class DateFormatter {
        public $regexes, $pDays, $pMonths, $pYears;
        public $rules, $xMonths, $preferences;
 
-       protected $lang;
+       protected $lang, $mLinked;
 
        const ALL = -1;
        const NONE = 0;
index 40b0a4f..7c221d8 100644 (file)
@@ -147,7 +147,11 @@ class Parser {
         */
        public $mSubstWords;
        # Initialised in constructor
-       public $mConf, $mPreprocessor, $mExtLinkBracketedRegex, $mUrlProtocols;
+       public $mConf, $mExtLinkBracketedRegex, $mUrlProtocols;
+
+       # Initialized in getPreprocessor()
+       /** @var Preprocessor */
+       public $mPreprocessor;
 
        # Cleared with clearState():
        /**
@@ -393,7 +397,6 @@ class Parser {
                 */
 
                global $wgShowHostnames;
-               $fname = __METHOD__ . '-' . wfGetCaller();
 
                if ( $clearState ) {
                        $magicScopeVariable = $this->lock();
@@ -1199,7 +1202,7 @@ class Parser {
         *
         * @param string $text
         * @param bool $isMain
-        * @param bool $frame
+        * @param PPFrame|bool $frame
         *
         * @return string
         */
@@ -5427,7 +5430,7 @@ class Parser {
        }
 
        /**
-        * @param string $handler
+        * @param MediaHandler $handler
         * @return array
         */
        public function getImageParams( $handler ) {
index 9e06ee2..5fa52ff 100644 (file)
@@ -669,6 +669,7 @@ class ParserOptions {
         *
         * This ignores report limit settings that only affect HTML comments
         *
+        * @param ParserOptions $other
         * @return bool
         * @since 1.25
         */
index bae3eaa..65b527c 100644 (file)
@@ -57,6 +57,7 @@ class ParserOutput extends CacheTime {
        private $mLimitReportData = array(); # Parser limit report data
        private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
        private $mPreventClickjacking = false; # Whether to emit X-Frame-Options: DENY
+       private $mFlags = array();        # Generic flags
 
        const EDITSECTION_REGEX =
                '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
index 1c9824a..dbf80fa 100644 (file)
@@ -35,20 +35,10 @@ abstract class Profiler {
        protected $templated = false;
        /** @var array All of the params passed from $wgProfiler */
        protected $params = array();
-
+       /** @var IContextSource Current request context */
+       protected $context = null;
        /** @var TransactionProfiler */
        protected $trxProfiler;
-
-       /**
-        * @var array Mapping of output type to class name
-        */
-       private static $outputTypes = array(
-               'db' => 'ProfilerOutputDb',
-               'text' => 'ProfilerOutputText',
-               'udp' => 'ProfilerOutputUdp',
-               'dump' => 'ProfilerOutputDump',
-       );
-
        /** @var Profiler */
        private static $instance = null;
 
@@ -69,17 +59,28 @@ abstract class Profiler {
         */
        final public static function instance() {
                if ( self::$instance === null ) {
-                       global $wgProfiler;
+                       global $wgProfiler, $wgProfileLimit;
+
+                       $params = array(
+                               'class'     => 'ProfilerStub',
+                               'sampling'  => 1,
+                               'threshold' => $wgProfileLimit,
+                               'output'    => array(),
+                       );
                        if ( is_array( $wgProfiler ) ) {
-                               $class = isset( $wgProfiler['class'] ) ? $wgProfiler['class'] : 'ProfilerStub';
-                               $factor = isset( $wgProfiler['sampling'] ) ? $wgProfiler['sampling'] : 1;
-                               if ( PHP_SAPI === 'cli' || mt_rand( 0, $factor - 1 ) != 0 ) {
-                                       $class = 'ProfilerStub';
-                               }
-                               self::$instance = new $class( $wgProfiler );
-                       } else {
-                               self::$instance = new ProfilerStub( array() );
+                               $params = array_merge( $params, $wgProfiler );
+                       }
+
+                       $inSample = mt_rand( 0, $params['sampling'] - 1 ) === 0;
+                       if ( PHP_SAPI === 'cli' || !$inSample ) {
+                               $params['class'] = 'ProfilerStub';
+                       }
+
+                       if ( !is_array( $params['output'] ) ) {
+                               $params['output'] = array( $params['output'] );
                        }
+
+                       self::$instance = new $params['class']( $params );
                }
                return self::$instance;
        }
@@ -117,6 +118,32 @@ abstract class Profiler {
                }
        }
 
+       /**
+        * Sets the context for this Profiler
+        *
+        * @param IContextSource $context
+        * @since 1.25
+        */
+       public function setContext( $context ) {
+               $this->context = $context;
+       }
+
+       /**
+        * Gets the context for this Profiler
+        *
+        * @return IContextSource
+        * @since 1.25
+        */
+       public function getContext() {
+               if ( $this->context ) {
+                       return $this->context;
+               } else {
+                       wfDebug( __METHOD__ . " called and \$context is null. " .
+                               "Return RequestContext::getMain(); for sanity\n" );
+                       return RequestContext::getMain();
+               }
+       }
+
        // Kept BC for now, remove when possible
        public function profileIn( $functionname ) {}
        public function profileOut( $functionname ) {}
@@ -152,37 +179,54 @@ abstract class Profiler {
        abstract public function close();
 
        /**
-        * Log the data to some store or even the page output
+        * Get all usable outputs.
         *
         * @throws MWException
+        * @return array Array of ProfilerOutput instances.
+        * @since 1.25
+        */
+       private function getOutputs() {
+               $outputs = array();
+               foreach ( $this->params['output'] as $outputType ) {
+                       // The class may be specified as either the full class name (for
+                       // example, 'ProfilerOutputUdp') or (for backward compatibility)
+                       // the trailing portion of the class name (for example, 'udp').
+                       $outputClass = strpos( $outputType, 'ProfilerOutput' ) === false
+                               ? 'ProfilerOutput' . ucfirst( $outputType )
+                               : $outputType;
+                       if ( !class_exists( $outputClass ) ) {
+                               throw new MWException( "'$outputType' is an invalid output type" );
+                       }
+                       $outputInstance = new $outputClass( $this, $this->params );
+                       if ( $outputInstance->canUse() ) {
+                               $outputs[] = $outputInstance;
+                       }
+               }
+               return $outputs;
+       }
+
+       /**
+        * Log the data to some store or even the page output
+        *
         * @since 1.25
         */
        public function logData() {
-               $output = isset( $this->params['output'] ) ? $this->params['output'] : null;
+               $request = $this->getContext()->getRequest();
 
-               if ( !$output || $this instanceof ProfilerStub ) {
-                       // return early when no output classes defined or we're a stub
+               $timeElapsed = $request->getElapsedTime();
+               $timeElapsedThreshold = $this->params['threshold'];
+               if ( $timeElapsed <= $timeElapsedThreshold ) {
                        return;
                }
 
-               if ( !is_array( $output ) ) {
-                       $output = array( $output );
+               $outputs = $this->getOutputs();
+               if ( !$outputs ) {
+                       return;
                }
-               $stats = null;
-               foreach ( $output as $outType ) {
-                       if ( !isset( self::$outputTypes[$outType] ) ) {
-                               throw new MWException( "'$outType' is an invalid output type" );
-                       }
-                       $class = self::$outputTypes[$outType];
 
-                       /** @var ProfilerOutput $profileOut */
-                       $profileOut = new $class( $this, $this->params );
-                       if ( $profileOut->canUse() ) {
-                               if ( is_null( $stats ) ) {
-                                       $stats = $this->getFunctionStats();
-                               }
-                               $profileOut->log( $stats );
-                       }
+               $stats = $this->getFunctionStats();
+               foreach ( $outputs as $output ) {
+                       $output->log( $stats );
                }
        }
 
index 1d04536..244b4e4 100644 (file)
@@ -43,4 +43,7 @@ class ProfilerStub extends Profiler {
        public function getCurrentSection() {
                return '';
        }
+
+       public function logData() {
+       }
 }
index b313558..baec181 100644 (file)
@@ -22,6 +22,9 @@
  * @author Aaron Schulz
  */
 
+use Psr\Log\LoggerInterface;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\NullLogger;
 /**
  * Helper class that detects high-contention DB queries via profiling calls
  *
@@ -29,7 +32,7 @@
  *
  * @since 1.24
  */
-class TransactionProfiler {
+class TransactionProfiler implements LoggerAwareInterface {
        /** @var float Seconds */
        protected $dbLockThreshold = 3.0;
        /** @var float Seconds */
@@ -58,6 +61,19 @@ class TransactionProfiler {
        /** @var array */
        protected $expectBy = array();
 
+       /**
+        * @var LoggerInterface
+        */
+       private $logger;
+
+       public function __construct() {
+               $this->setLogger( new NullLogger() );
+       }
+
+       public function setLogger( LoggerInterface $logger ) {
+               $this->logger = $logger;
+       }
+
        /**
         * Set performance expectations
         *
@@ -125,7 +141,7 @@ class TransactionProfiler {
        public function transactionWritingIn( $server, $db, $id ) {
                $name = "{$server} ({$db}) (TRX#$id)";
                if ( isset( $this->dbTrxHoldingLocks[$name] ) ) {
-                       wfDebugLog( 'DBPerformance', "Nested transaction for '$name' - out of sync." );
+                       $this->logger->info( "Nested transaction for '$name' - out of sync." );
                }
                $this->dbTrxHoldingLocks[$name] = array(
                        'start' => microtime( true ),
@@ -154,8 +170,7 @@ class TransactionProfiler {
                $elapsed = ( $eTime - $sTime );
 
                if ( $isWrite && $n > $this->expect['maxAffected'] ) {
-                       wfDebugLog( 'DBPerformance',
-                               "Query affected $n row(s):\n" . $query . "\n" . wfBacktrace( true ) );
+                       $this->logger->info( "Query affected $n row(s):\n" . $query . "\n" . wfBacktrace( true ) );
                }
 
                // Report when too many writes/queries happen...
@@ -209,7 +224,7 @@ class TransactionProfiler {
        public function transactionWritingOut( $server, $db, $id ) {
                $name = "{$server} ({$db}) (TRX#$id)";
                if ( !isset( $this->dbTrxMethodTimes[$name] ) ) {
-                       wfDebugLog( 'DBPerformance', "Detected no transaction for '$name' - out of sync." );
+                       $this->logger->info( "Detected no transaction for '$name' - out of sync." );
                        return;
                }
                // Fill in the last non-query period...
@@ -237,7 +252,7 @@ class TransactionProfiler {
                                list( $query, $sTime, $end ) = $info;
                                $msg .= sprintf( "%d\t%.6f\t%s\n", $i, ( $end - $sTime ), $query );
                        }
-                       wfDebugLog( 'DBPerformance', $msg );
+                       $this->logger->info( $msg );
                }
                unset( $this->dbTrxHoldingLocks[$name] );
                unset( $this->dbTrxMethodTimes[$name] );
@@ -250,7 +265,8 @@ class TransactionProfiler {
        protected function reportExpectationViolated( $expect, $query ) {
                $n = $this->expect[$expect];
                $by = $this->expectBy[$expect];
-               wfDebugLog( 'DBPerformance',
-                       "Expectation ($expect <= $n) by $by not met:\n$query\n" . wfBacktrace( true ) );
+               $this->logger->info(
+                       "Expectation ($expect <= $n) by $by not met:\n$query\n" . wfBacktrace( true )
+               );
        }
 }
diff --git a/includes/profiler/output/ProfilerOutputStats.php b/includes/profiler/output/ProfilerOutputStats.php
new file mode 100644 (file)
index 0000000..ef6ef7c
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * ProfilerOutput class that flushes profiling data to the profiling
+ * context's stats buffer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Profiler
+ */
+
+/**
+ * ProfilerOutput class that flushes profiling data to the profiling
+ * context's stats buffer.
+ *
+ * @ingroup Profiler
+ * @since 1.25
+ */
+class ProfilerOutputStats extends ProfilerOutput {
+
+       /**
+        * Flush profiling data to the current profiling context's stats buffer.
+        *
+        * @param array $stats
+        */
+       public function log( array $stats ) {
+               $contextStats = $this->collector->getContext()->getStats();
+
+               foreach ( $stats as $stat ) {
+                       // Sanitize the key
+                       $key = str_replace( '::', '.', $stat['name'] );
+                       $key = preg_replace( '/[^a-z.]+/i', '_', $key );
+                       $key = trim( $key, '_.' );
+
+                       // Convert fractional seconds to whole milliseconds
+                       $cpu = round( $stat['cpu'] * 1000 );
+                       $real = round( $stat['real'] * 1000 );
+
+                       $contextStats->increment( "{$key}.calls" );
+                       $contextStats->timing( "{$key}.cpu", $cpu );
+                       $contextStats->timing( "{$key}.real", $real );
+               }
+       }
+}
index 5eab3cb..b9d1b2b 100644 (file)
@@ -72,6 +72,11 @@ class ResourceLoader {
         */
        protected $errors = array();
 
+       /**
+        * @var MessageBlobStore
+        */
+       protected $blobStore;
+
        /**
         * Load information stored in the database about modules.
         *
@@ -250,6 +255,7 @@ class ResourceLoader {
                        $this->registerTestModules();
                }
 
+               $this->setMessageBlobStore( new MessageBlobStore() );
        }
 
        /**
@@ -259,6 +265,14 @@ class ResourceLoader {
                return $this->config;
        }
 
+       /**
+        * @param MessageBlobStore $blobStore
+        * @since 1.25
+        */
+       public function setMessageBlobStore( MessageBlobStore $blobStore ) {
+               $this->blobStore = $blobStore;
+       }
+
        /**
         * Register a module with the ResourceLoader system.
         *
@@ -885,7 +899,7 @@ MESSAGE;
                // Pre-fetch blobs
                if ( $context->shouldIncludeMessages() ) {
                        try {
-                               $blobs = MessageBlobStore::getInstance()->get( $this, $modules, $context->getLanguage() );
+                               $blobs = $this->blobStore->get( $this, $modules, $context->getLanguage() );
                        } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                wfDebugLog(
index 88ba597..bf6a7dd 100644 (file)
@@ -253,7 +253,6 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                        );
                        $rules[] = "$selector {\n\t$declarations\n}";
 
-                       // TODO: Get variant configurations from $context->getSkin()
                        foreach ( $image->getVariants() as $variant ) {
                                $declarations = $this->getCssDeclarations(
                                        $image->getDataUri( $context, $variant, 'original' ),
@@ -273,9 +272,6 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                }
 
                $style = implode( "\n", $rules );
-               if ( $this->getFlip( $context ) ) {
-                       $style = CSSJanus::transform( $style, true, false );
-               }
                return array( 'all' => $style );
        }
 
index 20aac18..75ff8f3 100644 (file)
@@ -68,8 +68,9 @@ class LinkSearchPage extends QueryPage {
         * This allows for dependency injection even though we don't control object creation.
         */
        private function initServices() {
+               global $wgLanguageCode;
                if ( !$this->linkRenderer ) {
-                       $lang = $this->getContext()->getLanguage();
+                       $lang = Language::factory( $wgLanguageCode );
                        $titleFormatter = new MediaWikiTitleCodec( $lang, GenderCache::singleton() );
                        $this->linkRenderer = new MediaWikiPageLinkRenderer( $titleFormatter );
                }
index 55be2c2..608d62e 100644 (file)
@@ -533,7 +533,7 @@ class SpecialSearch extends SpecialPage {
                                $request->getVal( 'nsRemember' ),
                                'searchnamespace',
                                $request
-                       )
+                       ) && !wfReadOnly()
                ) {
                        // Reset namespace preferences: namespaces are not searched
                        // when they're not mentioned in the URL parameters.
index 44240d8..10edbcf 100644 (file)
@@ -545,14 +545,11 @@ class LoginForm extends SpecialPage {
                                return Status::newFatal( 'badretype' );
                        }
 
-                       # check for minimal password length
-                       $valid = $u->getPasswordValidity( $this->mPassword );
-                       if ( $valid !== true ) {
-                               if ( !is_array( $valid ) ) {
-                                       $valid = array( $valid, $wgMinimalPasswordLength );
-                               }
-
-                               return call_user_func_array( 'Status::newFatal', $valid );
+                       # check for password validity, return a fatal Status if invalid
+                       $validity = $u->checkPasswordValidity( $this->mPassword );
+                       if ( !$validity->isGood() ) {
+                               $validity->ok = false; // make sure this Status is fatal
+                               return $validity;
                        }
                }
 
@@ -765,7 +762,7 @@ class LoginForm extends SpecialPage {
                                // As a side-effect, we can authenticate the user's e-mail ad-
                                // dress if it's not already done, since the temporary password
                                // was sent via e-mail.
-                               if ( !$u->isEmailConfirmed() ) {
+                               if ( !$u->isEmailConfirmed() && !wfReadOnly() ) {
                                        $u->confirmEmail();
                                        $u->saveSettings();
                                }
index a79526e..6da8250 100644 (file)
@@ -1412,27 +1412,22 @@ abstract class UploadBase {
                                }
                        }
 
-                       # href with embedded svg as target
-                       if ( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) {
-                               wfDebug( __METHOD__ . ": Found href to embedded svg "
-                                       . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
-
-                               return true;
-                       }
-
-                       # href with embedded (text/xml) svg as target
-                       if ( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) {
-                               wfDebug( __METHOD__ . ": Found href to embedded svg "
-                                       . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
-
-                               return true;
+                       # only allow data: targets that should be safe. This prevents vectors like,
+                       # image/svg, text/xml, application/xml, and text/html, which can contain scripts
+                       if ( $stripped == 'href' && strncasecmp( 'data:', $value, 5 ) === 0 ) {
+                               // rfc2397 parameters. This is only slightly slower than (;[\w;]+)*.
+                               $parameters = '(?>;[a-zA-Z0-9\!#$&\'*+.^_`{|}~-]+=(?>[a-zA-Z0-9\!#$&\'*+.^_`{|}~-]+|"(?>[\0-\x0c\x0e-\x21\x23-\x5b\x5d-\x7f]+|\\\\[\0-\x7f])*"))*(?:;base64)?';
+                               if ( !preg_match( "!^data:\s*image/(gif|jpeg|jpg|png)$parameters,!i", $value ) ) {
+                                       wfDebug( __METHOD__ . ": Found href to unwhitelisted data: uri "
+                                               . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+                                       return true;
+                               }
                        }
 
-                       # Change href with animate from (http://html5sec.org/#137). This doesn't seem
-                       # possible without embedding the svg, but filter here in case.
-                       if ( $stripped == 'from'
+                       # Change href with animate from (http://html5sec.org/#137).
+                       if ( $stripped === 'attributename'
                                && $strippedElement === 'animate'
-                               && !preg_match( '!^https?://!im', $value )
+                               && $this->stripXmlNamespace( $value ) == 'href'
                        ) {
                                wfDebug( __METHOD__ . ": Found animate that might be changing href using from "
                                        . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
@@ -1524,7 +1519,7 @@ abstract class UploadBase {
        private static function checkCssFragment( $value ) {
 
                # Forbid external stylesheets, for both reliability and to protect viewer's privacy
-               if ( strpos( $value, '@import' ) !== false ) {
+               if ( stripos( $value, '@import' ) !== false ) {
                        return true;
                }
 
index 22cef7e..e4cc918 100644 (file)
@@ -4,7 +4,8 @@
                        "Anshumangupta21",
                        "Ganesh",
                        "Nepaboy",
-                       "Rajivkurjee"
+                       "Rajivkurjee",
+                       "SatyamMishra"
                ]
        },
        "tog-underline": "लिंक के नीचे रेखा",
@@ -12,7 +13,7 @@
        "tog-hidepatrolled": "हाल के परिवर्तन में मामूली संपादन छुपाईं",
        "tog-newpageshidepatrolled": "नयका पृष्ठ के सूची में से जाँचल पृष्क के छुपाँई",
        "tog-extendwatchlist": "मात्र हाल के परिवर्तन ही नाही,बल्कि सब परिवर्तन के देखावे खातिर ध्यान सूची के विस्तारित करीं",
-       "tog-usenewrc": "तà¥\81रà¤\82त à¤­à¤\88ल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤®à¥\87à¤\82 à¤\86 à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤­à¤\88ल परिवर्तनन के पन्ना अनुसार समूह में बांटी",
+       "tog-usenewrc": "तà¥\81रà¤\82त à¤­à¤\87ल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤®à¥\87à¤\82 à¤\86 à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤­à¤\87ल परिवर्तनन के पन्ना अनुसार समूह में बांटी",
        "tog-numberheadings": "स्वयं-सांख्यिकी शिर्षक",
        "tog-showtoolbar": "सम्पादन औजारपट्टी के दिखावल जाव",
        "tog-editondblclick": "दुई क्लिक पर पन्ना संपादन करीं",
        "youhavenewmessagesmulti": "रउआ लगे $1 पर नया सन्देश बा",
        "editsection": "सम्पादन",
        "editold": "सम्पादन",
-       "viewsourceold": "सà¥\8dतà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80à¤\82",
+       "viewsourceold": "स्रोत देखीं",
        "editlink": "सम्पादन",
-       "viewsourcelink": "सà¥\8dतà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80à¤\82",
+       "viewsourcelink": "स्रोत देखीं",
        "editsectionhint": "सम्पादन खण्ड: $1",
        "toc": "सामग्री",
        "showtoc": "देखाईं",
        "perfcached": "नीचे दिहल गइल डेटा कैशे मेमोरी से लिहल गइल बा, अतः हो सकता बा कि इ के पूर्ण अद्यतन ना भइल होखे। कैशे मेमोरी में अधिकतम {{PLURAL:$1|एक  नतीजा|$1 नतीजं}} उपलब्ध बाड़े।",
        "perfcachedts": "नीचे दिहल गइल डेटा कैशे मेमोरी से बा, आ एकर अंतिम अपडेट $1 के भइल रहल। कैश मेमोरी में अधिकतम {{PLURAL:$4|एक  नतीजा|$4 नतीजां}} उपलब्ध बा।",
        "querypage-no-updates": "इ पृष्ठ के अपडेट करल अयोग्य बा। अभी अहिजा के डाटा के ताज़ा नइखे करल जा सकत।",
-       "viewsource": "सà¥\8dतà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80à¤\82",
+       "viewsource": "स्रोत देखीं",
        "viewsource-title": "$1 के स्रोत देखीं",
        "actionthrottled": "कार्य समाप्त कर दिहल गइल बा",
        "actionthrottledtext": "स्पैम के रोकथाम खातिर, इ क्रिया एतना कम समय में एक सीमा से अधिक बार करे के मना बा, आ रउआ इ सीमा के पार कर चुकल बानी।\nकृपया कुछ समय बाद पुन: यत्न करीं।",
        "protectedpagetext": "इ पन्ना संपादन आ अन्य कार्यं से बचाव खातिर सुरक्षित कर दिहल गइल बा।",
-       "viewsourcetext": "रà¤\89à¤\86 à¤\87 à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸à¥\8dत्रोत देख सकत बानी आ एकर नकल उतार सकत बानी:",
+       "viewsourcetext": "रà¤\89à¤\86 à¤\8fह à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸्रोत देख सकत बानी आ एकर नकल उतार सकत बानी:",
        "viewyourtext": "रउआ इ पन्ना में ''आपन सम्पादन'' के स्रोत देख सकत बानी आ ओकर नकल उतार सकत बानी:",
        "protectedinterface": "इ पन्ना इ विकी के सॉफ़्टवेयर के इंटरफ़ेस पाठ्य के देवेला, आ इ के गलत प्रयोग से बचावे खातिर सुरक्षित कर दिहल गइल बा।\nसभन विकियन खातिर अनुवाद जोड़े या बदले खातिर कृपया मीडियाविकि के क्षेत्रीयकरण प्रकल्प [//translatewiki.net/ translatewiki.net] के प्रयोग करीं।",
        "editinginterface": "<strong>चेतावनी:</strong> आप एगो अइसन पन्ना के बदल बदल रहल बानी जवन सॉफ़्टवेयर के इंटरफ़ेस पाठ प्रदान करेला। इ पृष्ठ के बदले से अन्य सदस्यवन के प्रदर्शित इंटरफ़ेस के शक्लोसूरत में बदलाव आई।",
        "revdelete-reasonotherlist": "अन्य कारण",
        "revdelete-edit-reasonlist": "हटावे के कारण बदलीं",
        "revdelete-offender": "संशोधन सम्पादक:",
-       "mergehistory-from": "सà¥\8dतà¥\8dरà¥\8bत à¤ªà¤¨à¥\8dना:",
+       "mergehistory-from": "स्रोत पन्ना:",
        "mergehistory-reason": "कारण:",
        "revertmerge": "अलग करीं",
-       "mergelogpagetext": "à¤\8fà¤\95 à¤ªà¤¨à¥\8dना à¤\87तिहास à¤\95à¥\87 à¤¦à¥\81सर à¤ªà¤¨à¥\8dना à¤\87तिहास à¤®à¥\87à¤\82 à¤¤à¥\81रà¤\82त à¤µà¤¿à¤²à¤¯ à¤­à¤\88ल एगो सूची नीचे दिहल बा।",
+       "mergelogpagetext": "à¤\8fà¤\95 à¤ªà¤¨à¥\8dना à¤\87तिहास à¤\95à¥\87 à¤¦à¥\81सर à¤ªà¤¨à¥\8dना à¤\87तिहास à¤®à¥\87à¤\82 à¤¤à¥\81रà¤\82त à¤µà¤¿à¤²à¤¯ à¤­à¤\87लà¥\87 à¤\95à¥\87 एगो सूची नीचे दिहल बा।",
        "history-title": "''$1'' के संशोधन इतिहास",
        "lineno": "पंक्ति $1:",
        "compareselectedversions": "चुनल गईल संशोधन में अन्तर देखीं",
        "datedefault": "वरीयता नईखे",
        "prefs-user-pages": "सदस्य पन्ना",
        "prefs-personal": "सदस्य प्रोफाईल",
-       "prefs-rc": "तà¥\81रà¤\82त à¤­à¤\88ल परिवर्तन",
+       "prefs-rc": "तà¥\81रà¤\82त à¤­à¤\87ल परिवर्तन",
        "saveprefs": "सुरक्षित करीं",
        "prefs-editing": "संपादन",
        "searchresultshead": "खोज",
        "prefs-preview": "पूर्वावलोकन",
        "action-move": "ई पन्ना के स्थांतरण करीं",
        "action-delete": "ई पन्ना के मिटाईं",
-       "recentchanges": "तà¥\81रà¤\82त à¤­à¤\88ल परिवर्तन",
+       "recentchanges": "तà¥\81रà¤\82त à¤­à¤\87ल परिवर्तन",
        "recentchanges-legend": "हाल के परिवर्तन संबंधी विकल्प",
        "recentchanges-label-newpage": "ई सम्पादन से एगो नवका पृष्ठ तैयार हो गइल बा",
        "recentchanges-label-minor": "ई एगो छोटा सम्पाद बा",
        "newpages": "नवका पन्ना",
        "move": "स्थान्तरण",
        "movethispage": "ई पन्ना के स्थांतरण करीं",
-       "booksources": "à¤\95िताबà¥\80 à¤¸à¥\8dतà¥\8dरà¥\8bत",
+       "booksources": "किताबी स्रोत",
        "allarticles": "सभी पन्ना",
        "allpagessubmit": "जाईं",
        "allpagesprefix": "उपसर्ग के साथे पन्ना प्रदर्शन:",
index afbda42..569dbef 100644 (file)
        "preview": "Rakwelet",
        "showpreview": "Rakwelet",
        "showdiff": "Diskouez ar c'hemmoù",
-       "anoneditwarning": "'''Diwallit :''' N'oc'h ket kevreet. \nHo chomlec'h IP eo a vo enrollet war istor kemmoù ar bajenn-mañ.",
+       "anoneditwarning": "</strong>Diwallit :</strong> N'oc'h ket kevreet.\nGallout a raio an holl dud gwelet ho chomlec'h IP ma rit kemmoù. Ma <strong>[$1kevreit]</strong>pe<strong>[$2 krouit ur gont]</strong>, e vo deroet ho kemmoù d'hoc'h anv-implijer, e-touez spletoù all.",
        "anonpreviewwarning": "''N'oc'h ket kevreet. Enrollañ a lakao war-wel ho chomlec'h IP e istor kemmoù ar bajenn.''",
        "missingsummary": "'''Taolit evezh:''' N'hoc'h eus ket lakaet tamm testenn diverrañ ebet evit ho kemmoù. Mar klikit war enrollañ en-dro, e vo enrollet ho testenn evel m'emañ hepmuiken.",
        "missingcommenttext": "Skrivit hoc'h evezhiadenn a-is.",
        "upload-curl-error28": "Aet dreist d'an termen",
        "upload-curl-error28-text": "Re bell eo bet al lec'hienn o respont. Gwiriit mat emañ al lec'hienn enlinenn, gortozit ur pennadig ha klaskit en-dro. Mat e vo deoc'h adklask d'ur mare dibresoc'h marteze ivez.",
        "license": "Aotre-implijout :",
-       "license-header": "Aotre implijout",
+       "license-header": "Aotre-implijout",
        "nolicense": "Hini ebet diuzet",
        "licenses-edit": "Aozañ dibarzhioù an aotre-implijout",
        "license-nopreview": "(Dibosupl rakwelet)",
        "tooltip-pt-mycontris": "Roll ho tegasadennoù",
        "tooltip-pt-login": "Daoust ma n'eo ket ret, ec'h aliomp deoc'h kevreañ",
        "tooltip-pt-logout": "Digevreañ",
+       "tooltip-pt-createaccount": "Erbedet eo deoc'h krouiñ ur gont ha kevreañ ; n'eo ket ret koulskoude.",
        "tooltip-ca-talk": "Kaozeadennoù diwar-benn ar pennad",
        "tooltip-ca-edit": "Gallout a rit kemmañ ar bajenn-mañ. Implijit ar stokell Rakwelet a-raok enrollañ, mar plij.",
        "tooltip-ca-addsection": "Kregiñ gant ur rann nevez.",
index ae337ca..db735db 100644 (file)
        "wrongpassword": "Bylo zadáno nesprávné heslo.\nZkuste to znovu.",
        "wrongpasswordempty": "Bylo zadáno prázdné heslo. Zkuste to znovu.",
        "passwordtooshort": "Heslo musí být dlouhé nejméně $1 {{PLURAL:$1|znak|znaky|znaků}}.",
+       "passwordtoolong": "Hesla nemohou být delší než {{PLURAL:$1|1 znak|$1 znaky|$1 znaků}}.",
        "password-name-match": "Vaše heslo nesmí být stejné jako uživatelské jméno.",
        "password-login-forbidden": "Použití tohoto uživatelského jména a hesla bylo zakázáno.",
        "mailmypassword": "Poslat nové heslo",
index 6f1ccb0..c9ae95e 100644 (file)
        "oct": "Юпа",
        "nov": "Чӳк",
        "dec": "Раш",
-       "pagecategories": "{{PLURAL:$1|1=Категори|Категорисем}}",
+       "pagecategories": "{{PLURAL:$1|Категори|Категорисем}}",
        "category_header": "«$1» категорири статьясем",
        "subcategories": "Подкатегорисем",
        "category-media-header": "«$1» категорири файлсем",
        "category-empty": "''Хальхи вăхăтра ку категори пушă.''",
-       "hidden-categories": "{{PLURAL:$1|1=Пытарнă категори|Пытарнă категорисем}}",
+       "hidden-categories": "{{PLURAL:$1|Пытарнă категори|Пытарнă категорисем}}",
        "hidden-category-category": "Пытарнă категорисем",
        "category-subcat-count": "{{PLURAL:$2|Ку категоринче çак айри категори пур.|$2-ран(-рен,-тан,-тен) {{PLURAL:$1|$1 айри категорине кăтартнă|$1 айри категорине кăтартнă|$1 айри категорине кăтартнă}}.}}",
        "category-subcat-count-limited": "Ку категоринче {{PLURAL:$1|$1 айри категори|$1 айри категори|$1 айри категори}}.",
        "newwindow": "(çĕнĕ чӳречере)",
        "cancel": "Пăрахăçла",
        "moredotdotdot": "Малалла…",
-       "mypage": "Ð\9cан Ñ\81траница",
+       "mypage": "Страница",
        "mytalk": "Сӳтсе явни",
        "anontalk": "Çак IP-адреса сӳтсе явни",
        "navigation": "Меню",
        "last": "малт.",
        "page_first": "пĕрремĕш",
        "page_last": "юлашки",
+       "history-fieldset-title": "Историне пăх",
        "histfirst": "Пĕрремĕш",
        "histlast": "Юлашки",
        "historysize": "({{PLURAL:$1|1 байт|$1 байт}})",
        "recentchanges-label-bot": "Ку улшăнăва бот тунă",
        "recentchanges-legend-newpage": "$1 — çĕнĕ страница",
        "rclistfrom": "Юлашки улшăнусене $3 $2 вăхăтран пуçласа кăтартнă",
-       "rcshowhideminor": "пĕчĕк тӳрлетӳсене $1",
-       "rcshowhidebots": "$1 ботсене",
+       "rcshowhideminor": "пĕчĕк тӳрлетнисене $1",
+       "rcshowhidebots": "ботсене $1",
        "rcshowhidebots-show": "Кăтарт",
-       "rcshowhideliu": "сайта кĕнĕскерсене $1",
+       "rcshowhideliu": "сайта кĕнисене $1",
        "rcshowhideanons": "ячĕсене палăртманскерсене $1",
        "rcshowhidepatr": "тĕрĕсленĕ тӳрлетӳсене $1",
-       "rcshowhidemine": "хăвăн тӳрлетӳсене $1",
+       "rcshowhidemine": "хăвăн тӳрлетнисене $1",
        "rclinks": "Юлашки $2 кун хушшинче тунă $1 улшăнусене кăтартмалла<br />$3",
        "diff": "танл.",
        "hist": "ист",
        "fewestrevisions": "Сахал тӳрлетнĕ статьясем",
        "nbytes": "$1 {{PLURAL:$1|1=байт|байт}}",
        "nlinks": "$1 {{PLURAL:$1|1=каçă|каçă}}",
-       "nviews": "$1 хут пăхнă",
+       "nviews": "$1 {{PLURAL:$1|пăхни|пăхнисем}}",
        "specialpage-empty": "Ку страница пушă",
        "lonelypages": "Тăлăх страницăсем",
        "uncategorizedpages": "Каталогсăр страницăсем",
        "emailsenttext": "Сирĕн электронлă çырăва леçрĕмĕр.",
        "watchlist": "Пăхса тăракан страницăсем ят-йышĕ",
        "mywatchlist": "Сăнаса тăракан списокĕ",
-       "watchlistfor2": "$1 $2 валли",
+       "watchlistfor2": "$1 валли $2",
        "nowatchlist": "Эсир пăхса тăракан страницăсен списокĕ пушă.",
        "watchnologin": "Системăна хăвăр ята каламалла",
        "addedwatchtext": "«[[:$1]]» страницăна сирĕн [[Special:Watchlist|сăнав списока]] хушрăмăр. Малашне [[Special:RecentChanges|юлашки улшăнусене кăтартакан страницăра]] унпа çыхăннă улшăнусене хылăм шрифтпа курăнĕç.\nЕнчен те сирĕн ку страницăна сăнас кăмăл пĕтсен, «ан сăна» пускăч çине пусăр.",
        "searchsuggest-search": "Шырамалли",
        "pagelang-select-lang": "Чĕлхе суйлăр",
        "mediastatistics-header-audio": "Аудио",
-       "mediastatistics-header-video": "Видеосем"
+       "mediastatistics-header-video": "Видеосем",
+       "special-characters-group-symbols": "Символсем"
 }
index c5bd8e9..f765cab 100644 (file)
        "wrongpassword": "Das Passwort ist falsch. Bitte versuche es erneut.",
        "wrongpasswordempty": "Es wurde kein Passwort eingegeben. Bitte versuche es erneut.",
        "passwordtooshort": "Passwörter müssen mindestens {{PLURAL:$1|1 Zeichen|$1 Zeichen}} lang sein.",
+       "passwordtoolong": "Passwörter können nicht länger als {{PLURAL:$1|ein|$1}} Zeichen sein.",
        "password-name-match": "Dein Passwort muss sich von deinem Benutzernamen unterscheiden.",
        "password-login-forbidden": "Die Verwendung dieses Benutzernamens und Passwortes ist nicht erlaubt.",
        "mailmypassword": "Passwort zurücksetzen",
        "notextmatches": "Keine Übereinstimmungen mit Inhalten",
        "prevn": "{{PLURAL:$1|vorheriger|vorherige $1}}",
        "nextn": "{{PLURAL:$1|nächster|nächste $1}}",
+       "prev-page": "vorherige Seite",
+       "next-page": "nächste Seite",
        "prevn-title": "{{PLURAL:$1|Vorheriges Ergebnis|Vorherige $1 Ergebnisse}}",
        "nextn-title": "{{PLURAL:$1|Folgendes Ergebnis|Folgende $1 Ergebnisse}}",
        "shown-title": "Zeige $1 {{PLURAL:$1|Ergebnis|Ergebnisse}} pro Seite",
index c7182a9..a497dec 100644 (file)
        "hidetoc": "bınımne",
        "collapsible-collapse": "Kılm ke",
        "collapsible-expand": "Hera ke",
-       "thisisdeleted": "Bıvêne ya zi $1 peyser bia?",
+       "thisisdeleted": "Bıvêne ya zi $1 peyser biya?",
        "viewdeleted": "$1 bıvêne?",
        "restorelink": "{{PLURAL:$1|jew vurnayış besteriya|$1 vurnayışi besteriyaye}}",
        "feedlinks": "Warikerdış:",
        "rev-suppressed-diff-view": "Jew timarkerdışê ena versiyon '''Ploxneyış'' biyo.\nÎdarekarî eşkeno ena dif bivîne; belki tiya de [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ploxnayış] de teferruat esto.",
        "rev-delundel": "bımocne/bınımne",
        "rev-showdeleted": "bımocne",
-       "revisiondelete": "Bestere/çımraviyarnayışan peyser bia",
+       "revisiondelete": "Çımraviyarnayışan bestere/peyser biya",
        "revdelete-nooldid-title": "Çımraviyarnayışo waşte nêvêreno",
        "revdelete-nooldid-text": "Şıma vıraştışê nê fonksiyoni rê ya yew çımraviyarnayışo waşte diyar nêkerdo, çımraviyarnayışo diyarkerde çıniyo, ya ki şıma wazenê ke çımraviyarnayışê nıkayêni bınımnê.",
        "revdelete-no-file": "Dosya diyarkerdiye çıniya.",
        "right-move-rootuserpages": "Pelanê kaberiê rıstımi bere",
        "right-movefile": "Dosyan bere",
        "right-suppressredirect": "Wexto ke pelan benê, pelanê çımey ra neql mevıraze",
-       "right-upload": "Dosya bar bıke",
+       "right-upload": "Dosyeyan bar ke",
        "right-reupload": "Dosyeyê ke estê, inan serde bınuse",
        "right-reupload-own": "Dosyeyê ke to bar kerdi, inan sero bınuse",
        "right-reupload-shared": "Dosyeyê ke ambarê medyao barekerde de, inan mehelli wedare",
-       "right-upload_by_url": "Yew URL ra dosyan bar bıke",
+       "right-upload_by_url": "Yew URL ra dosyeyan bar ke",
        "right-purge": "Virê sita seba yew pele bêdestur bestere.",
        "right-autoconfirmed": "Perê ke nême kılit biyê, inan bıvurne",
        "right-bot": "Zey yew kardê otomotiki kar bıvin",
        "right-deletedhistory": "Qeydanê tarixanê esterıteyan de qayt ke, bê nuştey inan",
        "right-deletedtext": "Mabênê newede vurnayışanê esterıtiyan de qaytê nuştey esterıtey u vurnayışan ke",
        "right-browsearchive": "Pelanê esterıteyan bıgeyre",
-       "right-undelete": "Jû pela esterıtiye peyser bia",
+       "right-undelete": "Yew pela esterıtiye peyser biya",
        "right-suppressrevision": "İdarekeran ra miyanki, newede vurnayışan de qayt ke u newede vıraze",
        "right-viewsuppressed": "İdarekeran ra miyanki newede vurnayışan de qayt ke",
        "right-suppressionlog": "Rocekanê xasan bıvêne",
        "right-markbotedits": "Vurnayışanê peyd ameyan, vurnayışê boti deye nışan kerê",
        "right-noratelimit": "Sinoranê xızi (rate limit) ra tesir nêbi",
        "right-import": "Pelan wikiyanê binan ra bia",
-       "right-importupload": "Pelî dosya bar kerdişî ra import bike",
+       "right-importupload": "Barkerdışê yew dosya ra zerre ke",
        "right-patrol": "Vurnayîşanê karberê binî nîşan bike ke patrol biyê",
        "right-autopatrol": "Vurnayîşanê xo otomatik nîşan bike ke patrol biyê",
        "right-patrolmarks": "Vurnayîşanê peniyî nîşan patrol biyê bivîne",
        "action-upload": "ena dosya bar ke",
        "action-reupload": "dosyayê ke database de esto ser ey binuse",
        "action-reupload-shared": "dosyayê ki ho embarê medyayî de esto ser ay binusne",
-       "action-upload_by_url": "Ena dosya yew URL ra bar bike",
+       "action-upload_by_url": "na dosya yew URL ra bar ke",
        "action-writeapi": "ser nuşte API gure bike",
        "action-delete": "ena pele bestere",
        "action-deleterevision": "nê çımraviyarnayışi bestere",
        "filereuploadsummary": "Vurnayîşê dosyayî:",
        "filestatus": "Weziyetê heqa telifi:",
        "filesource": "Çıme:",
-       "ignorewarning": "Îkazi kebul meke u dosya reyna bar bike",
+       "ignorewarning": "İqazi qebul meke û dosya reyna bar ke",
        "ignorewarnings": "Îkazi kebul meke",
        "minlength1": "Nameyanê dosyayî de gani bî ezamî yew herf est biyê.",
        "illegalfilename": "\"$1\" no nameyê dosya de tayê karakteri nêşuxulyenî. newe ra tesel bıkerê",
        "filename-prefix-blacklist": " #<!-- leave this line exactly as it is --> <pre>\n# Syntax is as follows:\n#   * Everything from a \"#\" character to the end of the line is a comment\n#   * Every non-blank line is a prefix for typical file names assigned automatically by digital cameras\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # some mobile phones\nIMG # generic\nJD # Jenoptik\nMGP # Pentax\nPICT # misc.\n #</pre> <!-- leave this line exactly as it is -->",
        "upload-success-subj": "bar biyo",
        "upload-success-msg": "[$2] barkerdışê şıma qebul bı. Barkerdışê şımayo itado: [[:{{ns:file}}:$1]]",
-       "upload-failure-subj": "Problem bar bike",
+       "upload-failure-subj": "Problem bar ke",
        "upload-failure-msg": "[$1] delal: $2 ra barkerdıştê şıman ra jew xelat vıcyayo.",
        "upload-warning-subj": "İqazê barkerdışi",
        "upload-warning-msg": "Barkerdış dê [$2] de xırabey vıcyê. Xırabi timar kerdışi re  peyser şırê  [[Special:Upload/stash/$1|heruna barkerdışi]].",
        "sharedupload-desc-edit": "Na dosya $1 proceyan dê binandı ke şeno bıgurweyno.\nŞıma qayılê ke malumatê cı bıvurnê se şıre [pela da $2 ].",
        "sharedupload-desc-create": "Na dosya $1 proceyan dê binandı ke şeno bıgurweyno.\nŞıma qayılê ke malumatê cı bıvurnê se şıre [pela da $2 ].",
        "filepage-nofile": "Ena name de dosya çin o.",
-       "filepage-nofile-link": "Ena name de dosya çin o. Feqet ti eşkeno [$1 bar bike].",
+       "filepage-nofile-link": "Ebe nê name ra dosya çıniya, labelê tı şena [$1 ey kerê].",
        "uploadnewversion-linktext": "Versiyonê newiyerê ena dosya bar ke",
        "shared-repo-from": "$1 ra",
        "shared-repo": "yew embarê repositoryî",
        "delete-toobig": "no pel, pê $1 {{PLURAL:$1|tene vuriyayiş|tene vuriyayiş}}i wayirê yew tarixo kehen o.\nqey hewna nêşiyayişi wina pelani u {{SITENAME}}nêxerebnayişê keyepeli yew hed niyaya ro.",
        "delete-warning-toobig": "no pel wayirê tarixê vurnayiş ê derg o, $1 {{PLURAL:$1|revizyonê|revizyonê}} seri de.\nhewn a kerdışê ıney {{SITENAME}} şuxul bıne gırano;\nbı diqqet dewam kerê.",
        "rollback": "vurnayişan tepiya bıger",
-       "rollbacklink": "peyser bia",
+       "rollbacklink": "peyser biya",
        "rollbacklinkcount": "$1 {{PLURAL:$1|vurnayış|vurnayışi}} peyd gıroti",
        "rollbacklinkcount-morethan": "$1 {{PLURAL:$1|vurnayış|vuranyışi}} tewr peyd gırot",
        "rollbackfailed": "Peyserardış nêbi",
        "undeleterevision-missing": "revizyonê nemeqbul u vindbiyayeyi.\nRevizyoni ya hewn a biyê ya arşiw ra veciyayê ya zi cıresayişê şımayi şaş o.",
        "undelete-nodiff": "revizyonê verıni nidiya",
        "undeletebtn": "Timar bike",
-       "undeletelink": "bıvêne/peyser bia",
+       "undeletelink": "bıvêne/peyser biya",
        "undeleteviewlink": "bıvin",
        "undeleteinvert": "Weçinıtışi açarne",
        "undeletecomment": "Sebeb:",
        "movesubpagetext": "{{PLURAL:$1|pelê bınıni yê|pelê bınıni yê}} no $1 peli cer de yo.",
        "movenosubpage": "pelê bınıni yê no peli çino.",
        "movereason": "Sebeb:",
-       "revertmove": "peyser bia",
+       "revertmove": "peyser biya",
        "delete_and_move": "Bestere û bere",
        "delete_and_move_text": "==gani hewn a bıbıo/bıesteriyo==\n\n\" no [[:$1]]\" name de yew pel ca ra esto. şıma wazeni pê hewn a kerdışê ey peli vurnayişê nameyi bıkeri?",
        "delete_and_move_confirm": "Eya, na pele bestere",
        "import-noarticle": "Pel çino ke împort bike!",
        "import-nonewrevisions": "Qet versiyoni nêardi (nê pêro ya vera biyê ya zi qandê xeteyan ra nayinan sera xıl diyayo).",
        "xml-error-string": "$1 çizgi de $2 col $3 (bit $4): $5",
-       "import-upload": "Dosyayê XML bar bike",
+       "import-upload": "Dosyaya XML bar ke",
        "import-token-mismatch": "vindibiyayişê ma'lumatê hesabi. kerem kerê newe ra tesel/cereb bıkerê.",
        "import-invalid-interwiki": "Ena wiki ra azere kerdış nêbeno.",
        "import-error-edit": "Pela \" $1 \" qandê vurnayışi aya nêgêrêna çıkı cı rê icazet nêdeyayo.",
        "tooltip-watchlistedit-raw-submit": "Lista seyrkerdışi newe ke",
        "tooltip-recreate": "pel hewn a bışiyo zi tepiya biya",
        "tooltip-upload": "Sergen de bari be",
-       "tooltip-rollback": "\"Peyser bia\" be yew tık pela iştıraq(an)ê peyên|i(an) peyser ano.",
+       "tooltip-rollback": "\"Peyser biya\" be yew tık pela iştıraqanê peyênan peyser ano",
        "tooltip-undo": "\"Undo\" ena vurnayışê newi iptal kena u vurnayışê verni a kena.\nTı eşkeno yew sebeb bınus.",
        "tooltip-preferences-save": "Terciha qeyd ke",
        "tooltip-summary": "Yew xulasaya kilm binuse",
        "compare-title-not-exists": "Sernameyo ke şımayê vanê mewcud niyo.",
        "compare-revision-not-exists": "Revizyono ke şımaye vanê mewcud niyo.",
        "dberr-problems": "Mayê muxulêm! Ena sita dı newke xırabiya teknik esta.",
-       "dberr-again": "Yew di dekika vinder u hin bar bike.",
+       "dberr-again": "Dı-rê deqiqeyi vınde û heni bar ke.",
        "dberr-info": "(Erzmelumati ra xızmetkari nêreseno: $1)",
        "dberr-info-hidden": "(Ardendé erz malumatiya gredayışo nébeno)",
        "dberr-usegoogle": "Ti eşkeno hem zi ser Google de bigêre.",
index b115620..faf3220 100644 (file)
        "missingcommentheader": "'''Atensiòun:''' an n'é mìa stê precişê al mutîv/al tétol de sté mudéfica. S'es tōrna a clichêr insém a \"{{int:savearticle}}\" la mudéfica la gnirà salvêda sèinsa tétol.",
        "summary-preview": "Guêrda préma sûnt:",
        "subject-preview": "Guêrda préma argumèint/tétol:",
+       "previewerrortext": "A gh'é stê 'n erōr mèinter a s'é serchê ed guardêr al lavōr préma 'd salvêrel.",
        "blockedtitle": "Utèint bluchê",
        "blockedtext": " '''Al tō nòm utèint o indirés IP l'é stê bluchê.'''\n\nAl blôch l'é stê fât da $1. Al mutîv dal blôch l'é còst:  ''$2''.\n\n*Inési dal blôch: $8\n*Scadèinsa dal blôch: $6\n*Intervâl ed blôch: $7\n\nS' ét vō, l'é pusébil mètres in cuntât cun $1 o 'n êter [[{{MediaWiki:Grouppage-sysop}}|aministradōr]] per discóter dal blôch.\n\nGuêrda che la funsiòun 'Scrév a l'utèint' an n'é mìa in ôvra s' an n'é mìa stê registrtê un indirés ed pôsta eletrônica vâlid int al tō [[Special:Preferences| preferèinsi]] o se sté funsiòun l'é stêda bluchêda. L'indirés IP 'd adèsa l'é $3, al nóme ID dal blôch l'é #$5. T'é perghê ed precişêr tót j elemèint ed préma per ògni dmânda de spiegasiòun",
        "autoblockedtext": "Cl'indirés IP ché l'è stê bluchê in avtomâtich perché spartî cun 'n êter utèint, bluchê ânca ló da $1. Al mutîv dal blôch l'é còst:\n\n''$2''\n \n*Inési dal blôch: $8 \n*Scadèinsa dal blôch: $6 \n*Intervâl ed blôch: $7\n \nS' ét vō, l'é pusébil mètres in cuntât cun $1 o 'n êter [[{{MediaWiki:Grouppage-sysop}}|aministradōr]] per dmandêr spiegasiòun insém al blôch. Guêrda che la funsiòun 'Scrév a l'utèint' an n'é mìa in ôvra s' an n'é mìa stê registrtê un indirés ed pôsta eletrônica vâlid int al tō [[Special:Preferences| preferèinsi]] e, in tót al manēri, se int al tachêr al blôch, sté funsiòun l'é stêda bluchêda. L'indirés IP 'd adèsa l'é $3, al nóme ID dal blôch l'é #$5. T'é perghê ed precişêr tót j elemèint ed préma per ògni dmânda de spiegasiòun",
        "uploadscriptednamespace": "Cól file SVG ché al gh'à un namespace '$1' mìa permés.",
        "uploadinvalidxml": "Al côdis XML int al file al pōl mìa èser lavurê bèin.",
        "uploadvirus": "Cól fil ché al ghè un 'virus'! Particulêr: $1",
+       "uploadjava": "Cól file ché l'é un file ZIP che 'l gh'à dèinter un file .class Java. Carghêr i file Java an n'é mìa permés, perché pōlen schivşêr i lémit ed sicurèsa.",
+       "upload-source": "File 'd urégin",
+       "sourcefilename": "Nòm dal file 'd urégin:",
+       "sourceurl": "URL 'd urégin:",
+       "destfilename": "Nòm dal file in dó 'l gh'à d'andêr:",
+       "upload-maxfilesize": "Grandèsa mâsima dal file:$1",
+       "upload-description": "Spiegasiòun dal file",
+       "upload-options": "Siēlti per carghêr",
+       "watchthisupload": "Zûnta a i tgnu  'd ôc",
+       "filename-bad-prefix": "Al nòm dal file che s'é drē carghêr al cumîncia cun <strong>\"$1\"</strong>, ch'l'é un nòm genèrich cumpâgn a quî dê in avtomâtich dal mâchini fotogrâfichi digitêli. As prèiga ed sernîr un nòm pió precîş p'r al fîle.",
+       "upload-success-subj": "Carghê cun sucès",
+       "upload-success-msg": "La cârga da [$2] l'é andêda bèin. Al file a's pōl catêr ché: [[:{{ns:file}}:$1]]",
+       "upload-failure-subj": "A gh'é un problēma carghêr",
+       "upload-failure-msg": " A s'é verifiche un problēma cun la cârga da [$2]:\n\n\n$1",
+       "upload-warning-subj": "Avîş che s'é drē carghêr",
        "license": "Licèinsa:",
        "license-header": "Licèinsa",
        "nolicense": "Nisóna licèinsa sgnêda",
index f81567f..16a1e6a 100644 (file)
        "wrongpassword": "Incorrect password entered.\nPlease try again.",
        "wrongpasswordempty": "Password entered was blank.\nPlease try again.",
        "passwordtooshort": "Passwords must be at least {{PLURAL:$1|1 character|$1 characters}}.",
+       "passwordtoolong": "Passwords cannot be longer than {{PLURAL:$1|1 character|$1 characters}}.",
        "password-name-match": "Your password must be different from your username.",
        "password-login-forbidden": "The use of this username and password has been forbidden.",
        "mailmypassword": "Reset password",
        "notextmatches": "No page text matches",
        "prevn": "previous {{PLURAL:$1|$1}}",
        "nextn": "next {{PLURAL:$1|$1}}",
+       "prev-page": "previous page",
+       "next-page": "next page",
        "prevn-title": "Previous $1 {{PLURAL:$1|result|results}}",
        "nextn-title": "Next $1 {{PLURAL:$1|result|results}}",
        "shown-title": "Show $1 {{PLURAL:$1|result|results}} per page",
index 1ea4044..05b4c55 100644 (file)
        "wrongpassword": "La contraseña indicada es incorrecta.\nInténtalo de nuevo.",
        "wrongpasswordempty": "No has escrito una contraseña.\nInténtalo de nuevo.",
        "passwordtooshort": "Las contraseñas deben tener al menos {{PLURAL:$1|1 carácter|$1 caracteres}}.",
+       "passwordtoolong": "Las contraseñas no deben tener más de {{PLURAL:$1|1 carácter|$1 caracteres}}.",
        "password-name-match": "Tu contraseña debe ser diferente de tu nombre de usuario.",
        "password-login-forbidden": "El uso de este nombre de usuario y contraseña han sido prohibidos.",
        "mailmypassword": "Restablecer la contraseña",
index 245f512..1518721 100644 (file)
@@ -66,8 +66,8 @@
        "tog-minordefault": "همهٔ ویرایش‌ها به طور پیش‌فرض به عنوان «جزئی» علامت بخورد",
        "tog-previewontop": "پیش‌نمایش قبل از جعبهٔ ویرایش نمایش یابد",
        "tog-previewonfirst": "پیش‌نمایش هنگام اولین ویرایش نمایش یابد",
-       "tog-enotifwatchlistpages": "اگر صفحه یا پرونده‌ای از فهرست پی‌گیری‌هایم ویرایش شد به من نامه‌ای فرستاده شود",
-       "tog-enotifusertalkpages": "هنگامی که در صفحهٔ بحث کاربری‌ام تغییری صورت می‌گیرد به من نامه‌ای فرستاده شود",
+       "tog-enotifwatchlistpages": "اگر صفحه یا پرونده‌ای از فهرست پی‌گیری‌هایم ویرایش شد به من ایمیلی فرستاده شود",
+       "tog-enotifusertalkpages": "هنگامی که در صفحهٔ بحث کاربری‌ام تغییری صورت می‌گیرد به من ایمیلی فرستاده شود",
        "tog-enotifminoredits": "برای تغییرات جزئی در صفحه‌ها و پرونده‌ها هم به من ایمیل فرستاده شود",
        "tog-enotifrevealaddr": "آدرس ایمیل من را در ایمیل‌های اطلاع‌رسانی نمایش یابد",
        "tog-shownumberswatching": "شمار کاربران پی‌گیرندهٔ نمایش یابد",
index f795d70..c54008f 100644 (file)
        "wrongpassword": "Syöttämäsi salasana ei ole oikein. Ole hyvä ja yritä uudelleen.",
        "wrongpasswordempty": "Et voi antaa tyhjää salasanaa.",
        "passwordtooshort": "Salasanan täytyy olla vähintään {{PLURAL:$1|yhden merkin pituinen|$1 merkkiä pitkä}}.",
+       "passwordtoolong": "Salasanat saavat olla enintään $1 {{PLURAL:$1|merkin}} pituisia.",
        "password-name-match": "Salasanasi täytyy olla eri kuin käyttäjätunnuksesi.",
        "password-login-forbidden": "Tämän käyttäjänimen ja salasanan käyttö on estetty.",
        "mailmypassword": "Uudista salasana",
index 05786af..1e81ade 100644 (file)
        "readonly_lag": "La base de données a été automatiquement verrouillée pendant que les serveurs secondaires rattrapent leur retard sur le serveur principal.",
        "internalerror": "Erreur interne",
        "internalerror_info": "Erreur interne : $1",
-       "internalerror-fatal-exception": "Erreur fatale de type \"$1\"",
+       "internalerror-fatal-exception": "Erreur fatale de type « $1 »",
        "filecopyerror": "Impossible de copier le fichier « $1 » vers « $2 ».",
        "filerenameerror": "Impossible de renommer le fichier « $1 » en « $2 ».",
        "filedeleteerror": "Impossible de supprimer le fichier « $1 ».",
index 37c8b62..1c36479 100644 (file)
        "wrongpassword": "הסיסמה שהקלדתם שגויה.\nאנא נסו שוב.",
        "wrongpasswordempty": "הסיסמה שהקלדתם ריקה.\nאנא נסו שוב.",
        "passwordtooshort": "סיסמאות חייבות להיות באורך {{PLURAL:$1|תו אחד|$1 תווים}} לפחות.",
+       "passwordtoolong": "סיסמאות אינן יכולות להיות ארוכות {{PLURAL:$1|מתו אחד|מ־$1 תווים}}.",
        "password-name-match": "סיסמתך חייבת להיות שונה משם המשתמש שלך.",
        "password-login-forbidden": "השימוש בשם המשתמש והסיסמה האלה נאסר.",
        "mailmypassword": "איפוס סיסמה",
        "notextmatches": "אין דפים עם תוכן תואם",
        "prevn": "{{PLURAL:$1|הקודם|$1 הקודמים}}",
        "nextn": "{{PLURAL:$1|הבא|$1 הבאים}}",
+       "prev-page": "לעמוד הקודם",
+       "next-page": "לעמוד הבא",
        "prevn-title": "{{PLURAL:$1|התוצאה הקודמת|$1 התוצאות הקודמות}}",
        "nextn-title": "{{PLURAL:$1|התוצאה הבאה|$1 התוצאות הבאות}}",
        "shown-title": "הצגת {{PLURAL:$1|תוצאה אחת|$1 תוצאות}} בדף",
index a5b4aed..a5f5815 100644 (file)
@@ -59,7 +59,8 @@
                        "बिप्लब आनन्द",
                        "Phoenix303",
                        "Steinsplitter",
-                       "Macofe"
+                       "Macofe",
+                       "Ankita-ks"
                ]
        },
        "tog-underline": "कड़ियाँ अधोरेखन:",
        "wrongpassword": "आपने जो कूटशब्द लिखा है वह गलत है। कृपया पुनः प्रयास करें।",
        "wrongpasswordempty": "कूटशब्द खाली है।\nपुनः यत्न करें।",
        "passwordtooshort": "आपका कूटशब्द कम से कम {{PLURAL:$1|1 अक्षर|$1 अक्षरों}} का होना चाहिये।",
+       "passwordtoolong": "पासवर्ड {{PLURAL:$1|1 वर्ण|$1 वर्णों}} से ज़्यादा लम्बे नही हो सकते।",
        "password-name-match": "आपका कूटशब्द आपके सदस्यनाम से भिन्न होना चाहिए।",
        "password-login-forbidden": "इस सदस्यनाम और कूटशब्द का उपयोग वर्जित है।",
        "mailmypassword": "कूटशब्द पुनःस्थापित करें",
        "missingcommentheader": "'''अनुस्मारक:''' आपने इस टिप्पणी का कोई शीर्षक नहीं दिया है।\nअगर आप \"{{int:savearticle}}\" पर दोबारा क्लिक करते हैं तो आपके बदलाव बिना शीर्षक के संजोये जायेंगे।",
        "summary-preview": "सारांश की झलक:",
        "subject-preview": "विषय/शीर्षक की झलक:",
+       "previewerrortext": "अापके परिवर्तनों का पूर्वावलोकन करने का प्रयास करते समय एक त्रुटि हुई।",
        "blockedtitle": "सदस्य अवरुद्ध है",
        "blockedtext": "'''आपका सदस्यनाम अथवा आइ॰पी पता अवरोधित कर दिया गया हैं ।'''\n\nअवरोध $1 द्वारा किया गया था।\nअवरोध का कारण है ''$2''\n\n* अवरोध का आरंभ: $8\n* अवरोध की समाप्ति: $6\n* अवरोधित इकाई: $7\n\nइस अवरोध के बारे में चर्चा करने के लिए आप $1 या किसी अन्य [[{{MediaWiki:Grouppage-sysop}}|प्रबन्धक]] से संपर्क कर सकते हैं।\nअगर आपने [[Special:Preferences|अपनी वरीयताओं]] में वैध ई-मेल पता प्रविष्ट किया है तो ही आप 'इस प्रयोक्ता को ई-मेल भेजें' वाली सुविधा का इस्तेमाल कर सकते हैं और आपको इसका इस्तेमाल करने से नहीं रोका गया है।\nआपका मौजूदा आइ॰पी पता $3 है और अवरोध क्रमांक #$5 है।\nअपने किसी भी प्रश्न में कृपया यह सभी जानकारी भी शामिल करें।",
        "autoblockedtext": "एक और सदस्य आपके ही आइ॰पी का प्रयोग कर रहे थे और उन्हें $1 द्वारा अवरोधित कर दिया गया था। फलस्वरूप आपका आइ॰पी पता भी स्वचालित रूप से अवरोधित हो गया है।\nअवरोध करने का कारण है:\n\n:''$2''\n\n* अवरोध प्रारंभ: $8\n* अवरोध समाप्ति: $6\n* अवरोधित सदस्य: $7\n\nअवरोध की चर्चा करने के लिए आप $1 या किसी अन्य [[{{MediaWiki:Grouppage-sysop}}|प्रबंधक]] से संपर्क कर सकते हैं।\n\nकृपया ध्यान दें कि यदि आपक \"इस सदस्य को ई-मेल भेजें\" वाली सुविधा का प्रयोग करना चाहते हैं तो आपकी [[Special:Preferences|वरीयताओं]] में वैध ई-मेल पता होना चाहिए और इसका प्रयोग आपके लिए अवरोधित नहीं होना चाहिए।\n\nआपका मौजूदा आइ॰पी पता $3 है और अवरोध क्रमांक #$5 है।\nअपने किसी भी प्रश्न में कृपया यह सभी जानकारी भी शामिल करें।",
        "prefs-tokenwatchlist": "टोकन",
        "prefs-diffs": "अंतर",
        "prefs-help-prefershttps": "यह वरीयता आपके अगले लॉगिन पर प्रभावी होगी।",
+       "prefswarning-warning": "आपने अपनी वरीयताओं में एैसे परिवर्तन किए हैं जिन्हे अभी तक संचित नहीं किया गया है। अगर अाप \"$1\" पर बिना क्लिक किये इस पृष्ठ को छोड़ देते हैं तो अापकी वरीयताओं का अद्यतन नहीं किया जाएगा।",
        "prefs-tabs-navigation-hint": "सुझाव: आप टैब्स सूची में टैब्स के बीच आवागमन करने के लिए बाएँ और दाएँ तीर कुंजियों का उपयोग कर सकते हैं।",
        "email-address-validity-valid": "ई-मेल पता वैध प्रतीत होता है",
        "email-address-validity-invalid": "एक वैध ई-मेल पता प्रविष्ट करें",
        "unwatchedpages": "ध्यान न दिये हुए पृष्ठ",
        "listredirects": "पुनर्निर्देशनों की सूची",
        "listduplicatedfiles": "डुप्लिकेट के साथ फाइलों की सूची।",
+       "listduplicatedfiles-summary": "यह एैसे फ़ाइलों की सूची है जिनका नवीनतम संस्करण दूसरे फ़ाइलों के नवीनतम संस्करण की प्रतिलिपि हैं। सिर्फ़ स्थानीय फ़ाइलों को विचारा गया है।",
        "unusedtemplates": "अप्रयुक्त साँचे",
        "unusedtemplatestext": "इस पृष्ठ पर {{ns:template}} नामस्थान वाले वे सभी पृष्ठ इंगित है जो किसी अन्य पृष्ठ में शामिल नहीं हैं।\nइन्हें हटाने के पहले इन साँचों की और कड़ियाँ जाँच लें।",
        "unusedtemplateswlh": "अन्य कड़ियाँ",
        "wantedfiles": "वांछित फ़ाइलें",
        "wantedfiletext-cat": "निम्न फ़ाइलें प्रयुक्त हैं पर मौजूद नहीं हैं। बाहरी भंडारों की फ़ाइलें मौजूद होने के बावजूद सूची में हो सकती हैं। ऐसी कोई भी गलत प्रविष्टियाँ <del>काटी हुई</del> होंगी। साथ ही, जो पृष्ठ ऐसी फ़ाइलों का प्रयोग करते हैं जो मौजूद नहीं हैं, उनकी सूची [[:$1]] में है।",
        "wantedfiletext-nocat": "निम्न फ़ाइलें प्रयुक्त हैं पर मौजूद नहीं हैं। बाहरी भंडारों की फ़ाइलें मौजूद होने के बावजूद सूची में हो सकती हैं। ऐसी कोई भी गलत प्रविष्टियाँ <del>काटी हुई</del> होंगी।",
+       "wantedfiletext-nocat-noforeign": "निम्न फ़ाइलों को इस्तेमाल कर रहे हैं, लेकिन मौजूद नहीं है।",
        "wantedtemplates": "वांछित साँचे",
        "mostlinked": "सर्वाधिक से जुड़े हुए पृष्ठ",
        "mostlinkedcategories": "सर्वाधिक से जुड़ी हुई श्रेणियाँ",
        "listusers": "सदस्यसूची",
        "listusers-editsonly": "केवल संपादन कर चुके सदस्य दिखाएँ",
        "listusers-creationsort": "निर्माण तिथि के आधार पर क्रमांकन करें",
+       "listusers-desc": "अवरोही क्रम में क्रमबद्ध करें",
        "usereditcount": "$1 {{PLURAL:$1|सम्पादन}}",
        "usercreated": "$1 को $2 बजे बनाया गया, सदस्यनाम $3 है",
        "newpages": "नए पृष्ठ",
        "trackingcategories-name": "संदेश नाम",
        "trackingcategories-desc": "श्रेणी शामिल किए जाने के मानदंड",
        "trackingcategories-nodesc": "कोई वर्णन उपलब्ध नहीं।",
+       "trackingcategories-disabled": "श्रेणी अक्षम करी गयी है",
        "mailnologin": "पाने वाले का एड्रेस दिया नहीं",
        "mailnologintext": "अन्य सदस्यों को इ-मेल भेजने के लिये [[Special:UserLogin|लॉग इन]] करना आवश्यक है और आपकी [[Special:Preferences|वरीयताओं]] में वैध ई-मेल पता होना आवश्यक है।",
        "emailuser": "इस सदस्य को ई-मेल भेजें",
        "thumbnail_gd-library": "अवैध जीडी लाइब्रेरी जमाव: कार्यसमूह $1 मौजूद नहीं है",
        "thumbnail_image-missing": "लगता है संचिका नामौजूद है: $1",
        "import": "पृष्ठ इम्पोर्ट करें",
-       "importinterwiki": "à¤\9fà¥\8dरानà¥\8dसविà¤\95ि à¤\86यात",
+       "importinterwiki": "à¤\95िसà¥\80 à¤\94र à¤µà¤¿à¤\95ि à¤¸à¥\87 à¤\86यात à¤\95रà¥\87",
        "import-interwiki-text": "आयात करने के लिये एक विकि और एक पृष्ठ चुनें।\nअवतरण दिनांक और संपादक नाम ज्यों-के-त्यों रखे जाएँगे।\nअन्य विकि से सभी आयात [[Special:Log/import|आयात लॉग]] में डाली जाती हैं।",
        "import-interwiki-sourcewiki": "स्रोत विकि:",
        "import-interwiki-sourcepage": "स्रोत पृष्ठ:",
        "tags-create-no-name": "आपको एक चिप्पि का नाम निर्दिष्ट करना चाहिए।",
        "tags-delete-title": "चिप्पि हटायें",
        "tags-delete-reason": "कारण:",
+       "tags-activate-reason": "कारण:",
        "tags-activate-submit": "सक्रिय करें",
        "tags-deactivate-reason": "कारण:",
        "tags-deactivate-submit": "निष्क्रिय करें",
index 7a03979..1b1bd89 100644 (file)
        "disclaimers": "Jogi nyilatkozat",
        "disclaimerpage": "Project:Jogi nyilatkozat",
        "edithelp": "Szerkesztési segítség",
+       "helppage-top-gethelp": "Segítség",
        "mainpage": "Kezdőlap",
        "mainpage-description": "Kezdőlap",
        "policy-url": "Project:Irányelvek",
        "no-null-revision": "Nem sikerült új null-revíziót létrehozni a(z) „$1” lap számára.",
        "badtitle": "Hibás cím",
        "badtitletext": "A kért oldal címe érvénytelen, üres, vagy rosszul hivatkozott nyelvközi vagy wikiközi cím volt. Olyan karaktereket is tartalmazhatott, melyek címekben nem használhatók.",
-       "perfcached": "Az alábbi adatok gyorsítótárból (''cache''-ből) származnak, és ezért lehetséges, hogy nem a legfrissebb változatot mutatják. Legfeljebb {{PLURAL:$1|egy|$1 }} eredmény áll rendelkezésre a gyorsítótárban.",
+       "perfcached": "Az alábbi adatok gyorsítótárból (''cache''-ből) származnak, és ezért lehetséges, hogy nem a legfrissebb változatot mutatják. Legfeljebb $1 eredmény áll rendelkezésre a gyorsítótárban.",
        "perfcachedts": "Az alábbi adatok gyorsítótárból (''cache''-ből) származnak, legutóbbi frissítésük ideje $1. Legfeljebb {{PLURAL:$4|egy|$4}} eredmény áll rendelkezésre a gyorsítótárban.",
        "querypage-no-updates": "Az oldal frissítése jelenleg le van tiltva. Az itt szereplő adatok nem frissülnek azonnal.",
        "viewsource": "Lapforrás",
        "login-userblocked": "Ez a szerkesztő blokkolva van, a bejelentkezés nem engedélyezett.",
        "wrongpassword": "A megadott jelszó érvénytelen. Próbáld meg újra.",
        "wrongpasswordempty": "Nem adtál meg jelszót. Próbáld meg újra.",
-       "passwordtooshort": "A jelszónak legalább {{PLURAL:$1|egy|$1}} karakterből kell állnia.",
+       "passwordtooshort": "A jelszónak legalább $1 karakterből kell állnia.",
        "password-name-match": "A jelszavadnak különböznie kell a szerkesztőnevedtől.",
        "password-login-forbidden": "Ezen felhasználónév és jelszó használata tiltott.",
        "mailmypassword": "Jelszó alaphelyzetbe állítása",
        "withoutinterwiki-submit": "Megjelenítés",
        "fewestrevisions": "Legrövidebb laptörténetű lapok",
        "nbytes": "{{PLURAL:$1|egy|$1}} bájt",
-       "ncategories": "{{PLURAL:$1|egy|$1}} kategória",
+       "ncategories": "$1 kategória",
        "ninterwikis": "{{PLURAL:$1|egy|$1}} interwiki",
        "nlinks": "{{PLURAL:$1|egy|$1}} hivatkozás",
        "nmembers": "{{PLURAL:$1|egy|$1}} elem",
        "undeletepagetext": "Az alábbi {{PLURAL:$1|lapot törölték, de még helyreállítható|$1 lapot törölték, de még helyreállíthatók}} az archívumból.\nAz archívumot időről időre üríthetik!",
        "undelete-fieldset-title": "Változatok helyreállítása",
        "undeleteextrahelp": "A lap teljes helyreállításához ne jelölj be egy jelölőnégyzetet sem, csak kattints a '''''{{int:undeletebtn}}''''' gombra.\nA lap részleges helyreállításához jelöld be a kívánt változatok melletti jelölőnégyzeteket, és kattints a '''''{{int:undeletebtn}}''''' gombra.",
-       "undeleterevisions": "{{PLURAL:$1|egy|$1}} változat archiválva",
+       "undeleterevisions": "$1 változat archiválva",
        "undeletehistory": "Ha helyreállítasz egy lapot, azzal visszahozod laptörténet összes változatát.\nHa lap törlése óta azonos néven már létrehoztak egy újabb lapot, a helyreállított\nváltozatok a laptörténet végére kerülnek be, a jelenlegi lapváltozat módosítása nélkül.",
        "undeleterevdel": "A törlés visszavonása nem hajtható végre, ha a legfrissebb lapváltozat részleges törlését eredményezi.\nIlyen esetekben vissza kell vonnod a legújabb törölt változatok kijelölését vagy azok elrejtését.",
        "undeletehistorynoadmin": "Ezt a szócikket törölték. A törlés okát alább az összegzésben\nláthatod, az oldalt a törlés előtt szerkesztő felhasználók részleteivel együtt. Ezeknek\na törölt változatoknak a tényleges szövege csak az adminisztrátorok számára hozzáférhető.",
        "undeleteviewlink": "megtekintés",
        "undeleteinvert": "Kijelölés megfordítása",
        "undeletecomment": "Ok:",
-       "undeletedrevisions": "{{PLURAL:$1|egy|$1}} változat helyreállítva",
+       "undeletedrevisions": "$1 változat helyreállítva",
        "undeletedrevisions-files": "{{PLURAL:$1|egy|$1}} változat és {{PLURAL:$2|egy|$2}} fájl visszaállítva",
        "undeletedfiles": "{{PLURAL:$1|egy|$1}} fájl visszaállítva",
        "cannotundelete": "Lap visszaállítása sikertelen: $1",
        "thumbnail_gd-library": "A GD-könyvtár nincs megfelelően beállítva: a(z) $1 függvény hiányzik",
        "thumbnail_image-missing": "Úgy tűnik, hogy a fájl hiányzik: $1",
        "import": "Lapok importálása",
-       "importinterwiki": "Transwiki importálása",
-       "import-interwiki-text": "Válaszd ki az importálandó wikit és lapcímet.\nA változatok dátumai és a szerkesztők nevei megőrzésre kerülnek.\nValamennyi transwiki importálási művelet az [[Special:Log/import|importálási naplóban]] kerül naplózásra.",
+       "importinterwiki": "Importálás más wikiből",
+       "import-interwiki-text": "Válaszd ki az importálandó wikit és lapcímet.\nA változatok dátumai és a szerkesztők nevei megőrzésre kerülnek.\nValamennyi más wikiről való importálás az [[Special:Log/import|importálási naplóban]] kerül naplózásra.",
        "import-interwiki-sourcewiki": "Forráswiki:",
        "import-interwiki-sourcepage": "Forráslap:",
        "import-interwiki-history": "A lap összes előzményváltozatainak másolása",
        "importcantopen": "Nem nyitható meg az importfájl",
        "importbadinterwiki": "Rossz wikiközi hivatkozás",
        "importsuccess": "Az importálás befejeződött!",
-       "importnosources": "Nincsenek transzwikiimport-források definiálva, a közvetlen laptörténet-felküldés pedig nem megengedett.",
+       "importnosources": "Nincsenek források definiálva a wikiközi importáláshoz, a közvetlen laptörténet-felküldés pedig nem megengedett.",
        "importnofile": "Nem került importfájl feltöltésre.",
        "importuploaderrorsize": "Az importálandó fájl feltöltése nem sikerült, mert nagyobb, mint a megengedett feltöltési méret.",
        "importuploaderrorpartial": "Az importálandó fájl feltöltése nem sikerült. A fájl csak részben lett feltöltve.",
        "compare-revision-not-exists": "A megadott lapváltozat nem létezik.",
        "dberr-problems": "Sajnáljuk, de az oldallal technikai problémák vannak.",
        "dberr-again": "Várj néhány percet, majd frissítsd az oldalt.",
-       "dberr-info": "(Nem sikerült kapcsolatot létesíteni az adatbázisszerverrel: $1)",
-       "dberr-info-hidden": "(Nem sikerült kapcsolatot létesíteni az adatbázisszerverrel)",
+       "dberr-info": "(Nem sikerült kapcsolódni az adatbázishoz: $1)",
+       "dberr-info-hidden": "(Nem sikerült kapcsolódni az adatbázishoz)",
        "dberr-usegoogle": "A probléma elmúlásáig próbálhatsz keresni a Google-lel.",
        "dberr-outofdate": "Fontos tudnivaló, hogy az oldal tartalmáról készített indexeik elavultak lehetnek.",
        "dberr-cachederror": "Lenn a kért oldal gyorsítótárazott változata látható, és lehet, hogy nem teljesen friss.",
index 07677c5..67b4ca5 100644 (file)
        "wrongpassword": "La password inserita non è corretta. Riprovare.",
        "wrongpasswordempty": "Non è stata inserita alcuna password. Riprovare.",
        "passwordtooshort": "Le password devono contenere almeno {{PLURAL:$1|1 carattere|$1 caratteri}}.",
+       "passwordtoolong": "La password non può contenere più di {{PLURAL:$1|1 carattere|$1 caratteri}}.",
        "password-name-match": "La password deve essere diversa dal nome utente.",
        "password-login-forbidden": "L'uso di questo nome utente e password è stato proibito.",
        "mailmypassword": "Reimposta password",
index 60afffb..06e5863 100644 (file)
        "disclaimers": "პასუხისმგებლობის უარყოფა",
        "disclaimerpage": "Project:პასუხისმგებლობის უარყოფა",
        "edithelp": "დახმარება",
+       "helppage-top-gethelp": "დახმარება",
        "mainpage": "მთავარი გვერდი",
        "mainpage-description": "მთავარი გვერდი",
        "policy-url": "Project:პოლიტიკა",
index dd14b35..50f6572 100644 (file)
        "rev-deleted-unhide-diff": "Çımraviarnaisunê na ferqi ra  jü '''esteriyo'''.\nBeno ke [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log] de teferruat esto.\nSıma be idarekerênia ho ra şikinê hona [$1 nê ferqi bıvênê], eke wazenê dewam kerê.",
        "rev-delundel": "bıasne/wedare",
        "rev-showdeleted": "bıasne",
-       "revisiondelete": "Çımraviarnaisu bestere/peyser bia",
+       "revisiondelete": "Çımraviyarnayisu bestere/peyser biya",
        "revdelete-nooldid-title": "Çımraviarnaena waştiye nêvêrena",
        "revdelete-nooldid-text": "Sıma vırastena nê fonksiyoni rê ya jü çımraviarnaena waştiye diyar nêkerdo, çımraviarnaena diyarkerdiye çına, ya ki sıma wazenê ke çımraviarnaena nıkaêne bınımnê.",
        "revdelete-no-file": "Dosya diyarkerdiye çina.",
        "history-title": "Tarixê çımraviyarnayişê \"$1\"",
        "lineno": "Rêza $1i:",
        "compareselectedversions": "Varyantunê weçinıtun têver sane",
-       "editundo": "peyser bia",
+       "editundo": "peyser biya",
        "searchresults": "Neticê cıfeteliyaene",
        "searchresults-title": "\"$1\" rê neticê cıfeteliyaene",
        "notextmatches": "Qet zu pele de nêvêniya",
        "deletecomment": "Sebeb:",
        "deleteotherreason": "Sebebo bin/ilaweki:",
        "deletereasonotherlist": "Sebebo bin",
-       "rollbacklink": "peyser bia",
+       "rollbacklink": "peyser biya",
        "protectlogpage": "Qeydê seveknaene",
        "protectedarticle": "\"[[$1]]\" sevekna",
        "modifiedarticleprotection": "serba \"[[$1]]\" sewiya seveknaene vurriye",
        "undeletepagetitle": "'''Ni, [[:$1|$1]] be çımraviarnaunê pele ra yenê pêra'''.",
        "viewdeletedpage": "Pelunê esteriyau bıvine",
        "undelete-fieldset-title": "Çımraviarnau peyser biya",
-       "undeletebtn": "Peyser bia",
-       "undeletelink": "bıvêne/peyser bia",
+       "undeletebtn": "Peyser biya",
+       "undeletelink": "bıvêne/peyser biya",
        "undeleteviewlink": "bıvêne",
        "undeleteinvert": "Weçinıtey ters bıçarne",
        "undeletecomment": "Sebeb:",
        "block-log-flags-hiddenname": "namê karberi wedariyaeo",
        "range_block_disabled": "Qabılıyetê idarekeri be afernaena komuna têdine qapan bi.",
        "ipb_expiry_invalid": "Xêlê zeman nêvêreno.",
-       "movepagetext": "Ebe gurênaena formê cêrêni namê jü pele vurino, qeydê cıyê verêni pêro tede sonê be namê newey ser.\nNameo khan jü pela de cihetiê be namê newey cêna.\nTı şikina ita de cihetu otomatikman hetê namê oricinali ser rocane kerê.\nEke tı nêwazena otomatikman bıkerê, gunê [[Special:DoubleRedirects|cihetunê çıftu]] ya ki [[Special:BrokenRedirects|cihetunê nêvêrdeyu]] pêroine be ho duz kerê.\nHo vira meke ke be na vurnaiso ke tı kena, gurênaisê girêu be caunê rastu pêroine ra tı mesula.\n\nDiqet ke, namê newey de hora ke jü madde esto, vurnaisê namey '''nêbeno''', wa no ke thalo ya ki jü cihetiserberdiso u vurnaisê huyo verên çino. No yeno na mana ke tı şikina namê jü pele peyser bıcêrê, koti ra ke namê ae vuriyo, beno ke to ğelet kerd u zobina ki qarısê pela de bine nêbena.\n\n'''Teme!'''\nNo vurnais beno ke serba jü pela populere neticunê nêbiyau biaro meydan;\nkerem ke, verê vurnaişi neticunê biyau bia be çımu ver.",
+       "movepagetext": "Ebe gurênayena formê cêrêni namê jü pele vurino, qeydê cıyê verêni pêro tede sonê be namê newey ser.\nNamewo khan jü pela de cihetiyê be namê neweyi cêna.\nTı şikina ita de cihetu otomatikman hetê namê oricinali ser rocane kerê.\nEke tı nêwazena otomatikman bıkerê, gunê [[Special:DoubleRedirects|cihetunê çıftu]] ya ki [[Special:BrokenRedirects|cihetunê nêvêrdeyu]] pêroyine be ho duz kerê.\nHo vira meke ke be na vurnaiso ke tı kena, gurênayisê girêwu be cawunê rastu pêroyine ra tı mesula.\n\nDiqet ke, namê neweyi de hora ke jü made esto, vurnayisê nameyi <strong>nêbeno</strong>, wa no ke thalo ya ki jü cihetiserberdiso u vurnayisê huyo verên çino. No yeno na mana ke tı şikina namê jü pele peyser bıcêrê, koti ra ke namê aye vuriyo, beno ke to ğelet kerd û zobina ki qarısê pela de bine nêbena.\n\n<strong>Teme!</strong>\nNo vurnayis beno ke serba jü pela populere neticunê nêbiyawu biyaro meydan;\nkerem ke, verê vurnayişi neticunê biyawu biya be çımu ver.",
        "movepagetalktext": "Na pela hurênaişia ke tedera otomatikmen kırışina be namê newey, hama nê halu ra '''qêri''':\n*Jü pela hurênaişia pırre bınê namê newey de hora esta, ya ki\n*Qutiya bınêne to nêçinıte we.\n\nNê halu de, tı gunê pele ebe dest berê ya ki ser kerê eke wajiye.",
        "movearticle": "Pele bere:",
        "newtitle": "Ebe nameo newe:",
        "movetalk": "Pela hurênaişiê alaqedare bere",
        "movelogpage": "Qeydê berdene",
        "movereason": "Sebeb:",
-       "revertmove": "raçarnaene",
+       "revertmove": "raçarne",
        "export": "Pelu qeyd ke",
        "allmessages": "Mesacê sistemi",
        "allmessagesname": "Name",
        "tooltip-watch": "Na pele lista huya şêrkerdişi ser ke",
        "tooltip-recreate": "Na pele esterıte bo ki, nae oncia bıaferne",
        "tooltip-upload": "Dest be bar-kerdene ke",
-       "tooltip-rollback": "\"Peyser bia\" ebe jü tık pela iştırak(un)ê peyên|i(u) peyser ano.",
+       "tooltip-rollback": "\"Peyser biya\" ebe jü tık pela iştırakunê peyênu peyser ano.",
        "tooltip-undo": "\"Peyser\" ni vurnaişi peyser ano u modusê verqayt de vurnaisê formi keno ra.\nTêser-kerdena jü sebebi rê xulasa de imkan dano cı.",
        "tooltip-summary": "Xulasê da kılme cı kuye",
        "common.css": "/* CSSo ke itaro, serba çermu pêroine gurenino */",
index 97a9c8d..a1af0f4 100644 (file)
        "underline-never": "Qet",
        "underline-default": "Tercîhên lêgerokê",
        "editfont-default": "Tercîhên lêgerokê",
-       "sunday": "yekşem",
-       "monday": "duşem",
+       "sunday": "Yekşem",
+       "monday": "Duşem",
        "tuesday": "Sêşem",
        "wednesday": "Çarşem",
        "thursday": "Pêncşem",
        "friday": "În",
-       "saturday": "Å\9femî",
+       "saturday": "Å\9eemî",
        "sun": "Ykş",
        "mon": "Duş",
        "tue": "Sêş",
        "thu": "Pşm",
        "fri": "În",
        "sat": "Şem",
-       "january": "rêbendan",
-       "february": "reşemî",
-       "march": "adar",
-       "april": "avrêl",
-       "may_long": "gulan",
-       "june": "pûşper",
-       "july": "tîrmeh",
-       "august": "gelawêj",
-       "september": "rezber",
-       "october": "kewçêr",
-       "november": "sermawez",
-       "december": "berfanbar",
+       "january": "Rêbendan",
+       "february": "Reşemî",
+       "march": "Adar",
+       "april": "Avrêl",
+       "may_long": "Gulan",
+       "june": "Pûşper",
+       "july": "Tîrmeh",
+       "august": "Gelawêj",
+       "september": "Rezber",
+       "october": "Kewçêr",
+       "november": "Sermawez",
+       "december": "Berfanbar",
        "january-gen": "Rêbendan",
        "february-gen": "Reşemî",
        "march-gen": "Adar",
        "april-gen": "Avrêl",
-       "may-gen": "gulan",
-       "june-gen": "pûşper",
+       "may-gen": "Gulan",
+       "june-gen": "Pûşper",
        "july-gen": "Tîrmeh",
        "august-gen": "Gelawêj",
-       "september-gen": "rezber",
+       "september-gen": "Rezber",
        "october-gen": "Kewçêr",
        "november-gen": "Sermawez",
-       "december-gen": "berfanbar",
+       "december-gen": "Berfanbar",
        "jan": "rêb",
        "feb": "reş",
        "mar": "adr",
        "oct": "kew",
        "nov": "ser",
        "dec": "ber",
+       "january-date": "Rêbendan $1",
+       "february-date": "Reşemî $1",
+       "march-date": "Adar $1",
+       "april-date": "Avrêl $1",
+       "may-date": "Gulan $1",
+       "june-date": "Pûşper $1",
+       "july-date": "Tîrmeh $1",
+       "august-date": "Gelawêj $1",
+       "september-date": "Rezber $1",
+       "october-date": "Kewçêr $1",
+       "november-date": "Sermawez $1",
+       "december-date": "Berfanbar $1",
        "pagecategories": "{{PLURAL:$1|Kategorî|Kategorî}}",
        "category_header": "Gotarên di kategoriya \"$1\" de",
        "subcategories": "Binkategorî",
        "disclaimers": "Ferexetname",
        "disclaimerpage": "Project:Ferexetname",
        "edithelp": "Alîkariya guherandinê",
+       "helppage-top-gethelp": "Alîkarî",
        "mainpage": "Destpêk",
        "mainpage-description": "Destpêk",
        "policy-url": "Project:Rêgez",
        "nospecialpagetext": "<strong>Rûpela taybet a te xwestî tune ye.</strong>\n\nHemû rûpelên taybet dikarin di [[Special:SpecialPages|lîsteya rûpelên taybet]] de werin dîtin.",
        "error": "Çewtî",
        "databaseerror": "Çewtiya bingeha daneyan",
+       "databaseerror-error": "Çewtî:$1",
        "laggedslavemode": "'''Zanibe:''' Dibe ku di vê rûpelê de rojanekirinên dawî nîn bin.",
        "readonly": "Bingeha daneyan hatiye girtin",
        "enterlockreason": "Sedemeke bestinê binivîse, herwiha demeke texmînkirî ji bo vebûna bestinê binivîse!",
        "yourpassword": "Şîfre:",
        "userlogin-yourpassword": "Şîfre",
        "userlogin-yourpassword-ph": "Şîfreya xwe binivîse",
+       "createacct-yourpassword-ph": "Şîfreya xwe binivîse",
        "yourpasswordagain": "Şîfreyê dîsa binivîse:",
        "createacct-yourpasswordagain-ph": "Şîfreyê ji nû ve têkeve",
        "remembermypassword": "Şifreya min di her têketina min de bîne bîra xwe (herî zêde $1 {{PLURAL:$1|rojekê|rojan}})",
        "externaldberror": "Çewtiyeke bingeha daneyan heye, an jî destûra te ya rojanekirina hesabê xweyê navxweyî nîne.",
        "login": "Têkeve",
        "nav-login-createaccount": "Têkeve / hesabekî nû çêke",
-       "userlogin": "Têkeve an hesabekî nû çêke",
+       "userlogin": "Têkeve / hesabekî nû çêke",
        "userloginnocreate": "Têkeve",
        "logout": "Derkeve",
        "userlogout": "Derkeve",
index 3701e87..c7329a0 100644 (file)
@@ -93,7 +93,7 @@
        "november-gen": "نوامر",
        "december-gen": "دسامر",
        "jan": "جانویه",
-       "feb": "فبريه",
+       "feb": "فوریه",
        "mar": "مارش",
        "apr": "آبريل",
        "may": "ما",
        "copyrightpage": "{{ان اس:پروجه}}:کپی رایت",
        "currentevents": "پيشومدل تازه باو",
        "currentevents-url": "پروجه:پيشومدل تازه باو",
-       "disclaimers": "کذو کننه یا",
+       "disclaimers": "تیه پوشکاریا",
        "disclaimerpage": "پروجه:منكر بيئن کلی",
        "edithelp": "هومياری سی ويرايشت",
        "helppage-top-gethelp": "هومياری",
        "wrongpassword": "رازینه گواردن غلط وارد بیه.\nهنی تلاش بکید",
        "wrongpasswordempty": "رازینه گواردنی که دئیت حالیه.د نؤ تلاش بکیت",
        "passwordtooshort": "رازینه گواردن با حداقل  {{PLURAL:$1|1 character|$1 characters}}          با",
+       "passwordtoolong": "رازینه گواردن نواس بیشتر د {{PLURAL:$1|1 character|$1 characters}} با.",
        "password-name-match": "رازینه گواردنتو با د نوم کاریاری فرخ داشتوه",
        "password-login-forbidden": "وه کار گرتن ای پاسوردو نوم کاریاری قدقن بیه.",
        "mailmypassword": "د نۈ وارد كردن رازینه گواردن",
        "notextmatches": "نیسسه بلگه هومسازی ناره",
        "prevn": "وادما {{PLURAL:$1|$1}}",
        "nextn": "نيايی {{PLURAL:$1|$1}}",
+       "prev-page": "بلگه دمايی",
+       "next-page": "بلگه نهایی",
        "prevn-title": "پيشتر $1 {{PLURAL:$1|نتيجه|نتيجيا}}",
        "nextn-title": "نيايی $1 {{PLURAL:$1|نتيجه|نتيجيا}}",
        "shown-title": "نشون دئن $1 {{جمی:$1|نتيجه|نتيجه}} سی هر بلگه",
        "blocklink": "نهاگری بوئه",
        "unblocklink": "بی قطی",
        "change-blocklink": "اجازه نديئن سی  آلشت",
-       "contribslink": "هومیاری",
+       "contribslink": "هومیاریا",
        "emaillink": "انجومانامه نه کل کو",
        "blocklogpage": "قلف",
        "blocklogentry": " [[$1]] وا یه گل وخت تموم بیئن $2 و $3  قلف بیه",
        "default-skin-not-found-row-disabled": "* <رازینه>$1</رازینه> / $2 ('''ناکنشتگر بیه''')",
        "mediastatistics": "آماریا وارسگر",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 بایت|$1 بایتیا}} ($2; $3%)",
+       "mediastatistics-table-mimetype": "جورMIME:",
        "mediastatistics-table-extensions": "دمادیسیا ممکن",
        "mediastatistics-table-count": "شماره جانیایا",
        "mediastatistics-table-totalbytes": "انازه وه یک شیوسه",
        "mediastatistics-header-executable": "اجرا کردنیا",
        "mediastatistics-header-archive": "قالویا جم بیه",
        "json-error-syntax": "خطا دستوری",
+       "json-error-inf-or-nan": "ارزایشتیا INF یا NAN یه گل یا بیشتر د وه د انازه یی که رازینه کاری بیه",
+       "json-error-unsupported-type": "یه گل ارزایشت د جوری که نبوئه رازینه کاری با وتو دئه بیه",
        "headline-anchor-title": "هوم پیوند کردن د ای بهرجا",
        "special-characters-group-latin": "لاتين",
        "special-characters-group-latinextended": "لاتین گپ کلون کاری بیه",
        "special-characters-group-thai": "تايی",
        "special-characters-group-lao": "لائو",
        "special-characters-group-khmer": "خمر",
+       "special-characters-title-endash": "خط فاصله",
+       "special-characters-title-emdash": "خط فاصله",
        "special-characters-title-minus": "نشون کم کردن"
 }
index 74a6723..157da4b 100644 (file)
        "wrongpassword": "Внесовте погрешна лозинка. Обидете се повторно.",
        "wrongpasswordempty": "Внесената лозинка е празна. Обидете се повторно.",
        "passwordtooshort": "Лозинката мора да има најмалку {{PLURAL:$1|1 знак|$1 знаци}}.",
+       "passwordtoolong": "Лозинката не треба да има повеќе од {{PLURAL:$1|1 знак|$1 знаци}}.",
        "password-name-match": "Лозинката мора да се разликува од корисничкото име.",
        "password-login-forbidden": "Употребата на ова корисничко име и лозинка е забранета.",
        "mailmypassword": "Нова лозинка",
index 6fd83a5..e7922b4 100644 (file)
        "wrongpassword": "'A password nzertàta nun è bbona.\nPe' piacere pruvate n'ata vota.",
        "wrongpasswordempty": "'A password nzertàta è abbacante.\nPe' piacere pruvate n'ata vota.",
        "passwordtooshort": "'E password hann'avé minimo {{PLURAL:$1|nu carattere|$1 carattere}}.",
+       "passwordtoolong": "'E password nun ponno essere cchiù luonghe 'e {{PLURAL:$1|nu carattere|$1 carattere}}.",
        "password-name-match": "'A password adda essere diverza 'a 'o nomme utente.",
        "password-login-forbidden": "L'uso 'e stu nomme utente e password è stato proibito.",
        "mailmypassword": "Riabbìa 'a password",
        "notextmatches": "Voce addemannata nun truvata dint' 'e teste 'e articulo",
        "prevn": "{{PLURAL:$1|precedente|precedente $1}}",
        "nextn": "{{PLURAL:$1|successivo|successive $1}}",
+       "prev-page": "paggena 'e primma",
+       "next-page": "paggena aroppo",
        "prevn-title": "{{PLURAL:$1|Risultato precediente|$1 risultate precedenti}}",
        "nextn-title": "{{PLURAL:$1|Risultato successivo|$1 risultate successive}}",
        "shown-title": "Fa vere {{PLURAL:$1|'nu risultato|$1 risultate}} ppe paggena",
index 0ad7c89..9d2d63f 100644 (file)
        "missingcommentheader": "'''Påminnelse:''' Du har ikke angitt et emne/overskrift for denne kommentaren.\nOm du trykker «{{int:savearticle}}» igjen vil redigeringen din bli lagret uten forklaring.",
        "summary-preview": "Forhåndsvisning av redigeringsforklaring:",
        "subject-preview": "Forhåndsvisning av emne/overskrift:",
+       "previewerrortext": "En feil oppsto mens dine endringer skulle forhåndsvises.",
        "blockedtitle": "Brukeren er blokkert",
        "blockedtext": "'''Ditt brukernavn eller din IP-adresse har blitt blokkert.'''\n\nBlokkeringen ble utført av $1. Grunnen som ble oppgitt var ''$2''.\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkering ment på: $7\n\nDu kan kontakte $1 eller en annen [[{{MediaWiki:Grouppage-sysop}}|administrator]] for å diskutere blokkeringen.\nDu kan ikke bruke «E-post til denne brukeren»-funksjonen med mindre du har oppgitt en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]] og du ikke er blokkert fra å sende e-post.\nDin nåværende IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta all denne informasjonen ved henvendelser.",
        "autoblockedtext": "Din IP-adresse har blitt automatisk blokkert fordi den ble brukt av en annen bruker som ble blokkert av $1.\nDen oppgitte grunnen var:\n\n:'''$2'''\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkeringen er ment for: $7\n\nDu kan kontakte $1 eller en av de andre [[{{MediaWiki:Grouppage-sysop}}|administratorene]] for å diskutere blokkeringen.\n\nMerk at du ikke kan bruke «E-post til denne brukeren»-funksjonen med mindre du har registrert en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]].\n\nDin IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta med all denne informasjonen ved henvendelser.",
        "logentry-block-reblock": "$1 {{GENDER:$2|endret}} blokkeringsinnstillingen av {{GENDER:$4|$3}} med en utløpstid på $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|blokkerte}} {{GENDER:$4|$3}} med en utløpstid på $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|endret}} blokkeringsinnstillingen for {{GENDER:$4|$3}} med en utløpstid på $5 $6",
+       "logentry-import-upload": "$1 {{GENDER:$2|importert}} $3 gjennom filopplastning",
        "logentry-merge-merge": "$1 {{GENDER:$2|slo sammen}} $3 i $4 (versjonene t.o.m. $5)",
        "logentry-move-move": "$1 {{GENDER:$2|flyttet}} siden $3 til $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|flyttet}} siden $3 til $4 uten å etterlate en omdirigering",
        "feedback-submit": "Send",
        "feedback-thanks": "Din tilbakemelding til siden \"[ $2  $1 ]\" er sendt. Takk skal du ha!",
        "feedback-thanks-title": "Takk!",
+       "feedback-useragent": "Brukeragent",
        "searchsuggest-search": "Søk",
        "searchsuggest-containing": "inneholder …",
        "api-error-badaccess-groups": "Du har ikke tillatelse til å laste opp filer til denne wikien.",
        "json-error-recursion": "En eller flere rekursive referanser i verdien som skal kodes",
        "json-error-inf-or-nan": "En eller flere NAN- eller INF-verdier i verdien som skal kodes",
        "json-error-unsupported-type": "En verdi av en type som ikke kan kodes ble angitt",
-       "headline-anchor-title": "Lenke til denne seksjonen"
+       "headline-anchor-title": "Lenke til denne seksjonen",
+       "special-characters-group-latin": "Latin",
+       "special-characters-group-latinextended": "Utvidet Latin",
+       "special-characters-group-ipa": "IPA",
+       "special-characters-group-symbols": "Symboler",
+       "special-characters-group-greek": "Gresk",
+       "special-characters-group-cyrillic": "Kyrillisk",
+       "special-characters-group-arabic": "Arabisk",
+       "special-characters-group-arabicextended": "Utvidet arabisk",
+       "special-characters-group-persian": "Persisk",
+       "special-characters-group-hebrew": "Hebraisk",
+       "special-characters-group-bangla": "Bangla",
+       "special-characters-group-tamil": "Tamilsk",
+       "special-characters-group-telugu": "Telugu",
+       "special-characters-group-sinhala": "Singalesisk",
+       "special-characters-group-gujarati": "Gujarati",
+       "special-characters-group-devanagari": "Devanagari",
+       "special-characters-group-thai": "Thai",
+       "special-characters-group-lao": "Laotisk",
+       "special-characters-group-khmer": "Khmer",
+       "special-characters-title-endash": "tankestrek",
+       "special-characters-title-emdash": "lang tankestrek",
+       "special-characters-title-minus": "minustegn"
 }
index 319661d..b80a22e 100644 (file)
        "prefs-personal": "Gebrukersgegevens",
        "prefs-rc": "Leste wiezigingen",
        "prefs-watchlist": "Volglieste",
+       "prefs-editwatchlist-label": "Onderwarpen op joew volglieste bewarken:",
+       "prefs-editwatchlist-edit": "Onderwarpen op mien volgliesten bekieken en vortdoon",
        "prefs-watchlist-days": "Antal dagen in de volglieste bekieken:",
        "prefs-watchlist-days-max": "Hooguut $1 {{PLURAL:$1|dag|dagen}}",
        "prefs-watchlist-edits": "Antal wiezigingen in de uutebreiden volglieste:",
        "sp-contributions-search": "Zeuken naor biedragen",
        "sp-contributions-username": "IP-adres of gebrukersnaam:",
        "sp-contributions-toponly": "Allinnig de niejste versie laoten zien",
+       "sp-contributions-newonly": "Allinnig nieje ziejen laoten zien",
        "sp-contributions-submit": "Zeuk",
        "whatlinkshere": "Verwiezingen naor disse zied",
        "whatlinkshere-title": "Ziejen die verwiezen naor \"$1\"",
        "watchlistedit-raw-done": "Joew volglieste is bie-ewörken.",
        "watchlistedit-raw-added": "Der {{PLURAL:$1|is 1 zied|bin $1 ziejen}} bie edaon:",
        "watchlistedit-raw-removed": "Der {{PLURAL:$1|is 1 zied|bin $1 ziejen}} vortedaon:",
+       "watchlisttools-clear": "Volglieste leegmaken",
        "watchlisttools-view": "Wiezigingen bekieken",
        "watchlisttools-edit": "Volglieste bekieken en bewarken",
-       "watchlisttools-raw": "Roewe volglieste bewarken",
+       "watchlisttools-raw": "Volglieste as tekstlieste bewarken",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|overleg]])",
        "duplicate-defaultsort": "Waorschuwing: de standardsortering \"$2\" krig veurrang veur de sortering \"$1\".",
        "version": "Versie",
index 59dfde5..1ef0cc5 100644 (file)
        "previousrevision": "← पुरानो संशोधन",
        "nextrevision": "नयाँ संशोधन →",
        "currentrevisionlink": "हालको पुनरावलोकन",
-       "cur": "cur पृष्ठको लिङ्क इतिहास",
+       "cur": "वर्तमान पृष्ठको लिङ्क इतिहास",
        "next": "अर्को",
        "last": "अघिल्लो",
        "page_first": "पहिलो",
index dd5f224..f5ce300 100644 (file)
        "wrongpassword": "La ciav batùa a l'é pa giusta.\nChe a preuva torna, për piasì.",
        "wrongpasswordempty": "A l'ha butà na ciav veujda. Për piasì, che a preuva torna.",
        "passwordtooshort": "Le ciav a devo avèj almanch {{PLURAL:$1|1 caràter|$1 caràter}}.",
+       "passwordtoolong": "Le ciav a peulo nen esse pi longhe che {{PLURAL:$1|1 caràter|$1 caràter}}.",
        "password-name-match": "Soa ciav a dev esse diferenta da sò stranòm.",
        "password-login-forbidden": "L'usagi ëd së stranòm d'utent e ëd sa ciav a son ëstàit proibì.",
        "mailmypassword": "Riamposté la ciav",
index fef9ac8..8d86ce6 100644 (file)
        "thu": "Abbreviation for Thursday, a day of the week.",
        "fri": "Abbreviation for Friday, a day of the week.",
        "sat": "Abbreviation for Saturday, a day of the week.",
-       "january": "The first month of the Gregorian calendar\n{{Identical|January}}",
-       "february": "The second month of the Gregorian calendar\n{{Identical|February}}",
-       "march": "The third month of the Gregorian calendar\n{{Identical|March}}",
-       "april": "The fourth month of the Gregorian calendar\n{{Identical|April}}",
-       "may_long": "The fifth month of the Gregorian calendar\n{{Identical|May}}",
-       "june": "The sixth month of the Gregorian calendar\n{{Identical|June}}",
-       "july": "The seventh month of the Gregorian calendar\n{{Identical|July}}",
-       "august": "The eighth month of the Gregorian calendar\n{{Identical|August}}",
-       "september": "The ninth month of the Gregorian calendar\n{{Identical|September}}",
-       "october": "The tenth month of the Gregorian calendar\n{{Identical|October}}",
-       "november": "The eleventh month of the Gregorian calendar\n{{Identical|November}}",
-       "december": "The twelfth month of the Gregorian calendar\n{{Identical|December}}",
-       "january-gen": "The first month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|January}}",
-       "february-gen": "The second month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|February}}",
-       "march-gen": "The third month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|March}}",
-       "april-gen": "The fourth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|April}}",
-       "may-gen": "The fifth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|May}}",
-       "june-gen": "The sixth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|June}}",
-       "july-gen": "The seventh month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|July}}",
-       "august-gen": "The eighth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|August}}",
-       "september-gen": "The nineth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|September}}",
-       "october-gen": "The tenth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|October}}",
-       "november-gen": "The eleventh month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|November}}",
-       "december-gen": "The twelfth month of the Gregorian calendar. Must be in genitive, if the language has a genitive case.\n{{Identical|December}}",
-       "jan": "Abbreviation of January, the first month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "feb": "Abbreviation of February, the second month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "mar": "Abbreviation of March, the third month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "apr": "Abbreviation of April, the fourth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "may": "''Abbreviation'' of May, the fifth month of the Gregorian calendar.\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.\n\n{{doc-important|This is not the full name of May, which resides at {{msg-mw|May long}}}}\n\n{{Identical|May}}",
-       "jun": "Abbreviation of June, the sixth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "jul": "Abbreviation of July, the seventh month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "aug": "Abbreviation of August, the eighth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "sep": "Abbreviation of September, the ninth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "oct": "Abbreviation of October, the tenth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "nov": "Abbreviation of November, the eleventh month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
-       "dec": "Abbreviation of December, the twelfth month of the Gregorian calendar\n\nOne of the set: {{msg-mw|Jan}}, {{msg-mw|Feb}}, {{msg-mw|Mar}}, {{msg-mw|Apr}}, {{msg-mw|May}}, {{msg-mw|Jun}}, {{msg-mw|Jul}}, {{msg-mw|Aug}}, {{msg-mw|Sep}}, {{msg-mw|Oct}}, {{msg-mw|Nov}}, {{msg-mw|Dec}}.",
+       "january": "{{doc-months|1}}\n{{Identical|January}}",
+       "february": "{{doc-months|2}}\n{{Identical|February}}",
+       "march": "{{doc-months|3}}\n{{Identical|March}}",
+       "april": "{{doc-months|4}}\n{{Identical|April}}",
+       "may_long": "{{doc-months|5}}\n{{Identical|May}}",
+       "june": "{{doc-months|6}}\n{{Identical|June}}",
+       "july": "{{doc-months|7}}\n{{Identical|July}}",
+       "august": "{{doc-months|8}}\n{{Identical|August}}",
+       "september": "{{doc-months|9}}\n{{Identical|September}}",
+       "october": "{{doc-months|10}}\n{{Identical|October}}",
+       "november": "{{doc-months|11}}\n{{Identical|November}}",
+       "december": "{{doc-months|12}}\n{{Identical|December}}",
+       "january-gen": "{{doc-months|1|genitive}}\n{{Identical|January}}",
+       "february-gen": "{{doc-months|2|genitive}}\n{{Identical|February}}",
+       "march-gen": "{{doc-months|3|genitive}}\n{{Identical|March}}",
+       "april-gen": "{{doc-months|4|genitive}}\n{{Identical|April}}",
+       "may-gen": "{{doc-months|5|genitive}}\n{{Identical|May}}",
+       "june-gen": "{{doc-months|6|genitive}}\n{{Identical|June}}",
+       "july-gen": "{{doc-months|7|genitive}}\n{{Identical|July}}",
+       "august-gen": "{{doc-months|8|genitive}}\n{{Identical|August}}",
+       "september-gen": "{{doc-months|9|genitive}}\n{{Identical|September}}",
+       "october-gen": "{{doc-months|10|genitive}}\n{{Identical|October}}",
+       "november-gen": "{{doc-months|11|genitive}}\n{{Identical|November}}",
+       "december-gen": "{{doc-months|12|genitive}}\n{{Identical|December}}",
+       "jan": "{{doc-months|1|short}}",
+       "feb": "{{doc-months|2|short}}",
+       "mar": "{{doc-months|3|short}}",
+       "apr": "{{doc-months|4|short}}",
+       "may": "{{doc-months|5|short}}",
+       "jun": "{{doc-months|6|short}}",
+       "jul": "{{doc-months|7|short}}",
+       "aug": "{{doc-months|8|short}}",
+       "sep": "{{doc-months|9|short}}",
+       "oct": "{{doc-months|10|short}}",
+       "nov": "{{doc-months|11|short}}",
+       "dec": "{{doc-months|12|short}}",
        "january-date": "A date in the Gregorian month of January. $1 is the numerical date, for example \"23\".\n{{Identical|January}}",
        "february-date": "A date in the Gregorian month of February. $1 is the numerical date, for example \"23\".\n{{Identical|February}}",
        "march-date": "A date in the Gregorian month of March. $1 is the numerical date, for example \"23\".\n{{Identical|March}}",
        "wrongpassword": "Used as error message when the provided password is wrong.\nThis message is used in html.\n{{Identical|Please try again}}",
        "wrongpasswordempty": "Error message displayed when entering a blank password.\n{{Identical|Please try again}}",
        "passwordtooshort": "This message is shown in [[Special:Preferences]] and [[Special:CreateAccount]].\n\nParameters:\n* $1 - the minimum number of characters in the password",
+       "passwordtoolong": "This message is shown in [[Special:Preferences]], [[Special:CreateAccount]], and [[Special:Userlogin]].\n\nParameters:\n* $1 - the maximum number of characters in the password",
        "password-name-match": "Used as error message when password validity check failed.",
        "password-login-forbidden": "Error message shown when the user has tried to log in using one of the special username/password combinations used for MediaWiki testing. (See [[mwr:75589]], [[mwr:75605]].)",
        "mailmypassword": "Used as label for Submit button in [[Special:PasswordReset]].\n{{Identical|Reset password}}",
        "notextmatches": "Error message when there are no results",
        "prevn": "This is part of the navigation message on the top and bottom of Special pages (lists of things in alphabetical order, i.e. the '[[Special:Categories]]' page), where it is used as the first argument of {{msg-mw|Viewprevnext}}.\nIt is also used by Category pages (which do ''not'' use {{msg-mw|Viewprevnext}}).\n{{PLURAL:$1|$1}} is the number of items shown per page. It is not used when {{PLURAL:$1|$1}} is zero; not sure what happens when {{PLURAL:$1|$1}} is one.\n[[Special:WhatLinksHere|Whatlinkshere]] pages use {{msg-mw|Whatlinkshere-prev}} instead (still as an argument to {{msg-mw|Viewprevnext}}).\n\n{{Identical|Previous}}",
        "nextn": "This is part of the navigation message on the top and bottom of Special pages (lists of things in alphabetical order, i.e. the '[[Special:Categories]]' page), where it is used as the second argument of {{msg-mw|Viewprevnext}}.\n\nIt is also used by Category pages (which do ''not'' use {{msg-mw|Viewprevnext}}).\n\nParameters:\n* $1 - the number of items shown per page. It is not used when $1 is zero; not sure what happens when $1 is one.\n[[Special:WhatLinksHere|Whatlinkshere]] pages use {{msg-mw|Whatlinkshere-next}} instead (still as an argument to {{msg-mw|Viewprevnext}}).\n\n{{Identical|Next}}",
+       "prev-page": "This is part of the navigation message on the top and bottom of Category pages which links to the previous page",
+       "next-page": "This is part of the navigation message on the top and bottom of Category pages which links to the next page",
        "prevn-title": "Parameters:\n* $1 - number of search results\nSee also:\n* {{msg-mw|Viewprevnext}}",
        "nextn-title": "Parameters:\n* $1 - number of search results\nSee also:\n* {{msg-mw|Viewprevnext}}",
        "shown-title": "Parameters:\n* $1 - number of search results",
index 4069030..f9d9a6f 100644 (file)
        "wrongpassword": "Vnesli ste napačno geslo. Prosimo, poskusite znova.",
        "wrongpasswordempty": "Vpisali ste prazno geslo. Prosimo, poskusite znova.",
        "passwordtooshort": "Geslo mora imeti najmanj $1 {{PLURAL:$1|znak|znaka|znake|znakov|znakov}}.",
+       "passwordtoolong": "Gesla ne morejo biti daljša od {{PLURAL:$1|1 znaka|$1 znakov}}.",
        "password-name-match": "Vaše geslo se mora razlikovati od vašega uporabniškega imena.",
        "password-login-forbidden": "Uporaba tega uporabniškega imena in gesla je prepovedana.",
        "mailmypassword": "Ponastavitev gesla",
index 65e36d8..2f78cdf 100644 (file)
        "createaccount-text": "Neko je otvorio nalog s vašom e-adresom na {{SITENAME}} ($4) pod imenom $2 i lozinkom $3.\nPrijavite se i promenite svoju lozinku.\n\nAko je ovo greška, zanemarite ovu poruku.",
        "login-throttled": "Previše puta ste pokušali da se prijavite. \nMolimo vas da sačekate $1 pre nego što pokušate ponovo.",
        "login-abort-generic": "Neuspešna prijava – prekinuto",
+       "login-migrated-generic": "Vaš nalog je migriran i vaše korisničko više ne postoji na ovom vikiju.",
        "loginlanguagelabel": "Jezik: $1",
        "suspicious-userlogout": "Vaš zahtev za odjavu je odbijen jer je poslat od strane neispravnog pregledača ili posrednika.",
        "createacct-another-realname-tip": "Pravo ime nije obavezno.\nAko izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rada.",
        "revdelete-text-text": "Izbrisane izmene će i dalje biti vidljive u istoriji stranice, ali delovi njihovog sadržaja neće biti javno dostupnu.",
        "revdelete-text-file": "Izbrisane verzije datoteke će i dalje biti vidljive u istoriji datoteke, ali delovi njihovog sadržaja neće biti javno dostupnu.",
        "logdelete-text": "Izbrisani unosi u dnevnicima će i dalje biti vidljivi u dnevnicima, ali delovi njihovog sadržaja neće biti javno dostupnu.",
+       "revdelete-text-others": "Ostali administratori će i dalje moći da pristupe skrivenom sadržaju i vrate ga, osim ako se postave dodatna ograničenja.",
        "revdelete-confirm": "Potvrdite da nameravate ovo uraditi, da razumete posledice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].",
        "revdelete-suppress-text": "Sakrivanje izmena bi trebalo koristiti <strong>samo</strong> u sledećim slučajevima:\n* zlonamerni ili pogrdni podaci\n* neprikladni lični podaci\n*: <em>kućna adresa i broj telefona, broj kreditne kartice, JMBG itd.</em>",
        "revdelete-legend": "Ograničenja vidljivosti",
        "prefs-diffs": "Razlike",
        "prefs-help-prefershttps": "Ova podešavanja će stupiti na snagu pri sledećoj prijavi.",
        "prefswarning-warning": "Promenili ste vaša podešavanja ali niste ih još sačuvali.\nAko ne pritisnete „$1“ vaša podešavanja će biti izgubljena.",
+       "prefs-tabs-navigation-hint": "Savet: možete koristiti tipke sa levom i desnom strelicom za kretanje kroz kartice.",
        "email-address-validity-valid": "E-adresa je ispravna",
        "email-address-validity-invalid": "Unesite ispravnu e-adresu",
        "userrights": "Upravljanje korisničkim pravima",
        "userrights-changeable-col": "Grupe koje možete da promenite",
        "userrights-unchangeable-col": "Grupe koje ne možete da promenite",
        "userrights-irreversible-marker": "$1*",
+       "userrights-conflict": "Sukob promena korisničkih prava! Molimo proverite vaše izmene.",
        "userrights-removed-self": "Uspešno ste sebi skinuli prava. Zbog toga nije vam dozvoljen pristup ovoj stranici.",
        "group": "Grupa:",
        "group-user": "Korisnici",
        "right-override-export-depth": "izvoz stranica uključujući i povazene stranice do dubine od pet veza",
        "right-sendemail": "slanje e-poruka drugim korisnicima",
        "right-passwordreset": "pregledanje poruka za obnavljanje lozinke",
+       "right-managechangetags": "pravljenje i/ili brisanje [[Special:Tags|oznaka]] iz baze podataka",
        "newuserlogpage": "Dnevnik novih korisnika",
        "newuserlogpagetext": "Ovo je istorija novih korisnika.",
        "rightslog": "Dnevnik korisničkih prava",
        "license": "Licenca:",
        "license-header": "Licenca:",
        "nolicense": "nije izabrano",
+       "licenses-edit": "Uredi izbor licenci",
        "license-nopreview": "(pregled nije dostupan)",
        "upload_source_url": "(vaša izabrana datoteka od ispravnih i javno dostupnih adresa)",
        "upload_source_file": "(vaša odabrana datoteka sa vašeg računara)",
        "randomincategory-invalidcategory": "„$1“ nije valjano ime kategorije",
        "randomincategory-nopages": "Nema stranica u kategoriji [[:Category:$1|$1]].",
        "randomincategory-category": "Kategorija:",
+       "randomincategory-legend": "Slučajna stranica u kategoriji",
        "randomredirect": "Slučajno preusmerenje",
        "randomredirect-nopages": "Nema preusmerenja u imenskom prostoru „$1“.",
        "statistics": "Statistike",
        "unusedimages": "Nekorišćene datoteke",
        "wantedcategories": "Tražene kategorije",
        "wantedpages": "Tražene stranice",
+       "wantedpages-summary": "Spisak nepostojećih stranica sa najviše veza do njih, na ovom spisku se ne nalaze stranice do kojih vode preusmerenja. Za spisak pokvarenih preusmerenja pogledajte [[{{#special:BrokenRedirects}}]].",
        "wantedpages-badtitle": "Neispravan naslov u nizu rezultata: $1",
        "wantedfiles": "Tražene datoteke",
        "wantedfiletext-cat": "Sledeće datoteke se koriste, ali ne postoje. Datoteke iz drugih riznica mogu biti navedene iako ne postoje. Takve datoteke će biti <del>poništene</del> sa spiska. Pored toga, stranice koje sadrže nepostojeće datoteke se nalaze [[:$1|ovde]].",
        "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
        "listgrouprights-namespaceprotection-restrictedto": "Prava potrebna za uređivanje",
        "trackingcategories-name": "Ime poruke",
+       "trackingcategories-desc": "Koje stranice se nalaze u kategoriji",
+       "noindex-category-desc": "Stranice koje u sebi imaju magičnu reč <code><nowiki>__NOINDEX__</nowiki></code>.",
+       "index-category-desc": "Stranice koje u sebi imaju magičnu reč <code><nowiki>__INDEX__</nowiki></code> i samim tim su indeksirane od strane robota.",
+       "broken-file-category-desc": "Stranice koje imaju veze do nepostojećih datoteka.",
+       "hidden-category-category-desc": "Kategorije koje u sebi imaju magičnu reč <code><nowiki>__HIDDENCAT__</nowiki></code> i samim tim se ne prikazuju u odeljku za kategorije na stranicama.",
        "trackingcategories-nodesc": "Opis nije dostupan.",
        "trackingcategories-disabled": "Kategorija je onemogućena",
        "mailnologin": "Nema adrese za slanje",
        "tags-tag": "Naziv oznake",
        "tags-display-header": "Izgled na spiskovima izmena",
        "tags-description-header": "Opis značenja",
+       "tags-source-header": "Izvor",
        "tags-active-header": "Aktivna?",
        "tags-hitcount-header": "Označene izmene",
+       "tags-actions-header": "Radnje",
        "tags-active-yes": "Da",
        "tags-active-no": "Ne",
+       "tags-source-none": "Van upotrebe",
        "tags-edit": "uredi",
+       "tags-delete": "obriši",
+       "tags-activate": "aktiviraj",
+       "tags-deactivate": "dekativiraj",
        "tags-hitcount": "$1 {{PLURAL:$1|izmena|izmene|izmena}}",
+       "tags-manage-no-permission": "Nemate dozvolu da menjate oznake.",
        "tags-create-heading": "Nova oznaka",
+       "tags-create-tag-name": "Naziv oznake:",
        "tags-create-reason": "Razlog:",
+       "tags-create-submit": "Napravi",
+       "tags-create-no-name": "Morate navesti naziv oznake.",
        "tags-create-already-exists": "Oznaka „$1“ već postoji.",
        "tags-create-warnings-below": "Pravite novu oznaku, želite li da nastavite?",
        "tags-delete-title": "Brisanje oznaka",
        "tags-delete-explanation-initial": "Brišete oznaku „$1“ iz baze podataka.",
+       "tags-delete-reason": "Razlog:",
+       "tags-delete-submit": "Nepovratno obriši ovu oznaku",
+       "tags-delete-not-found": "Oznaka „$1“ ne postoji.",
        "tags-activate-title": "Aktiviranje oznaka",
        "tags-activate-question": "Aktivirate oznaku „$1“.",
+       "tags-activate-reason": "Razlog:",
        "tags-activate-not-allowed": "Nije moguće aktivirati oznaku „$1“.",
        "tags-activate-not-found": "Oznaka „$1“ ne postoji.",
+       "tags-activate-submit": "Aktiviraj",
        "tags-deactivate-title": "Deaktiviranje oznaka",
+       "tags-deactivate-question": "Deaktivirate oznaku „$1“.",
        "tags-deactivate-reason": "Razlog:",
        "tags-deactivate-not-allowed": "Nije moguće deaktivirati oznaku „$1“.",
+       "tags-deactivate-submit": "Dekativiraj",
        "comparepages": "Upoređivanje stranica",
        "compare-page1": "Stranica 1",
        "compare-page2": "Stranica 2",
        "logentry-block-reblock": "$1 je {{GENDER:$2|promenio|promenila}} podešavanja za blokiranje {{GENDER:$4|korisnika|korisnice}} {{GENDER:$4|$3}} u trajanju od $5 $6",
        "logentry-suppress-block": "$1 je {{GENDER:$2|blokirao|blokirala}} {{GENDER:$4|$3}} u trajanju od $5 $6",
        "logentry-suppress-reblock": "$1 je {{GENDER:$2|promenio|promenila}} podešavanja za blokiranje {{GENDER:$4|korisnika|korisnice}} {{GENDER:$4|$3}} u trajanju od $5 $6",
+       "logentry-import-upload": "$1 je {{GENDER:$2|uvezao|uvezla}} $3 otpremanjem datoteke",
+       "logentry-import-interwiki": "$1 je {{GENDER:$2|uvezao|uvezla}} $3 s drugog vikija",
        "logentry-merge-merge": "$1 je {{GENDER:$2|spojio|spojila}} $3 u $4 (sve do izmene $5)",
        "logentry-move-move": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4",
        "logentry-move-move-noredirect": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 bez ostavljanja preusmerenja",
        "logentry-upload-upload": "$1 je {{GENDER:$2|poslao|poslala}} $3",
        "logentry-upload-overwrite": "$1 je {{GENDER:$2|poslao|poslala}} novu verziju $3",
        "logentry-upload-revert": "$1 je {{GENDER:$2|poslao|poslala}} $3",
+       "log-name-managetags": "Dnevnik oznaka",
+       "log-description-managetags": "Ovaj dnevnik sadrži spisak izmena u vezi [[Special:Tags|oznaka]]. Dnevnik sadrži samo radnje izvršene od strane administratora; unosi za oznake napravljene ili obrisane od strane viki softvera se ne nalaze u ovom dnevniku.",
        "logentry-managetags-create": "$1 je {{GENDER:$2|napravio|napravila}} oznaku „$4“",
        "logentry-managetags-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} oznaku „$4“ (uklonjena je iz $5 {{PLURAL:$5|izmene ili dnevnika|izmena i/ili dnevnika}})",
        "logentry-managetags-activate": "$1 je {{GENDER:$2|aktivirao|aktivirala}} oznaku „$4“ za upotrebu od strane korisnika i botova",
        "rightsnone": "(nema)",
        "revdelete-summary": "opis izmene",
        "feedback-adding": "Dodajem povratnu informaciju na stranicu…",
+       "feedback-back": "Nazad",
        "feedback-bugcheck": "Odlično! Proverite da li je greška [$1 poznata od pre].",
        "feedback-bugnew": "Provereno. Prijavi novu grešku",
        "feedback-bugornote": "Ako ste spremni da detaljno opišete tehnički problem, onda [$1 prijavite grešku].\nU suprotnom, poslužite se jednostavnim obrascem ispod. Vaš komentar će stajati na stranici „[$3 $2]“, zajedno s korisničkim imenom i pregledačem koji koristite.",
        "feedback-cancel": "Otkaži",
        "feedback-close": "Urađeno",
+       "feedback-error-title": "Greška",
        "feedback-error1": "Greška: neprepoznat rezultat od API-ja",
        "feedback-error2": "Greška: uređivanje nije uspelo",
        "feedback-error3": "Greška: nema odgovora od API-ja",
        "feedback-subject": "Naslov:",
        "feedback-submit": "Pošalji",
        "feedback-thanks": "Hvala! Vaša povratna informacija je postavljena na stranicu „[$2 $1]“.",
+       "feedback-thanks-title": "Hvala vam!",
        "searchsuggest-search": "Pretraga",
        "searchsuggest-containing": "sadrži...",
        "api-error-badaccess-groups": "Nije vam dozvoljeno da otpremate datoteke na ovaj viki.",
index d816c23..45830d1 100644 (file)
        "wrongpassword": "Lösenordet du angav är felaktigt. Försök igen.",
        "wrongpasswordempty": "Lösenordet som angavs var blankt. Var god försök igen.",
        "passwordtooshort": "Lösenord måste innehålla minst {{PLURAL:$1|$1 tecken}}.",
+       "passwordtoolong": "Lösenord kan inte vara längre än {{PLURAL:$1|1 tecken|$1 tecken}}.",
        "password-name-match": "Ditt lösenord måste vara olikt ditt användarnamn.",
        "password-login-forbidden": "Användningen av dessa användarnamn och lösenord har förbjudits.",
        "mailmypassword": "Återställ lösenord",
index 9555a52..33c7d5c 100644 (file)
        "svg-long-error": "ไฟล์ SVG ไม่ถูกต้อง: $1",
        "show-big-image": "ไฟล์ต้นฉบับ",
        "show-big-image-preview": "ขนาดของตัวอย่างนี้: $1",
-       "show-big-image-other": "ความละเอียดอื่น: $1",
+       "show-big-image-other": "{{PLURAL:$2|ความละเอียด|ความละเอียด}}อื่น: $1",
        "show-big-image-size": "$1 × $2 พิกเซล",
        "file-info-gif-looped": "วนซ้ำ",
        "file-info-gif-frames": "$1 {{PLURAL:$1|เฟรม|เฟรม}}",
index 14dc1e4..a910adf 100644 (file)
        "revdelete-uname-unhid": "kullanıcı adı gösterildi",
        "revdelete-restricted": "hizmetliler için uygulanmış kısıtlamalar",
        "revdelete-unrestricted": "hizmetliler için kaldırılmış kısıtlamalar",
-       "logentry-block-block": "$1 {{GENDER:$2|engelledi}} {{GENDER:$4|$3}} engelleme süresi $5 $6",
+       "logentry-block-block": "$1 {{GENDER:$2|engelledi}} {{GENDER:$4|$3}} engelleme süresi: $5 $6",
        "logentry-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} engelleme süresi $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} engelleme süresi $5 $6",
        "logentry-move-move": "$1, $3 sayfasını $4 sayfasına {{GENDER:$2|taşıdı}}",
index baa029f..49d66ac 100644 (file)
        "compareselectedversions": "Сайланган юрамаларны чагыштыру",
        "showhideselectedversions": "Сайланган юрамаларны күрсәтү/яшерү",
        "editundo": "үткәрмәү",
-       "diff-multi-sameuser": "(шул ук сандагы кулланучының {{PLURAL:$1|арадаш бер юрамасы|$1 арадаш юрамасы}} күрсәтелмәгән)",
+       "diff-multi-sameuser": "(шул ук кулланучының {{PLURAL:$1|бер арадаш юрамасы|$1 арадаш юрамасы}} күрсәтелмәгән)",
        "diff-multi-otherusers": "({{PLURAL:$2|Башка бер кулланучының|$2 кулланучының}} {{PLURAL:$1|бер арадаш юрамасы|$1 арадаш юрамасы}} күрсәтелмәгән)",
        "diff-multi-manyusers": "($2 күбрәк {{PLURAL:$2|кулланучының|кулланучының}} {{PLURAL:$1|Бер арадаш юрамасы|$1 арадаш юрамасы}} күрсәтелмәгән)",
        "searchresults": "Эзләү нәтиҗәләре",
        "userrights-lookup-user": "Кулланучы төркемнәре белән идарә итү",
        "userrights-user-editname": "Кулланучының исемен кертегез:",
        "editusergroup": "Кулланучының төркемнәрен алмаштыру",
-       "editinguser": "'''[[User:$1|$1]]''' кулланучысының хокукларын үзгәртү ([[User talk:$1|{{int:talkpagelinktext}}]]{{int:pipe-separator}}[[Special:Contributions/$1|{{int:contribslink}}]])",
+       "editinguser": "Кулланучы <strong>[[User:$1|$1]]</strong> $2 хокукларын үзгәртү",
        "userrights-editusergroup": "Кулланучының төркемнәрен алмаштыру",
        "saveusergroups": "Кулланучы төркемнәрен саклау",
        "userrights-groupsmember": "Әгъза:",
        "userrights-reason": "Сәбәп:",
        "userrights-no-interwiki": "Сезнең башка викиларда кулланучыларның хокукларын үзгәртергә хокукларыгыз юк.",
        "userrights-nodatabase": "Бирелгән $1 базасы юк яисә  локаль булып тормый.",
-       "userrights-changeable-col": "Сезнең тарафтан үзгәртә ала торган төркемнәр",
-       "userrights-unchangeable-col": "Сезнең тарафтан үзгәртә алмый торган төркемнәр",
+       "userrights-nologin": "Кулланучыларга вәкаләтләр билгеләү өчен идарәче хисап язмасы белән [[Special:UserLogin|керергә кирәк]]",
+       "userrights-notallowed": "Сезнең кулланучыларга вәкаләтләр тапшырырга яки кире алырга хокукы юк.",
+       "userrights-changeable-col": "Сезнең тарафтан үзгәртелми торган төркемнәр",
+       "userrights-unchangeable-col": "Сезнең тарафтан үзгәртелми торган төркемнәр",
        "userrights-irreversible-marker": "$1*",
+       "userrights-conflict": "Кулланучы хокукларын үзгәртү конфликты! Төзәтмәләрегезне тикшерегез, аннары кабатлагыз.",
+       "userrights-removed-self": "Сез үзегезне хокукларыгыздан мәхрүм иттегез. Шул сәбәпле сез бу сәхифәгә башка керә алмыйсыз.",
        "group": "Төркем:",
        "group-user": "Кулланучылар",
        "group-autoconfirmed": "Авторасланган кулланучы",
        "group-bot": "Ботлар",
        "group-sysop": "Идарәчеләр",
        "group-bureaucrat": "Бюрократлар",
-       "group-suppress": "ТикÑ\88еÑ\80Ò¯Ñ\87еләр",
+       "group-suppress": "Ð\9dазиÑ\80ләр",
        "group-all": "(барлык)",
        "group-user-member": "{{GENDER:$1|кулланучы}}",
        "group-autoconfirmed-member": "{{GENDER:$1|авторасланган кулланучы}}",
        "group-bot-member": "{{GENDER:$1|бот}}",
        "group-sysop-member": "{{GENDER:$1|идарәче}}",
        "group-bureaucrat-member": "{{GENDER:$1|бюрократ}}",
-       "group-suppress-member": "{{GENDER:$1|ТикÑ\88еÑ\80Ò¯Ñ\87е}}",
+       "group-suppress-member": "{{GENDER:$1|Ð\9dазиÑ\80}}",
        "grouppage-user": "{{ns:project}}:Кулланучылар",
        "grouppage-autoconfirmed": "{{ns:project}}:Авторасланган кулланучылар",
        "grouppage-bot": "{{ns:project}}:Ботлар",
        "grouppage-sysop": "{{ns:project}}:Идарәчеләр",
        "grouppage-bureaucrat": "{{ns:project}}:Бюрократлар",
-       "grouppage-suppress": "{{ns:project}}:ТикÑ\88еÑ\80Ò¯Ñ\87еләр",
+       "grouppage-suppress": "{{ns:project}}:Ð\9dазиÑ\80ләр",
        "right-read": "Битләрне карау",
        "right-edit": "Битләрне үзгәртү",
        "right-createpage": "битләр ясау (бәхәс булмаганнарын)",
        "right-createtalk": "бәхәс битен ясау",
-       "right-createaccount": "яңа кулланучы битен ясау",
-       "right-minoredit": "\"кече үзгәртү\" тамгасын кую",
+       "right-createaccount": "яңа кулланучы хисап язмасын ясау",
+       "right-minoredit": "\"кече төзәтмә\" тамгасын кую",
        "right-move": "Битләрне күчерү",
+       "right-move-subpages": "Битләрне асбитләр белән бергә күчерү",
+       "right-move-categorypages": "төркемдәге битләрне күчерү",
        "right-movefile": "файлларның исемен алмаштыру",
+       "right-suppressredirect": "Элекке исемнән юнәлтү ясамыйча исемне алмаштыру",
        "right-upload": "файлларны йөкләү",
+       "right-reupload": "Булган файллар өстеннән язарга",
        "right-delete": "битләрне бетерү",
        "right-editinterface": "Кулланучы интерфейсын үзгәртү",
        "newuserlogpage": "Кулланучыларны теркәү көндәлеге",
index 8a4500c..84dae98 100644 (file)
        "accmailtitle": "Maxfiy soʻz joʻnatildi",
        "newarticle": "(Yangi)",
        "newarticletext": "Bu sahifa hali mavjud emas.\nSahifani yaratish uchun quyida matn kiritishingiz mumkin (qoʻshimcha axborot uchun [$1 yordam sahifasini] koʻring).\nAgar bu sahifaga xatolik sabab kelib qolgan boʻlsangiz brauzeringizning '''orqaga''' tugmasini bosing.",
-       "anontalkpagetext": "----''Ushbu munozara sahifasi hali hisob yozuvini yaratmagan, yoki undan foydalanmaydigan anonim ishtirokchiga tegishli.\nShu sababli tenglashtirish uchun raqamli IP-manzildan foydalaniladi.\nUshbu manzilning oʻzi bir nechta boshqa ishtirokchilarga ham mos kelishi mumkin.\nAgar siz anonim ishtirokchi boʻlsangiz va siz oʻzingizga yoʻnaltirilmagan xabar oldim deb taxmin qilsangiz, iltimos, boshqa anonim ishtirokchilar bilan mumkin boʻlgan chalkashliklarni chetlab oʻtish uchun [[Special:UserLogin/signup|hisob yozuvi yarating]] yoki [[Special:UserLogin|tizimga kiring]].''",
+       "anontalkpagetext": "----\n<em>Ushbu munozara sahifasi hisob yozuvi yaratmagan (yoki yaratishni xohlamaydigan) anonim foydalanuvchiga tegishli.</em>\n\nShu sababli, uni aniqlash uchun raqamli IP-manzildan foydalaniladi.\nUshbu IP-manzil bir nechta foydalanuvchilarga tegishli boʻlishi mumkin.\nAgar siz anonim foydalanuvchi boʻlsangiz va qoldirilgan xabarlar sizga yoʻnaltirilmagan deb hisoblasangiz, iltimos, boshqa anonim foydalanuvchilar bilan adashtirib yubormasliklari uchun [[Special:UserLogin/signup|hisob yozuvi yarating]] yoki [[Special:UserLogin|tizimga kiring]].",
        "noarticletext": "Bu sahifada hozircha hech qanday matn yoʻq. Siz bu sarlavhani boshqa sahifalardan [[Special:Search/{{PAGENAME}}|qidirishingiz]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tegishli qaydlarga qarashingiz] yoki bu sahifani [{{fullurl:{{FULLPAGENAME}}|action=edit}} tahrirlashingiz]</span> mumkin.",
        "userpage-userdoesnotexist-view": "\"$1\" foydalanuvchi hisobi roʻyxatga olinmagan.",
        "clearyourcache": "'''Eslatma.''' Saqlaganingizdan so'ng o'zgarishlarni ko'rish uchun siz o'z brauzeringiz keshini tozalashingizga to'gri kelishi mumkin.\n* '''Firefox / Safari:''' ''Shift'' tugmasini bosgan holda, ''Yangilash'' unsurlar darchasini bosing, yoki ''Ctrl-F5'' yoki ''Ctrl-R'' (Macda ''⌘-R'') ni bosing\n* '''Google Chrome:''' ''Ctrl-Shift-R'' (Macda ''⌘-Shift-R'') ni bosing\n* '''Internet Explorer:''' ''Ctrl''ni bosgan holda, ''Yangilash''ni bosing, yoki ''Ctrl-F5''ni bosing\n* '''Opera:''' ''Asboblar → Moslamalar'' menyusidan keshni tozalashni tanlang",
        "thumbnail-more": "Kattalashtir",
        "thumbnail_error": "Tasvir yaratishda xatolik: $1",
        "importlogpage": "Import qilish qaydlari",
-       "import-logentry-upload": "\"[[$1]]\"ni yuklash yo'li bilan import qildi",
        "tooltip-pt-userpage": "Foydalanuvchi sahifangiz",
        "tooltip-pt-anonuserpage": "Siznig ip manzilingiz foydalanuvchi sahifasi",
        "tooltip-pt-mytalk": "Suhbat sahifangiz",
        "searchsuggest-containing": "ichida bu boʻlgan...",
        "api-error-unknown-code": "Noaniq xato: \"$1\".",
        "api-error-unknownerror": "Noaniq xato: \"$1\".",
-       "limitreport-title": "Tahlillagich maʼlumotlari:"
+       "limitreport-title": "Tahlillagich maʼlumotlari:",
+       "special-characters-group-latin": "Lotin",
+       "special-characters-group-latinextended": "Lotin kengaytirilgan",
+       "special-characters-group-ipa": "XFA (MFA)",
+       "special-characters-group-symbols": "Belgilar",
+       "special-characters-group-greek": "Yunon",
+       "special-characters-group-cyrillic": "Kirill",
+       "special-characters-group-arabic": "Arab",
+       "special-characters-group-arabicextended": "Arab kengaytirilgan",
+       "special-characters-group-persian": "Forsiy",
+       "special-characters-group-hebrew": "Yahudiy",
+       "special-characters-group-bangla": "Bengal",
+       "special-characters-group-tamil": "Tamil",
+       "special-characters-group-telugu": "Telugu",
+       "special-characters-group-sinhala": "Singal",
+       "special-characters-group-gujarati": "Gujarati",
+       "special-characters-group-devanagari": "Devanagari",
+       "special-characters-group-thai": "Tay",
+       "special-characters-group-lao": "Laos",
+       "special-characters-group-khmer": "Kxmer",
+       "special-characters-title-emdash": "uzun tire",
+       "special-characters-title-minus": "minus belgisi"
 }
index bac6fd8..287fe30 100644 (file)
        "wrongpassword": "您输入的密码错误。请重试。",
        "wrongpasswordempty": "密码输入为空。请重试。",
        "passwordtooshort": "您的密码至少需要$1个字符。",
+       "passwordtoolong": "密码不能超过{{PLURAL:$1|$1个字符}}。",
        "password-name-match": "您的密码必须和您的用户名不相同。",
        "password-login-forbidden": "这个用户名称及密码的使用是被禁止的。",
        "mailmypassword": "重置密码",
index 560886e..2f9c812 100644 (file)
        "wrongpassword": "您輸入的密碼錯誤,請再試一次。",
        "wrongpasswordempty": "輸入的密碼是空的。\n請再試一次。",
        "passwordtooshort": "您的密碼至少需要 $1 個字元。",
+       "passwordtoolong": "密碼不能超過 {{PLURAL:$1|1 個字元|$1 個字元}}。",
        "password-name-match": "您的密碼不可以跟使用者名稱相同。",
        "password-login-forbidden": "此使用者名稱和密碼已被禁止使用。",
        "mailmypassword": "重設密碼",
index 2247b36..f88650b 100644 (file)
@@ -13,7 +13,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'ܡܝܕܝܐ',
        NS_SPECIAL          => 'ܕܝܠܢܝܐ',
-       NS_MAIN             => '',
        NS_TALK             => 'ܡܡܠܠܐ',
        NS_USER             => 'ܡܦܠܚܢܐ',
        NS_USER_TALK        => 'ܡܡܠܠܐ_ܕܡܦܠܚܢܐ',
index b218e3c..23da7a3 100644 (file)
@@ -10,7 +10,6 @@
 
 $namespaceNames = array(
        NS_SPECIAL          => 'Xüsusi',
-       NS_MAIN             => '',
        NS_TALK             => 'Müzakirə',
        NS_USER             => 'İstifadəçi',
        NS_USER_TALK        => 'İstifadəçi_müzakirəsi',
index 63c88a8..74d3bb9 100644 (file)
@@ -14,7 +14,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'مئدیا',
        NS_SPECIAL          => 'اؤزل',
-       NS_MAIN             => '',
        NS_TALK             => 'دانیشیق',
        NS_USER             => 'ایستیفاده‌چی',
        NS_USER_TALK        => 'ایستیفاده‌چی_دانیشیغی',
index 393c6e5..027161f 100644 (file)
@@ -14,7 +14,6 @@ $fallback8bitEncoding = 'windows-1256';
 $namespaceNames = array(
        NS_MEDIA            => 'میدیا',
        NS_SPECIAL          => 'تایبەت',
-       NS_MAIN             => '',
        NS_TALK             => 'وتووێژ',
        NS_USER             => 'بەکارھێنەر',
        NS_USER_TALK        => 'لێدوانی_بەکارھێنەر',
index 1f49212..72d645e 100644 (file)
@@ -13,7 +13,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'މީޑިއާ',
        NS_SPECIAL          => 'ޚާއްސަ',
-       NS_MAIN             => '',
        NS_TALK             => 'ޚިޔާލު',
        NS_USER             => 'މެމްބަރު',
        NS_USER_TALK        => 'މެމްބަރުގެ_ވާހަކަ',
index 6c03f1d..4d964fb 100644 (file)
@@ -14,7 +14,6 @@ $fallback8bitEncoding = 'windows-1256';
 $namespaceNames = array(
        NS_MEDIA            => 'مدیا',
        NS_SPECIAL          => 'ویژه',
-       NS_MAIN             => '',
        NS_TALK             => 'بحث',
        NS_USER             => 'کاربر',
        NS_USER_TALK        => 'بحث_کاربر',
index 1f578a3..3d7fc43 100644 (file)
@@ -16,7 +16,6 @@ $fallback8bitEncoding = 'windows-1255';
 $namespaceNames = array(
        NS_MEDIA            => 'מדיה',
        NS_SPECIAL          => 'מיוחד',
-       NS_MAIN             => '',
        NS_TALK             => 'שיחה',
        NS_USER             => 'משתמש',
        NS_USER_TALK        => 'שיחת_משתמש',
index 4cd2495..bcc8328 100644 (file)
@@ -12,7 +12,6 @@ $fallback = 'ur';
 $rtl = true;
 
 $namespaceNames = array(
-       NS_MAIN             => '',
        NS_MEDIA            => 'میڈیا',
        NS_SPECIAL          => 'خاص',
        NS_TALK             => 'مشقولگی',
index a33efef..8749ccb 100644 (file)
@@ -50,7 +50,6 @@ $fallback8bitEncoding = 'windows-1256';
 $namespaceNames = array(
        NS_MEDIA            => 'تاسپا',
        NS_SPECIAL          => 'ارنايى',
-       NS_MAIN             => '',
        NS_TALK             => 'تالقىلاۋ',
        NS_USER             => 'قاتىسۋشى',
        NS_USER_TALK        => 'قاتىسۋشى_تالقىلاۋى',
index 89f877f..cdea1f4 100644 (file)
@@ -16,7 +16,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'میڈیا',
        NS_SPECIAL          => 'خاص',
-       NS_MAIN             => '',
        NS_TALK             => 'بَحَژ',
        NS_USER             => 'رُکُن',
        NS_USER_TALK        => 'رُکُن_بَحَژ',
index 16ecac2..6203b24 100644 (file)
@@ -26,7 +26,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'مدیا',
        NS_SPECIAL          => 'شا',
-       NS_MAIN             => '',
        NS_TALK             => 'گپ',
        NS_USER             => 'کارور',
        NS_USER_TALK        => 'کارور_گپ',
index e66cb02..f87d770 100644 (file)
@@ -96,7 +96,6 @@ $bookstoreList = array(
 $namespaceNames = array(
        NS_MEDIA          => 'Media',
        NS_SPECIAL        => 'Spezial',
-       NS_MAIN           => '',
        NS_TALK           => 'Diskuschoon',
        NS_USER           => 'Bruker',
        NS_USER_TALK      => 'Bruker_Diskuschoon',
index 1394c16..81a6d2f 100644 (file)
@@ -31,7 +31,6 @@ $rtl = true;
 $namespaceNames = array(
        NS_MEDIA            => 'وسیط',
        NS_SPECIAL          => 'خاص',
-       NS_MAIN             => '',
        NS_TALK             => 'تبادلۂ_خیال',
        NS_USER             => 'صارف',
        NS_USER_TALK        => 'تبادلۂ_خیال_صارف',
index 6075edf..f9d2eac 100644 (file)
@@ -1709,14 +1709,6 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
 
-       'oojs-ui.styles' => array(
-               'position' => 'top',
-               'skinStyles' => array(
-                       'default' => 'resources/lib/oojs-ui/oojs-ui-mediawiki.css',
-               ),
-               'targets' => array( 'desktop', 'mobile' ),
-       ),
-
        // FIXME: This is a bit of a mess; T92551 requests fixing
        'oojs-ui.styles.icons-alerts' => array(
                'position' => 'top',
index 2b7f4cd..e965352 100644 (file)
@@ -146,6 +146,13 @@ Template:table_attribs_4
 | style="background-color:#DC241f;" width="10px" |
 !! endarticle
 
+!! article
+Template:table_attribs_5
+!! text
+<noinclude>
+|</noinclude>style="color:red;"||Bar
+!! endarticle
+
 !! article
 Template:table_header_cells
 !! text
@@ -4080,6 +4087,7 @@ Definition Lists: colons occurring in tags
 :b</div>
 ;{{echo|a:b}}
 ;{{echo|''a:b''}}
+;;;''a:b''
 !! html+tidy
 <dl>
 <dt>a</dt>
@@ -4101,6 +4109,17 @@ Definition Lists: colons occurring in tags
 <dd>b</dd>
 <dt><i>a:b</i></dt>
 </dl>
+<dl>
+<dd>
+<dl>
+<dd>
+<dl>
+<dt><i>a:b</i></dt>
+</dl>
+</dd>
+</dl>
+</dd>
+</dl>
 !! end
 
 !! test
@@ -5799,6 +5818,7 @@ Indented table markup mixed with indented pre content (proposed in bug 6200)
 {|
 |{{table_attribs}}
 | {{table_attribs}}
+|| {{table_attribs_5}}
 | <!--foo--> <!--bar--> <!--baz--> {{table_attribs}}
 |align=center {{table_attribs}}
 | <!--foo--> align=center <!--bar--> {{table_attribs}}
@@ -5810,6 +5830,9 @@ Indented table markup mixed with indented pre content (proposed in bug 6200)
 </td>
 <td style="color:red;">Foo
 </td>
+<td> style="color:red;"</td>
+<td>Bar
+</td>
 <td style="color:red;">Foo
 </td>
 <td align="center" style="color:red;">Foo
@@ -5929,7 +5952,7 @@ Wikitext table with a lot of comments
 <!-- c0 -->
 | foo
 <!-- c1 -->
-|- <!-- c2 -->
+|-<!-- c2 -->
 <!-- c3 -->
 |<!-- c4 -->
 <!-- c5 -->
@@ -5945,6 +5968,26 @@ Wikitext table with a lot of comments
 
 !! end
 
+!! test
+Wikitext table comments represented in parsoid dom
+!! wikitext
+{|<!--c1--><!--c2-->
+|-<!--c3-->
+| x
+|}
+!! html/php+tidy
+<table>
+<tr>
+<td>x</td>
+</tr>
+</table>
+!! html/parsoid
+<table><!--c1--><!--c2-->
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'><!--c3-->
+<td data-parsoid='{"autoInsertedEnd":true}'> x</td></tr>
+</tbody></table>
+!! end
+
 !! test
 Wikitext table with double-line table cell
 !! wikitext
@@ -6396,7 +6439,7 @@ parsoid=html2wt
 Testing serialization after deletion of table cells
 !!options
 parsoid={
-  "modes": ["wt2wt"],
+  "modes": ["wt2wt", "selser"],
   "changes": [
     ["#x", "remove"]
   ]
@@ -7656,6 +7699,7 @@ Blah blah blah
 ###
 ### Redirects, Parsoid-only
 ###
+
 !! test
 1. Simple redirect to page
 !! options
@@ -7666,16 +7710,20 @@ parsoid
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
-# Only wt2html and html2html since "Main_Page" will serialize to "Main Page"
 !! test
 2. Other redirect variants
-!! options
-parsoid=wt2html,wt2wt
 !! wikitext
 #REDIRECT [[Main_Page]]
+!! html/parsoid
+<link rel="mw:PageProp/redirect" href="./Main_Page" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Main_Page"},"sa":{"href":"Main_Page"}}'/>
+!! end
+
+!! test
+3. Other redirect variants
+!! wikitext
 #REDIRECT [[<nowiki>[[Bar]]</nowiki>]]
 !! html/parsoid
-<link rel="mw:PageProp/redirect" href="./Main_Page"><link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D">
+<link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./%5B%5BBar%5D%5D"},"sa":{"href":"&lt;nowiki>[[Bar]]&lt;/nowiki>"}}'/>
 !! end
 
 !! test
@@ -7732,7 +7780,7 @@ parsoid=wt2html
 !! test
 Redirect to category
 !! options
-parsoid=wt2html
+parsoid=wt2wt,wt2html
 !! wikitext
 #REDIRECT [[Category:Foo]]
 !! html
@@ -7752,11 +7800,11 @@ parsoid=wt2html
 !! test
 Redirect to category page
 !! options
-parsoid=wt2html,html2html
+parsoid
 !! wikitext
 #REDIRECT [[:Category:Foo]]
 !! html
-<p><a rel="mw:WikiLink" href="Category:Foo" title="Category:Foo">Category:Foo</a></p>
+<link rel="mw:PageProp/redirect" href="Category:Foo" title="Category:Foo"/>
 !! end
 
 !! test
@@ -7786,7 +7834,7 @@ parsoid
 !! wikitext
 #REDIRECT [[en:File:Wiki.png]]
 !! html
-<link rel="mw:PageProp/redirect" href="File:Wiki.png">
+<link rel="mw:PageProp/redirect" href="./File:Wiki.png">
 !! end
 
 !! test
@@ -7796,7 +7844,7 @@ parsoid
 !! wikitext
 #REDIRECT [[meatball:File:Wiki.png]]
 !! html
-<link rel="mw:PageProp/redirect" href="File:Wiki.png">
+<link rel="mw:PageProp/redirect" href="./File:Wiki.png">
 !! end
 
 !! test
@@ -7810,6 +7858,18 @@ language=is
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
+!! test
+Redirect syntax under text isn't considered a redirect
+!! wikitext
+some text
+#redirect [[Main Page]]
+!! html/parsoid
+<p>some text</p>
+<ol data-parsoid='{}'><li data-parsoid='{}'>redirect <a rel="mw:WikiLink" href="./Main_Page" title="Main Page" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page"},"sa":{"href":"Main Page"}}'>Main Page</a></li></ol>
+!! end
+
+# FIXME: Should hoist the redirect to the top of the page and ensure there
+# is only one.
 !! test
 New redirect
 !! options
@@ -11723,7 +11783,7 @@ parsoid=wt2html,wt2wt,html2html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -11734,7 +11794,7 @@ Simple image (using File: namespace, now canonical)
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -11745,7 +11805,7 @@ Right-aligned image
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
 !! end
 
 !! test
@@ -11756,7 +11816,7 @@ Image with caption
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
@@ -11767,7 +11827,7 @@ Image with caption, bug 53312 #1
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page stuff"><img alt="Caption page stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page stuff</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page stuff</figcaption></figure>
 !! end
 
 !! test
@@ -11778,7 +11838,7 @@ Image with caption, bug 53312 #2
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page="><img alt="Caption page=" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page=</figcaption></figure>
 !! end
 
 !! test
@@ -11789,7 +11849,7 @@ Image with caption, bug 53312 #3
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page=stuff"><img alt="Caption page=stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=stuff</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page=stuff</figcaption></figure>
 !! end
 
 !! test
@@ -11805,7 +11865,7 @@ thumbsize=220
 <div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Caption <a href="/index.php?title=Link1&amp;action=edit&amp;redlink=1" class="new" title="Link1 (page does not exist)">Link1</a> [[]] <a href="/index.php?title=Link2&amp;action=edit&amp;redlink=1" class="new" title="Link2 (page does not exist)">Link2</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption <a rel="mw:WikiLink" href="./Link1" title="Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"}}'>Link1</a>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption <a rel="mw:WikiLink" href="./Link1" title="Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"}}'>Link1</a>
 [[]]
 <a rel="mw:WikiLink" href="./Link2" title="Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"}}'>Link2</a>
 </figcaption></figure>
@@ -11837,7 +11897,7 @@ Linktrails should not work for images: [[File:Foobar.jpg]]s
 <p>Linktrails should not work for images: <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>s
 </p>
 !! html/parsoid
-<p>Linktrails should not work for images: <span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span>s</p>
+<p>Linktrails should not work for images: <span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span>s</p>
 !! end
 
 !! test
@@ -11850,7 +11910,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
@@ -11861,7 +11921,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[24,38,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[24,38,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
 !! end
 
 !! test
@@ -11872,7 +11932,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt3" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,32,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[33,47,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt3" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,32,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[33,47,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
 !! end
 
 !! test
@@ -11883,7 +11943,7 @@ parsoid=wt2html,wt2wt,html2html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}' data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,31,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">50px&lt;/span>"}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50"/></a></span></p>
+<p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}' data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,31,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">50px&lt;/span>"}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
 !! end
 
 ## Parsoid does not provide editing support for images where templates produce multiple image attributes.
@@ -11896,7 +11956,7 @@ Image with multiple attributes from the same template
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
@@ -11927,9 +11987,9 @@ thumbsize=220
 </div>
 <p>456</p>
 !! html/parsoid
-<p>123<span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>456</p>
-<p>123</p><figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure><p>456</p>
-<p>123</p><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220"></a></figure><p>456</p>
+<p>123<span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span>456</p>
+<p>123</p><figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure><p>456</p>
+<p>123</p><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></figure><p>456</p>
 !! end
 
 !! test
@@ -11940,7 +12000,7 @@ Image with multiple captions -- only last one is accepted
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption3 - accepted"><img alt="Caption3 - accepted" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption3 - accepted</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption3 - accepted</figcaption></figure>
 !! end
 
 !! test
@@ -11951,7 +12011,7 @@ Image with multiple widths -- use last
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="34" width="300"/></a></span></p>
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></span></p>
 !! end
 
 !! test
@@ -11967,8 +12027,8 @@ thumbsize=220
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" style="vertical-align: middle" /></a>
 </p>
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -11983,9 +12043,9 @@ Image with width attribute at different positions
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption"><img alt="Caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a></div>
 
 !! html/parsoid
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
 !! end
 
 # a sad bit of backward-compatibility
@@ -12001,7 +12061,7 @@ parsoid=wt2html,wt2wt,html2html
 <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/177px-Foobar.jpg" width="177" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/265px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/353px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="2" width="20"/></a></span> <span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="177"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="2" width="20"/></a></span> <span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="20" width="177"/></a></span></p>
 !! end
 
 !! test
@@ -12012,7 +12072,7 @@ Image with link parameter, wiki target
 <p><a href="/wiki/Main_Page" title="Main Page"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 # parsoid bug 49293 (part 1)
@@ -12024,7 +12084,7 @@ Image with link parameter, URL target
 <p><a href="http://example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 # parsoid bug 49293 (part 2)
@@ -12036,7 +12096,7 @@ Image with link parameter, protocol-less URL target
 <p><a href="//example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="//example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="//example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12091,7 +12151,7 @@ Image with empty link parameter
 <p><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" />
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><span><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></span></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><span><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></span></span></p>
 !! end
 
 !! test
@@ -12102,7 +12162,7 @@ Image with link parameter (wiki target) and unnamed parameter
 <p><a href="/wiki/Main_Page" title="Title"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12113,7 +12173,7 @@ Image with link parameter (URL target) and unnamed parameter
 <p><a href="http://example.com/" title="Title" rel="nofollow"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12127,7 +12187,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12140,7 +12200,7 @@ thumbsize=220
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/File:Foobar.jpg"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12154,7 +12214,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12168,7 +12228,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="http://example.com"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="http://example.com"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="http://example.com"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12182,7 +12242,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" />  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><span><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></span><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><span><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></span><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12196,7 +12256,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="alttext" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img alt="alttext" resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img alt="alttext" resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
@@ -12209,7 +12269,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
@@ -12222,7 +12282,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Altitude" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
@@ -12238,8 +12298,8 @@ parsoid=wt2html,wt2wt,html2html
 </p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="testing bold in alt" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;testing '''bold''' in alt&quot;}"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img alt="testing bold in alt" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;testing '''bold''' in alt&quot;}"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="testing bold in alt" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12250,7 +12310,7 @@ Alt image option should handle most kinds of wikitext without barfing
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a link and a bold template." src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is the image caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"This is the image caption"},{"ck":"alt","ak":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}."}]}' data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["alt",{"html":"alt=This is a &lt;a rel=\"mw:WikiLink\" href=\"./Link\" title=\"Link\" data-parsoid=\"{&amp;quot;stx&amp;quot;:&amp;quot;simple&amp;quot;,&amp;quot;a&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;./Link&amp;quot;},&amp;quot;sa&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;link&amp;quot;},&amp;quot;dsr&amp;quot;:[65,73,2,2]}\">link&lt;/a> and a &lt;i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[80,106,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;&#39;&#39;bold template&#39;&#39;&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">bold template&lt;/i>."}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img alt="This is a link and a bold template." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"alt":"This is a link and a bold template.","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}.","resource":"Image:Foobar.jpg"}}'/></a><figcaption>This is the image caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"This is the image caption"},{"ck":"alt","ak":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}."}]}' data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["alt",{"html":"alt=This is a &lt;a rel=\"mw:WikiLink\" href=\"./Link\" title=\"Link\" data-parsoid=\"{&amp;quot;stx&amp;quot;:&amp;quot;simple&amp;quot;,&amp;quot;a&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;./Link&amp;quot;},&amp;quot;sa&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;link&amp;quot;},&amp;quot;dsr&amp;quot;:[65,73,2,2]}\">link&lt;/a> and a &lt;i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[80,106,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;&#39;&#39;bold template&#39;&#39;&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">bold template&lt;/i>."}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img alt="This is a link and a bold template." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"This is a link and a bold template.","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}.","resource":"Image:Foobar.jpg"}}'/></a><figcaption>This is the image caption</figcaption></figure>
 !! end
 
 ###################
@@ -12274,9 +12334,9 @@ parsoid=wt2html,wt2wt,html2html
 </p><p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
 !! end
 
 !! test
@@ -12293,9 +12353,9 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12312,9 +12372,9 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 ###################
@@ -12341,8 +12401,8 @@ parsoid=wt2html,wt2wt,html2html
 </p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="2000" height="227" class="thumbborder" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
-<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="227" width="2000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="227" width="2000"/></a></span></p>
 !! end
 
 !! test
@@ -12358,8 +12418,8 @@ parsoid=wt2html,wt2wt,html2html
 </p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/1000px-Foobar.jpg" width="1000" height="113" class="thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/1500px-Foobar.jpg 1.5x, http://example.com/images/3/3a/Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
-<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="113" width="1000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="113" width="1000"/></a></span></p>
 !! end
 
 !! test
@@ -12372,7 +12432,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:52px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div></div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></figure>
 !! end
 
 !! test
@@ -12388,8 +12448,8 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:2002px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div></div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="1500" width="2000"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="1500" width="2000"/></a></figure>
 !! end
 
 !! test
@@ -12402,7 +12462,7 @@ parsoid=wt2html,wt2wt,html2html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
 !! end
 
 !! test
@@ -12418,8 +12478,8 @@ parsoid=wt2html,wt2wt,html2html
 </p><p><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a>
 </p>
 !! html/parsoid
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="1500" width="2000"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="1500" width="2000"/></a></span></p>
 !! end
 
 !! test
@@ -12441,10 +12501,10 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
-<figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
-<figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
-<figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
 !! end
 
 ###################
@@ -12477,7 +12537,7 @@ Frameless image caption with a free URL
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"http://example.com"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"http://example.com"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12490,7 +12550,7 @@ thumbsize=220
 <div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
 !! end
 
 !! test
@@ -12504,7 +12564,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
 !! end
 
 !! test
@@ -12516,7 +12576,7 @@ SVG thumbnails with no language set
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12529,7 +12589,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=File:Foobar.svg&amp;lang=de" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/langde-180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langde-270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langde-360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12542,7 +12602,7 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>lang=invalid.language.code</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>lang=invalid.language.code</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>lang=invalid.language.code</figcaption></figure>
 !! end
 
 !! test
@@ -12553,7 +12613,7 @@ BUG 1887: A ISBN with a thumbnail
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a href="Special:BookSources/1235467890" rel="mw:ExtLink">ISBN 1235467890</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a href="Special:BookSources/1235467890" rel="mw:ExtLink">ISBN 1235467890</a></figcaption></figure>
 !! end
 
 !! test
@@ -12564,7 +12624,7 @@ BUG 1887: A RFC with a thumbnail
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is <a href="//tools.ietf.org/html/rfc12354" rel="mw:ExtLink">RFC 12354</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>This is <a href="//tools.ietf.org/html/rfc12354" rel="mw:ExtLink">RFC 12354</a></figcaption></figure>
 !! end
 
 !! test
@@ -12575,7 +12635,7 @@ BUG 1887: A mailto link with a thumbnail
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
 !! end
 
 # Pending resolution to bug 368
@@ -12587,7 +12647,7 @@ BUG 648: Frameless image caption with a link
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12598,7 +12658,7 @@ BUG 648: Frameless image caption with a link (suffix)
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a linkfoo in it"><img alt="text with a linkfoo in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]]foo in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]]foo in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12609,7 +12669,7 @@ BUG 648: Frameless image caption with an interwiki link
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img alt="text with a MeatBall:Link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12620,7 +12680,7 @@ BUG 648: Frameless image caption with a piped interwiki link
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link|link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link|link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12631,7 +12691,7 @@ Escape HTML special chars in image alt text
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="&amp; &lt; &gt; &quot;"><img alt="&amp; &lt; &gt; &quot;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp; &lt; > \""}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp; &lt; > \""}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12642,7 +12702,7 @@ BUG 499: Alt text should have &#1234;, not &amp;1234;
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="♀"><img alt="♀" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp;#9792;"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp;#9792;"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12666,7 +12726,7 @@ Image caption containing another image
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption with another <a href="/wiki/File:Thumb.png" class="image" title="image"><img alt="image" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" /></a> inside it!</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is a caption with another <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"image"}'><a href="File:Thumb.png"><img resource="./File:Thumb.png" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a></span> inside it!</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>This is a caption with another <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"image"}'><a href="./File:Thumb.png"><img resource="./File:Thumb.png" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a></span> inside it!</figcaption></figure>
 !! end
 
 !! test
@@ -12678,7 +12738,7 @@ Image: caption containing a newline
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="This *is some text"><img alt="This *is some text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"This\n*is some text"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"This\n*is some text"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !!end
 
 !!test
@@ -12690,7 +12750,7 @@ Image: caption containing leading space
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>bar</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> bar</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption> bar</figcaption></figure>
 !!end
 
 !! test
@@ -12709,7 +12769,7 @@ and some more text.]]
 <div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
 <table>
 <tbody>
 <tr><th>Foo </th><th>Bar</th></tr>
@@ -12726,7 +12786,7 @@ Bug 3090: External links other than http: in image captions
 <div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This caption has <a rel="nofollow" class="external text" href="irc://example.net">irc</a> and <a rel="nofollow" class="external text" href="https://example.com">Secure</a> ext links in it.</div></div></div>
 
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
 !! end
 
 !! test
@@ -12739,7 +12799,7 @@ parsoid=wt2html,wt2wt,html2html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="a"><img alt="a" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="b" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size b" typeof="mw:Image" data-mw='{"caption":"a"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size b" typeof="mw:Image" data-mw='{"caption":"a"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12753,7 +12813,7 @@ language=es
 <div class="floatleft"><a href="/wiki/Foo" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12768,7 +12828,7 @@ language=es
 <div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/Foo" title="Foo"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/Archivo:Foobar.jpg" class="internal" title="Aumentar"></a></div>caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12782,7 +12842,7 @@ parsoid=wt2html,wt2wt,html2html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="extra thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size mw-image-border extra" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size mw-image-border extra" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
 !! end
 
 # Note that 'right' is the default alignment, despite the misspelled 'righ' below
@@ -12803,9 +12863,9 @@ parsoid=wt2html,wt2wt,html2html
 <div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! article
@@ -12835,7 +12895,7 @@ wgEnableUploads=0
 <p><a href="/wiki/File:Foobaz.jpg" title="File:Foobaz.jpg">File:Foobaz.jpg</a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:Foobaz.jpg"><img resource="./File:Foobaz.jpg" src="./Special:FilePath/Foobaz.jpg" height="220" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Foobaz.jpg"><img resource="./File:Foobaz.jpg" src="./Special:FilePath/Foobaz.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 # Parsoid-specific testing for images
@@ -12850,7 +12910,7 @@ Parsoid-specific image handling - simple image with size and middle alignment
 !! wikitext
 [[File:Foobar.jpg|middle|50px]]
 !! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50"></a></span></p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
 !! end
 
 !! test
@@ -12861,7 +12921,7 @@ parsoid=wt2wt,wt2html,html2html
 !! wikitext
 [[Image:Foobar.jpg|middle|50px]]
 !! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50"></a></span></p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
 !! end
 
 !! test
@@ -12870,7 +12930,7 @@ Parsoid-specific image handling - simple image with size and middle alignment
 !! wikitext
 [[File:Foobar.jpg|50px|middle]]
 !! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
@@ -12881,7 +12941,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[Image:Foobar.jpg|50px|middle]]
 !! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50"></a></span></p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
 !! end
 
 !! test
@@ -12889,7 +12949,7 @@ Parsoid-specific image handling - simple image with both sizes, a baseline align
 !! wikitext
 [[File:Foobar.jpg|500x10px|baseline|caption]]
 !! html/parsoid
-<p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
@@ -12897,7 +12957,7 @@ Parsoid-specific image handling - simple image with border and size spec
 !! wikitext
 [[File:Foobar.jpg|50px|border|caption]]
 !! html/parsoid
-<p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
@@ -12905,7 +12965,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption
 !! wikitext
 [[File:Foobar.jpg|left|baseline|thumb|caption content]]
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" /></a><figcaption>caption content</figcaption></figure>
+<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption content</figcaption></figure>
 !! end
 
 !! test
@@ -12914,7 +12974,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption
 !! wikitext
 [[File:Foobar.jpg|thumb|left|baseline|caption content]]
 !! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
+<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
 !! end
 
 !! test
@@ -12922,7 +12982,7 @@ Parsoid-specific image handling - thumbnail with specific size, halign, valign,
 !! wikitext
 [[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]]
 !! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" /></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12931,7 +12991,7 @@ valign, and caption (existing content)
 !! wikitext
 [[File:Foobar.jpg|thumb|50x50px|right|middle|caption]]
 !! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12942,7 +13002,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|frame|500x50px|caption]]
 !! html/parsoid
-<figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941" /></a><figcaption>caption</figcaption></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12953,7 +13013,7 @@ parsoid=wt2html,wt2wt,html2html
 !! wikitext
 [[File:Foobar.jpg|left|baseline|frame|500x50px|caption]]
 !! html/parsoid
-<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941" /></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -12961,7 +13021,7 @@ Parsoid-specific image handling - frameless image with specific size, border, an
 !! wikitext
 [[File:Foobar.jpg|frameless|442x50px|border|caption]]
 !! html/parsoid
-<p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
@@ -12969,7 +13029,7 @@ Parsoid-specific image handling - simple image with a formatted caption
 !! wikitext
 [[File:Foobar.jpg|<table><tr><td>a</td><td>b</td></tr><tr><td>c</td></tr></table>]]
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
@@ -12977,7 +13037,7 @@ Parsoid-specific image handling - caption with a template in it
 !! wikitext
 [[File:Foobar.jpg|thumb|200x23px|This caption has a {{echo|transclusion}} in it.]]
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
 !! end
 
 !! test
@@ -12990,7 +13050,7 @@ foo
 bar
 !! html/parsoid
 <p>foo</p>
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
 <p>bar</p>
 !! end
 
@@ -13001,7 +13061,7 @@ parsoid=wt2html,wt2wt
 !! wikitext
 [[File:Foobar.jpg|thumb|]]
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption></figcaption></figure>
 !! end
 
 # empty captions don't get serialized unless we're in the "round trip" case
@@ -13011,9 +13071,10 @@ Parsoid-specific image handling - empty caption (2)
 parsoid=html2wt
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb">
-  <a href="File:Foobar.jpg">
+  <a href="./File:Foobar.jpg">
     <img resource="./File:Foobar.jpg"
          src="//example.com/images/3/3a/Foobar.jpg"
+         data-file-width="1941" data-file-height="220" data-file-type="bitmap"
          height="25" width="220"/>
   </a>
   <figcaption></figcaption>
@@ -13027,7 +13088,7 @@ Parsoid-specific image handling - whitespace caption
 !! wikitext
 [[File:Foobar.jpg|thumb| ]]
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> </figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption> </figcaption></figure>
 !! end
 
 !! test
@@ -13038,7 +13099,7 @@ foo
 bar
 !! html/parsoid
 <p>foo
-<span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="180" width="240"/></a></span>
+<span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" data-file-width="240" data-file-height="180" data-file-type="drawing" height="180" width="240"/></a></span>
 bar</p>
 !! end
 
@@ -13410,8 +13471,8 @@ parsoid
 [[:File:Foo.png|Bar]]
 !! html
 <p>
-<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">File:Foo.png</a>
-<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">Bar</a>
+<a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">File:Foo.png</a>
+<a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">Bar</a>
 </p>
 !! end
 
@@ -13849,7 +13910,7 @@ http://example.com [[File:Foobar.jpg]]
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a> <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a> <span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a> <span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !!end
 
 !! test
@@ -13901,7 +13962,7 @@ section 5
 </ul>
 </div>
 
-<h2><span class="mw-headline" id="text_.3E_text">text &gt; text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: text > text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="text_.3E_text">text &gt; text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: text &gt; text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <p>section 1
 </p>
 <h2><span class="mw-headline" id="text_.3C_text">text &lt; text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: text &lt; text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -14077,7 +14138,7 @@ http://example.com[[File:Foobar.jpg]]
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !!end
 
 !! test
@@ -14472,7 +14533,7 @@ Image link to nonexistent file (bug 1850 - good)
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class="new" title="File:No such.jpg">File:No such.jpg</a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:No_such.jpg"><img resource="./File:No_such.jpg" src="./Special:FilePath/No_such.jpg" height="220" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:No_such.jpg"><img resource="./File:No_such.jpg" src="./Special:FilePath/No_such.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 !! test
@@ -17452,7 +17513,7 @@ djvu
 <p><a href="/index.php?title=File:LoremIpsum.djvu&amp;page=2" class="image"><img alt="LoremIpsum.djvu" src="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-2480px-LoremIpsum.djvu.jpg" width="2480" height="3508" srcset="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-3720px-LoremIpsum.djvu.jpg 1.5x, http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-4960px-LoremIpsum.djvu.jpg 2x" /></a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"page","ak":"page=2"}]}'><a href="./File:LoremIpsum.djvu" data-parsoid='{"a":{"href":"./File:LoremIpsum.djvu"},"sa":{}}'><img resource="./File:LoremIpsum.djvu" src="//example.com/images/5/5f/LoremIpsum.djvu" height="3508" width="2480" data-parsoid='{"a":{"resource":"./File:LoremIpsum.djvu","height":"3508","width":"2480"},"sa":{"resource":"File:LoremIpsum.djvu"}}'/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"page","ak":"page=2"}]}'><a href="./File:LoremIpsum.djvu" data-parsoid='{"a":{"href":"./File:LoremIpsum.djvu"},"sa":{}}'><img resource="./File:LoremIpsum.djvu" src="//example.com/images/5/5f/LoremIpsum.djvu" data-file-width="2480" data-file-height="3508" data-file-type="bitmap" height="3508" width="2480" data-parsoid='{"a":{"resource":"./File:LoremIpsum.djvu","height":"3508","width":"2480"},"sa":{"resource":"File:LoremIpsum.djvu"}}'/></a></span></p>
 !! end
 
 !! test
@@ -17487,7 +17548,7 @@ Images with the "|" character in the comment
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&amp;param2=%7Cx">external</a> URL</div></div></div>
 
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>An <a rel="mw:ExtLink" href="http://test/?param1=|left|&amp;param2=|x">external</a> URL</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>An <a rel="mw:ExtLink" href="http://test/?param1=|left|&amp;param2=|x">external</a> URL</figcaption></figure>
 !! end
 
 !! test
@@ -18993,7 +19054,7 @@ Bad images - basic functionality
 [[File:Bad.jpg]]
 !! DISABLED/html/php
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="./File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 !! test
@@ -19008,7 +19069,7 @@ Bar foo
 </p>
 !! html/parsoid
 <p>Foo bar
-<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="./File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span>
 Bar foo</p>
 !! end
 
@@ -19307,7 +19368,7 @@ percent-encoding and + signs in internal links (Bug 26410)
 <a href="/index.php?title=3E&amp;action=edit&amp;redlink=1" class="new" title="3E (page does not exist)">3E</a> <a href="/index.php?title=3E%2B&amp;action=edit&amp;redlink=1" class="new" title="3E+ (page does not exist)">3E+</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="User:+%" title="User:+%">User:+%</a> <a rel="mw:WikiLink" href="Page+title%" title="Page+title%">Page+title%</a> <a rel="mw:WikiLink" href="%+" title="%+">%+</a> <a rel="mw:WikiLink" href="%+" title="%+">%20</a> <a rel="mw:WikiLink" href="%+" title="%+">%+ </a> <a rel="mw:WikiLink" href="%+r" title="%+r">%+r</a> <a rel="mw:WikiLink" href="%" title="%">%</a> <a rel="mw:WikiLink" href="+" title="+">+</a> <span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"[[bar]]"}'><a href="File:%+abc9"><img resource="./File:%25+abc9" src="./Special:FilePath/%+abc9" height="220" width="220"/></a></span> <a rel="mw:WikiLink" href="3E" title="3E">3E</a> <a rel="mw:WikiLink" href="3E+" title="3E+">3E+</a></p>
+<p><a rel="mw:WikiLink" href="User:+%" title="User:+%">User:+%</a> <a rel="mw:WikiLink" href="Page+title%" title="Page+title%">Page+title%</a> <a rel="mw:WikiLink" href="%+" title="%+">%+</a> <a rel="mw:WikiLink" href="%+" title="%+">%20</a> <a rel="mw:WikiLink" href="%+" title="%+">%+ </a> <a rel="mw:WikiLink" href="%+r" title="%+r">%+r</a> <a rel="mw:WikiLink" href="%" title="%">%</a> <a rel="mw:WikiLink" href="+" title="+">+</a> <span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"[[bar]]"}'><a href="./File:%+abc9"><img resource="./File:%25+abc9" src="./Special:FilePath/%+abc9" height="220" width="220"/></a></span> <a rel="mw:WikiLink" href="3E" title="3E">3E</a> <a rel="mw:WikiLink" href="3E+" title="3E+">3E+</a></p>
 !! end
 
 !! test
@@ -19320,8 +19381,8 @@ Special characters in embedded file links (bug 27679)
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Does_not_exist.jpg" class="new" title="File:Does not exist.jpg">Title with &amp; ampersand</a>
 </p>
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="File:Contains_&amp;_ampersand.jpg"><img resource="./File:Contains_&amp;_ampersand.jpg" src="./Special:FilePath/Contains_&amp;_ampersand.jpg" height="220" width="220"/></a></span>
-<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"Title with &amp; ampersand"}'><a href="File:Does_not_exist.jpg"><img resource="./File:Does_not_exist.jpg" src="./Special:FilePath/Does_not_exist.jpg" height="220" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Contains_&amp;_ampersand.jpg"><img resource="./File:Contains_&amp;_ampersand.jpg" src="./Special:FilePath/Contains_&amp;_ampersand.jpg" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"Title with &amp; ampersand"}'><a href="./File:Does_not_exist.jpg"><img resource="./File:Does_not_exist.jpg" src="./Special:FilePath/Does_not_exist.jpg" height="220" width="220"/></a></span></p>
 !! end
 
 !! test
@@ -19608,7 +19669,7 @@ __TOC__
 </div>
 
 <h2><span class="mw-headline" id="Hello"><sup class="in-h2">Hello</sup></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Hello">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
-<h2><span class="mw-headline" id="b.22.3EEvilbye"><sup> b"&gt;Evilbye</sup></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: b&quot;>Evilbye">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="b.22.3EEvilbye"><sup> b"&gt;Evilbye</sup></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: b&quot;&gt;Evilbye">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
 
@@ -20061,7 +20122,7 @@ parsoid=wt2html,wt2wt
 <table>
 <tbody><tr><td>
 <small>
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Test</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Test</figcaption></figure>
 </small>
 </td></tr>
 </tbody></table>
@@ -20077,9 +20138,9 @@ parsoid=wt2html,wt2wt
 <small>[[Image:Foobar.jpg|right|300px]]</small>
 !! html/parsoid
 <p><b>foo</b></p>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><b>caption</b></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><b>caption</b></figcaption></figure>
 <p><b>bar</b></p>
-<small><figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="34" width="300"/></a></figure></small>
+<small><figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></figure></small>
 !! end
 
 #### ----------------------------------------------------------------
@@ -20642,6 +20703,22 @@ B <ref group="inexistent">bar</ref>
 </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
 !! options
@@ -22107,9 +22184,8 @@ parsoid
 parsoid
 !! wikitext
  [[File:Foobar.jpg|thumb|caption]]
-!! html
 !! html/parsoid
- <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+ <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
@@ -22620,8 +22696,8 @@ Multi-line image caption generated by templates with/without trailing newlines
 [[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
 [[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
 !! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt9" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt10" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt11" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span></figcaption></figure>
-<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt12" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt13" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt14" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span>\n\n</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt9" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt10" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt11" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span></figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt12" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt13" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt14" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span>\n\n</figcaption></figure>
 !!end
 
 !! test
@@ -22631,12 +22707,12 @@ parsoid=html2wt
 !! html
 <meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>foo&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><p>new para</p>
 
-<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid=''/><h1>new heading</h1>
+<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{}'/><h1>new heading</h1>
 !! wikitext
 <includeonly>foo</includeonly>
 new para
 
-[[./Category:Foo]]
+[[Category:Foo]]
 
 = new heading =
 !! end
@@ -22954,6 +23030,19 @@ parsoid=html2wt
 [[Foo]]
 !! end
 
+# See T93839
+!! test
+New wikilinks should be serialized properly
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{}'>Foo</a>
+<a rel="mw:WikiLink" href="./Foo" title="Foo">Foo</a>
+!! wikitext
+[[Foo]]
+[[Foo]]
+!! end
+
 !! test
 New wiki links (href variations)
 !! options
@@ -23161,7 +23250,7 @@ parsoid
 !! wikitext
 [[File:Foobar.jpg|thumb|alt=|bar]]
 !! html
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
 !! end
 
 #!! test
@@ -23170,7 +23259,7 @@ parsoid
 #parsoid=html2wt
 #language=ar
 #!! html
-#<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="180"/></a></figure>
+#<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="20" width="180"/></a></figure>
 #!! wikitext
 #[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]]
 #!! end
@@ -23183,7 +23272,7 @@ Image: Block level image should have \n before and after
 456
 !! html/parsoid
 <p>123</p>
-<figure class="mw-halign-right" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="17" width="150"/></a></figure>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="17" width="150"/></a></figure>
 <p>456</p>
 !!end
 
@@ -23195,7 +23284,7 @@ Image: New block level image should have \n before and after (existing content)
 456
 !! html/parsoid
 <p>123</p>
-<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
 <p>456</p>
 !!end
 
@@ -23208,9 +23297,9 @@ parsoid
 [[File:Foobar.jpg|thumb|upright=0.5|caption]]
 [[File:Foobar.jpg|thumb|500x500px|upright=0.5|caption]]
 !! html
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="12" width="110"/></a><figcaption>caption</figcaption></figure>
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="19" width="170"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="12" width="110"/></a><figcaption>caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
 !!end
 
 !! test
@@ -23220,7 +23309,7 @@ parsoid
 !! wikitext
 [[File:Foobar.jpg|500x500px|upright=0.5|caption]]
 !! html
-<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a></span></p>
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="57" width="500"/></a></span></p>
 !!end
 
 !! test
@@ -23229,7 +23318,7 @@ Image: from basic HTML (1)
 parsoid=html2wt
 !! html/parsoid
 <span typeof="mw:Image">
-  <img src="File:Foobar.jpg" width=100 height=100 alt="Alt">
+  <img src="./File:Foobar.jpg" width=100 height=100 alt="Alt">
 </span>
 !! wikitext
 [[File:Foobar.jpg|link=|alt=Alt|100x100px]]
@@ -23240,7 +23329,7 @@ Image: from basic HTML (2)
 !! options
 parsoid=html2wt
 !! html/parsoid
-<img src="File:Foobar.jpg" width=100 height=100 alt="Alt">
+<img src="./File:Foobar.jpg" width=100 height=100 alt="Alt">
 !! wikitext
 [[File:Foobar.jpg|link=|alt=Alt|100x100px]]
 !! end
@@ -23250,7 +23339,7 @@ Image: from basic HTML (3)
 !! options
 parsoid=html2wt
 !! html/parsoid
-<a href="Main"><img src="File:Foobar.jpg" width=100 height=100 alt="Alt"></a>
+<a href="Main"><img src="./File:Foobar.jpg" width=100 height=100 alt="Alt"></a>
 !! wikitext
 [[File:Foobar.jpg|link=Main|alt=Alt|100x100px]]
 !! end
@@ -23260,7 +23349,7 @@ Image: from basic HTML (4)
 !! options
 parsoid=html2wt
 !! html/parsoid
-<img src="File:Foobar.jpg">
+<img src="./File:Foobar.jpg">
 !! wikitext
 [[File:Foobar.jpg|link=]]
 !! end
@@ -23584,7 +23673,7 @@ parsoid=html2wt
 5a. Merge adjacent quote nodes if they've been edited
 !! options
 parsoid={
-  "modes": ["wt2wt"],
+  "modes": ["wt2wt", "selser"],
   "changes": [
     ["p", "contents", "remove", ":contains('b')"]
   ]
@@ -23599,7 +23688,7 @@ parsoid={
 5b. Merge adjacent quote nodes if they've been edited
 !! options
 parsoid={
-  "modes": ["wt2wt"],
+  "modes": ["wt2wt", "selser"],
   "changes": [
     ["#x", "remove"]
   ]
@@ -23836,11 +23925,111 @@ parsoid=html2wt,wt2wt
 </table>
 !! end
 
+!! test
+HTML id attribute with Parsoid-like element ids should not be serialized to wikitext
+!! options
+parsoid=html2wt
+!! html
+<table id='mwAb'>
+<td id='mwAc'>foo</td>
+<td id='serialize-this'>bar</td>
+</table>
+!! wikitext
+{|
+|foo
+| id="serialize-this" |bar
+|}
+!! end
+
+!! test
+Parsoid-like element ids should not be serialized to wikitext unless shadowed
+!! options
+parsoid=html2wt
+!! html
+<div id="mwAQ" data-parsoid='{"stx":"html","a":{"id":"mwAQ"},"sa":{"id":"hello"}}'>ok</div>
+!! wikitext
+<div id="hello">ok</div>
+!! end
+
+!! test
+WTS change modes
+!! options
+parsoid={
+  "modes": ["wt2wt"],
+  "changes": [
+    [ "#xyz", "before", "<b>before</b> stuff " ],
+    [ "#xyz", "after", " stuff <i>after</i>" ],
+    [ "#xyz", "html", "x <b>y</b> z" ]
+  ]
+}
+!! wikitext
+<span id="xyz">hello</span>
+!! wikitext/edited
+'''before''' stuff <span id="xyz">x '''y''' z</span> stuff ''after''
+!! end
+
+!! test
+Never serialize a-tag as html, regardless of what data-parsoid has to say
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"html"}'>Foo</a>
+!! wikitext
+[[Foo]]
+!! end
+
 # -----------------------------------------------------------------
 # End of section for Parsoid-only html2wt tests for serialization
 # of new content
 # -----------------------------------------------------------------
 
+# -----------------------------------------------------------------
+# The following section of tests are primarily to spec behavior of
+# the selective serializer. All these tests have manual selser
+# changes. The automated selser changes for all tests handle the
+# wide variation of changes, but these tests here capture specs
+# deterministically.
+# ----------------------------------------------------------------
+
+## T90517
+!! test
+1. Selser: New comments should not be lost
+!! options
+parsoid={
+  "modes": ["selser"],
+  "changes": [
+    [ "#a", "after", "<!--c1-->" ],
+    [ "#b", "before", "<!--c2-->" ]
+  ]
+}
+!! wikitext
+<span id="a">a</span>
+
+<span id="b">b</span>
+!! wikitext/edited
+<span id="a">a</span><!--c1-->
+
+<!--c2--><span id="b">b</span>
+!! end
+
+## T89383
+!! test
+2. Selser: Check for validity of DSR before using it
+!! options
+parsoid={
+  "modes": ["selser"],
+  "changes": [
+    [ "#a", "before", "<meta property='mw:PageProp/displaytitle' content='foo'>" ]
+  ]
+}
+!! wikitext
+<span id="a">a</span>
+!! wikitext/edited
+{{DISPLAYTITLE:foo}}
+<span id="a">a</span>
+!! end
+
+
 TODO:
 more images
 more tables
index 0253284..72cac05 100644 (file)
@@ -104,7 +104,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                ObjectCache::$instances[CACHE_DB] = new HashBagOStuff;
 
                $needsResetDB = false;
-               $logName = get_class( $this ) . '::' . $this->getName( false );
 
                if ( $this->needsDB() ) {
                        // set up a DB connection for this test to use
@@ -632,7 +631,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @param string $msg
         */
        private function assertEmpty2( $value, $msg ) {
-               return $this->assertTrue( $value == '', $msg );
+               $this->assertTrue( $value == '', $msg );
        }
 
        private static function unprefixTable( $tableName ) {
@@ -648,7 +647,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * @since 1.18
         *
-        * @param DataBaseBase $db
+        * @param DatabaseBase $db
         *
         * @return array
         */
diff --git a/tests/phpunit/data/xmp/doctype-included.result.php b/tests/phpunit/data/xmp/doctype-included.result.php
new file mode 100644 (file)
index 0000000..9a9cc36
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+$result = array();
diff --git a/tests/phpunit/data/xmp/doctype-included.xmp b/tests/phpunit/data/xmp/doctype-included.xmp
new file mode 100644 (file)
index 0000000..8c94675
--- /dev/null
@@ -0,0 +1,12 @@
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <!DOCTYPE x:xmpmeta [ <!ENTITY lol "lollollollollollollollollollollol"> ]>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core
+ 4.1.3-c001 49.282696, Mon Apr 02 2007 21:16:10        ">
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<rdf:Description
+ rdf:about=""
+ xmlns:exif="http://ns.adobe.com/exif/1.0/"
+ exif:DigitalZoomRatio="0/10">
+<exif:Flash rdf:parseType='Resource'>
+<exif:Fired>True</exif:Fired> <exif:Return>0</exif:Return> <exif:Mode>1</exif:Mode> <exif:Function>False</exif:Function> <exif:RedEyeMode>False</exif:RedEyeMode></exif:Flash> </rdf:Description> </rdf:RDF> </x:xmpmeta>
+
+<?xpacket end="w"?>
diff --git a/tests/phpunit/data/xmp/doctype-not-included.xmp b/tests/phpunit/data/xmp/doctype-not-included.xmp
new file mode 100644 (file)
index 0000000..9a40b4b
--- /dev/null
@@ -0,0 +1,11 @@
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core
+ 4.1.3-c001 49.282696, Mon Apr 02 2007 21:16:10        ">
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<rdf:Description
+ rdf:about=""
+ xmlns:exif="http://ns.adobe.com/exif/1.0/"
+ exif:DigitalZoomRatio="0/10">
+<exif:Flash rdf:parseType='Resource'>
+<exif:Fired>True</exif:Fired> <exif:Return>0</exif:Return> <exif:Mode>1</exif:Mode> <exif:Function>False</exif:Function> <exif:RedEyeMode>False</exif:RedEyeMode></exif:Flash> </rdf:Description> </rdf:RDF> </x:xmpmeta>
+
+<?xpacket end="w"?>
index 4c5424c..99ec2e4 100644 (file)
@@ -16,22 +16,11 @@ class MessageTest extends MediaWikiLangTestCase {
         * @dataProvider provideConstructor
         */
        public function testConstructor( $expectedLang, $key, $params, $language ) {
-               $reflection = new ReflectionClass( 'Message' );
-
-               $keyProperty = $reflection->getProperty( 'key' );
-               $keyProperty->setAccessible( true );
-
-               $paramsProperty = $reflection->getProperty( 'parameters' );
-               $paramsProperty->setAccessible( true );
-
-               $langProperty = $reflection->getProperty( 'language' );
-               $langProperty->setAccessible( true );
-
                $message = new Message( $key, $params, $language );
 
-               $this->assertEquals( $key, $keyProperty->getValue( $message ) );
-               $this->assertEquals( $params, $paramsProperty->getValue( $message ) );
-               $this->assertEquals( $expectedLang, $langProperty->getValue( $message ) );
+               $this->assertEquals( $key, $message->getKey() );
+               $this->assertEquals( $params, $message->getParams() );
+               $this->assertEquals( $expectedLang, $message->getLanguage() );
        }
 
        public static function provideConstructor() {
@@ -45,21 +34,62 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
-       public static function provideTestParams() {
+       public static function provideConstructorParams() {
                return array(
-                       array( array() ),
-                       array( array( 'foo' ), 'foo' ),
-                       array( array( 'foo', 'bar' ), 'foo', 'bar' ),
-                       array( array( 'baz' ), array( 'baz' ) ),
-                       array( array( 'baz', 'foo' ), array( 'baz', 'foo' ) ),
-                       array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), 'hhh' ),
-                       array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), 'hhh', array( 'ahahahahha' ) ),
-                       array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), array( 'ahahahahha' ) ),
-                       array( array( 'baz' ), array( 'baz' ), array( 'ahahahahha' ) ),
+                       array(
+                               array(),
+                               array(),
+                       ),
+                       array(
+                               array( 'foo' ),
+                               array( 'foo' ),
+                       ),
+                       array(
+                               array( 'foo', 'bar' ),
+                               array( 'foo', 'bar' ),
+                       ),
+                       array(
+                               array( 'baz' ),
+                               array( array( 'baz' ) ),
+                       ),
+                       array(
+                               array( 'baz', 'foo' ),
+                               array( array( 'baz', 'foo' ) ),
+                       ),
+                       array(
+                               array( 'baz', 'foo' ),
+                               array( array( 'baz', 'foo' ), 'hhh' ),
+                       ),
+                       array(
+                               array( 'baz', 'foo' ),
+                               array( array( 'baz', 'foo' ), 'hhh', array( 'ahahahahha' ) ),
+                       ),
+                       array(
+                               array( 'baz', 'foo' ),
+                               array( array( 'baz', 'foo' ), array( 'ahahahahha' ) ),
+                       ),
+                       array(
+                               array( 'baz' ),
+                               array( array( 'baz' ), array( 'ahahahahha' ) ),
+                       ),
                );
        }
 
-       public function getLanguageProvider() {
+       /**
+        * @covers Message::__construct
+        * @covers Message::getParams
+        * @dataProvider provideConstructorParams
+        */
+       public function testConstructorParams( $expected, $args ) {
+               $msg = new Message( 'imasomething' );
+
+               $returned = call_user_func_array( array( $msg, 'params' ), $args );
+
+               $this->assertSame( $msg, $returned );
+               $this->assertEquals( $expected, $msg->getParams() );
+       }
+
+       public static function provideConstructorLanguage() {
                return array(
                        array( 'foo', array( 'bar' ), 'en' ),
                        array( 'foo', array( 'bar' ), 'de' )
@@ -67,27 +97,98 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
+        * @covers Message::__construct
         * @covers Message::getLanguage
-        * @dataProvider getLanguageProvider
+        * @dataProvider provideConstructorLanguage
         */
-       public function testGetLanguageCode( $key, $params, $languageCode ) {
+       public function testConstructorLanguage( $key, $params, $languageCode ) {
                $language = Language::factory( $languageCode );
                $message = new Message( $key, $params, $language );
 
                $this->assertEquals( $language, $message->getLanguage() );
        }
 
+       public static function provideKeys() {
+               return array(
+                       'string' => array(
+                               'key' => 'mainpage',
+                               'expected' => array( 'mainpage' ),
+                       ),
+                       'single' => array(
+                               'key' => array( 'mainpage' ),
+                               'expected' => array( 'mainpage' ),
+                       ),
+                       'multi' => array(
+                               'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+                               'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+                       ),
+                       'empty' => array(
+                               'key' => array(),
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+                       'null' => array(
+                               'key' => null,
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+                       'bad type' => array(
+                               'key' => 123,
+                               'expected' => null,
+                               'exception' => 'InvalidArgumentException',
+                       ),
+               );
+       }
+
        /**
-        * @covers Message::params
-        * @dataProvider provideTestParams
+        * @covers Message::__construct
+        * @covers Message::getKey
+        * @covers Message::isMultiKey
+        * @covers Message::getKeysToTry
+        * @dataProvider provideKeys
         */
-       public function testParams( $expected ) {
-               $msg = new Message( 'imasomething' );
+       public function testKeys( $key, $expected, $exception = null ) {
+               if ( $exception ) {
+                       $this->setExpectedException( $exception );
+               }
 
-               $returned = call_user_func_array( array( $msg, 'params' ), array_slice( func_get_args(), 1 ) );
+               $msg = new Message( $key );
+               $this->assertContains( $msg->getKey(), $expected );
+               $this->assertEquals( $expected, $msg->getKeysToTry() );
+               $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
+       }
 
-               $this->assertSame( $msg, $returned );
-               $this->assertEquals( $expected, $msg->getParams() );
+       /**
+        * @covers ::wfMessage
+        */
+       public function testWfMessage() {
+               $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
+               $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
+       }
+
+       /**
+        * @covers Message::newFromKey
+        */
+       public function testNewFromKey() {
+               $this->assertInstanceOf( 'Message', Message::newFromKey( 'mainpage' ) );
+               $this->assertInstanceOf( 'Message', Message::newFromKey( 'i-dont-exist-evar' ) );
+       }
+
+       /**
+        * @covers ::wfMessage
+        * @covers Message::__construct
+        */
+       public function testWfMessageParams() {
+               $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
+               $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
+               $this->assertEquals(
+                       'You have foo (bar).',
+                       wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
+               );
+               $this->assertEquals(
+                       'You have foo (bar).',
+                       wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text()
+               );
        }
 
        /**
@@ -104,10 +205,12 @@ class MessageTest extends MediaWikiLangTestCase {
 
        /**
         * @covers Message::__construct
+        * @covers Message::text
+        * @covers Message::plain
+        * @covers Message::escaped
+        * @covers Message::toString
         */
-       public function testKey() {
-               $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
-               $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
+       public function testToStringKey() {
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->text() );
                $this->assertEquals( '<i-dont-exist-evar>', wfMessage( 'i-dont-exist-evar' )->text() );
                $this->assertEquals( '<i<dont>exist-evar>', wfMessage( 'i<dont>exist-evar' )->text() );
@@ -120,6 +223,26 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
+       public static function provideToString() {
+               return array(
+                       array( 'mainpage', 'Main Page' ),
+                       array( 'i-dont-exist-evar', '<i-dont-exist-evar>' ),
+                       array( 'i-dont-exist-evar', '&lt;i-dont-exist-evar&gt;', 'escaped' ),
+               );
+       }
+
+       /**
+        * @covers Message::toString
+        * @covers Message::__toString
+        * @dataProvider provideToString
+        */
+       public function testToString( $key, $expect, $format = 'plain' ) {
+               $msg = new Message( $key );
+               $msg->$format();
+               $this->assertEquals( $expect, $msg->toString() );
+               $this->assertEquals( $expect, $msg->__toString() );
+       }
+
        /**
         * @covers Message::inLanguage
         */
@@ -138,26 +261,10 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @covers Message::__construct
-        */
-       public function testMessageParams() {
-               $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
-               $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
-               $this->assertEquals(
-                       'You have foo (bar).',
-                       wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
-               );
-               $this->assertEquals(
-                       'You have foo (bar).',
-                       wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text()
-               );
-       }
-
-       /**
-        * @covers Message::__construct
+        * @covers Message::rawParam
         * @covers Message::rawParams
         */
-       public function testMessageParamSubstitution() {
+       public function testRawParams() {
                $this->assertEquals(
                        '(Заглавная страница)',
                        wfMessage( 'parentheses', 'Заглавная страница' )->plain()
@@ -177,10 +284,21 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @covers Message::__construct
+        * @covers RawMessage::__construct
+        * @covers RawMessage::fetchMessage
+        */
+       public function testRawMessage() {
+               $msg = new RawMessage( 'example &' );
+               $this->assertEquals( 'example &', $msg->plain() );
+               $this->assertEquals( 'example &amp;', $msg->escaped() );
+       }
+
+       /**
         * @covers Message::params
+        * @covers Message::toString
+        * @covers Message::replaceParameters
         */
-       public function testDeliciouslyManyParams() {
+       public function testReplaceManyParams() {
                $msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' );
                // One less than above has placeholders
                $params = array( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' );
@@ -189,12 +307,20 @@ class MessageTest extends MediaWikiLangTestCase {
                        $msg->params( $params )->plain(),
                        'Params > 9 are replaced correctly'
                );
+
+               $msg = new RawMessage( 'Params$*' );
+               $params = array( 'ab', 'bc', 'cd' );
+               $this->assertEquals(
+                       'Params: ab, bc, cd',
+                       $msg->params( $params )->text()
+               );
        }
 
        /**
+        * @covers Message::numParam
         * @covers Message::numParams
         */
-       public function testMessageNumParams() {
+       public function testNumParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -206,9 +332,10 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
+        * @covers Message::durationParam
         * @covers Message::durationParams
         */
-       public function testMessageDurationParams() {
+       public function testDurationParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -222,9 +349,10 @@ class MessageTest extends MediaWikiLangTestCase {
        /**
         * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
         * @group Database
+        * @covers Message::expiryParam
         * @covers Message::expiryParams
         */
-       public function testMessageExpiryParams() {
+       public function testExpiryParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -236,9 +364,10 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
+        * @covers Message::timeperiodParam
         * @covers Message::timeperiodParams
         */
-       public function testMessageTimeperiodParams() {
+       public function testTimeperiodParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -250,9 +379,10 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
+        * @covers Message::sizeParam
         * @covers Message::sizeParams
         */
-       public function testMessageSizeParams() {
+       public function testSizeParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -264,9 +394,10 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
+        * @covers Message::bitrateParam
         * @covers Message::bitrateParams
         */
-       public function testMessageBitrateParams() {
+       public function testBitrateParams() {
                $lang = Language::factory( 'en' );
                $msg = new RawMessage( '$1' );
 
@@ -277,7 +408,7 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
-       public function messagePlaintextParamsProvider() {
+       public static function providePlaintextParams() {
                return array(
                        array(
                                'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
@@ -308,10 +439,15 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @dataProvider messagePlaintextParamsProvider
+        * @covers Message::plaintextParam
         * @covers Message::plaintextParams
+        * @covers Message::formatPlaintext
+        * @covers Message::toString
+        * @covers Message::parse
+        * @covers Message::parseAsBlock
+        * @dataProvider providePlaintextParams
         */
-       public function testMessagePlaintextParams( $expect, $format ) {
+       public function testPlaintextParams( $expect, $format ) {
                $lang = Language::factory( 'en' );
 
                $msg = new RawMessage( '$1 $2' );
@@ -326,6 +462,46 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
+       public static function provideParser() {
+               return array(
+                       array(
+                               "''&'' <x><!-- x -->",
+                               'plain',
+                       ),
+
+                       array(
+                               "''&'' <x><!-- x -->",
+                               'text',
+                       ),
+                       array(
+                               '<i>&amp;</i> &lt;x&gt;',
+                               'parse',
+                       ),
+
+                       array(
+                               "<p><i>&amp;</i> &lt;x&gt;\n</p>",
+                               'parseAsBlock',
+                       ),
+               );
+       }
+
+       /**
+        * @covers Message::text
+        * @covers Message::parse
+        * @covers Message::parseAsBlock
+        * @covers Message::toString
+        * @covers Message::transformText
+        * @covers Message::parseText
+        * @dataProvider provideParser
+        */
+       public function testParser( $expect, $format ) {
+               $msg = new RawMessage( "''&'' <x><!-- x -->" );
+               $this->assertEquals(
+                       $expect,
+                       $msg->inLanguage( 'en' )->$format()
+               );
+       }
+
        /**
         * @covers Message::inContentLanguage
         */
@@ -372,52 +548,4 @@ class MessageTest extends MediaWikiLangTestCase {
        public function testInLanguageThrows() {
                wfMessage( 'foo' )->inLanguage( 123 );
        }
-
-       public function keyProvider() {
-               return array(
-                       'string' => array(
-                               'key' => 'mainpage',
-                               'expected' => array( 'mainpage' ),
-                       ),
-                       'single' => array(
-                               'key' => array( 'mainpage' ),
-                               'expected' => array( 'mainpage' ),
-                       ),
-                       'multi' => array(
-                               'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
-                               'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
-                       ),
-                       'empty' => array(
-                               'key' => array(),
-                               'expected' => null,
-                               'exception' => 'InvalidArgumentException',
-                       ),
-                       'null' => array(
-                               'key' => null,
-                               'expected' => null,
-                               'exception' => 'InvalidArgumentException',
-                       ),
-                       'bad type' => array(
-                               'key' => 17,
-                               'expected' => null,
-                               'exception' => 'InvalidArgumentException',
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider keyProvider()
-        *
-        * @covers Message::getKey
-        */
-       public function testGetKey( $key, $expected, $exception = null ) {
-               if ( $exception ) {
-                       $this->setExpectedException( $exception );
-               }
-
-               $msg = new Message( $key );
-               $this->assertEquals( $expected, $msg->getKeysToTry() );
-               $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
-               $this->assertContains( $msg->getKey(), $expected );
-       }
 }
index 2526fcc..ee6a8cf 100644 (file)
@@ -239,6 +239,7 @@ document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\
                $ctx->setLanguage( 'en' );
                $out = new OutputPage( $ctx );
                $rl = $out->getResourceLoader();
+               $rl->setMessageBlobStore( new NullMessageBlobStore() );
                $rl->register( array(
                        'test.foo' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.foo( { a: true } );',
@@ -280,3 +281,26 @@ document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\
                $this->assertEquals( $expectedHtml, $actualHtml );
        }
 }
+
+/**
+ * MessageBlobStore that doesn't do anything
+ */
+class NullMessageBlobStore extends MessageBlobStore {
+       public function get ( ResourceLoader $resourceLoader, $modules, $lang ) {
+               return array();
+       }
+
+       public function insertMessageBlob ( $name, ResourceLoaderModule $module, $lang ) {
+               return false;
+       }
+
+       public function updateModule ( $name, ResourceLoaderModule $module, $lang ) {
+               return;
+       }
+
+       public function updateMessage ( $key ) {
+       }
+       public function clear() {
+       }
+}
+
index 860529e..b74a7ea 100644 (file)
@@ -306,7 +306,10 @@ class UserTest extends MediaWikiTestCase {
         * @covers User::isValidPassword()
         */
        public function testCheckPasswordValidity() {
-               $this->setMwGlobals( 'wgMinimalPasswordLength', 6 );
+               $this->setMwGlobals( array(
+                       'wgMinimalPasswordLength' => 6,
+                       'wgMaximalPasswordLength' => 30,
+               ) );
                $user = User::newFromName( 'Useruser' );
                // Sanity
                $this->assertTrue( $user->isValidPassword( 'Password1234' ) );
@@ -314,10 +317,19 @@ class UserTest extends MediaWikiTestCase {
                // Minimum length
                $this->assertFalse( $user->isValidPassword( 'a' ) );
                $this->assertFalse( $user->checkPasswordValidity( 'a' )->isGood() );
+               $this->assertTrue( $user->checkPasswordValidity( 'a' )->isOK() );
                $this->assertEquals( 'passwordtooshort', $user->getPasswordValidity( 'a' ) );
 
+               // Maximum length
+               $longPass = str_repeat( 'a', 31 );
+               $this->assertFalse( $user->isValidPassword( $longPass ) );
+               $this->assertFalse( $user->checkPasswordValidity( $longPass )->isGood() );
+               $this->assertFalse( $user->checkPasswordValidity( $longPass )->isOK() );
+               $this->assertEquals( 'passwordtoolong', $user->getPasswordValidity( $longPass ) );
+
                // Matches username
                $this->assertFalse( $user->checkPasswordValidity( 'Useruser' )->isGood() );
+               $this->assertTrue( $user->checkPasswordValidity( 'Useruser' )->isOK() );
                $this->assertEquals( 'password-name-match', $user->getPasswordValidity( 'Useruser' ) );
 
                // On the forbidden list
@@ -385,4 +397,32 @@ class UserTest extends MediaWikiTestCase {
                $sixth = User::newFromName( 'EqualUnitTestUser' );
                $this->assertTrue( $fifth->equals( $sixth ) );
        }
+
+       /**
+        * @covers User::getId
+        */
+       public function testGetId() {
+               $user = User::newFromName( 'UTSysop' );
+               $this->assertTrue( $user->getId() > 0 );
+
+       }
+
+       /**
+        * @covers User::isLoggedIn
+        * @covers User::isAnon
+        */
+       public function testLoggedIn() {
+               $user = User::newFromName( 'UTSysop' );
+               $this->assertTrue( $user->isLoggedIn() );
+               $this->assertFalse( $user->isAnon() );
+
+               // Non-existent users are perceived as anonymous
+               $user = User::newFromName( 'UTNonexistent' );
+               $this->assertFalse( $user->isLoggedIn() );
+               $this->assertTrue( $user->isAnon() );
+
+               $user = new User;
+               $this->assertFalse( $user->isLoggedIn() );
+               $this->assertTrue( $user->isAnon() );
+       }
 }
index e91edcb..7a03f7d 100644 (file)
@@ -2,7 +2,6 @@
 
 /**
  * @group API
- * @group Database
  * @group medium
  *
  * @covers ApiMain
@@ -23,20 +22,12 @@ class ApiMainTest extends ApiTestCase {
        }
 
        public static function provideAssert() {
-               $anon = new User();
-               $bot = new User();
-               $bot->setName( 'Bot' );
-               $bot->addToDatabase();
-               $bot->addGroup( 'bot' );
-               $user = new User();
-               $user->setName( 'User' );
-               $user->addToDatabase();
                return array(
-                       array( $anon, 'user', 'assertuserfailed' ),
-                       array( $user, 'user', false ),
-                       array( $user, 'bot', 'assertbotfailed' ),
-                       array( $bot, 'user', false ),
-                       array( $bot, 'bot', false ),
+                       array( false, array(), 'user', 'assertuserfailed' ),
+                       array( true, array(), 'user', false ),
+                       array( true, array(), 'bot', 'assertbotfailed' ),
+                       array( true, array( 'bot' ), 'user', false ),
+                       array( true, array( 'bot' ), 'bot', false ),
                );
        }
 
@@ -45,11 +36,17 @@ class ApiMainTest extends ApiTestCase {
         *
         * @covers ApiMain::checkAsserts
         * @dataProvider provideAssert
-        * @param User $user
+        * @param bool $registered
+        * @param array $rights
         * @param string $assert
         * @param string|bool $error False if no error expected
         */
-       public function testAssert( $user, $assert, $error ) {
+       public function testAssert( $registered, $rights, $assert, $error ) {
+               $user = new User();
+               if ( $registered ) {
+                       $user->setId( 1 );
+               }
+               $user->mRights = $rights;
                try {
                        $this->doApiRequest( array(
                                'action' => 'query',
index e7b3e77..f0ba934 100644 (file)
@@ -8,6 +8,7 @@
 class XmlTypeCheckTest extends PHPUnit_Framework_TestCase {
        const WELL_FORMED_XML = "<root><child /></root>";
        const MAL_FORMED_XML = "<root><child /></error>";
+       const XML_WITH_PIH = '<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="/w/index.php"?><svg><child /></svg>';
 
        /**
         * @covers XMLTypeCheck::newFromString
@@ -27,4 +28,22 @@ class XmlTypeCheckTest extends PHPUnit_Framework_TestCase {
                $this->assertFalse( $testXML->wellFormed );
        }
 
+       /**
+        * @covers XMLTypeCheck::processingInstructionHandler
+        */
+       public function testProcessingInstructionHandler() {
+               $called = false;
+               $testXML = new XmlTypeCheck(
+                       self::XML_WITH_PIH,
+                       null,
+                       false,
+                       array(
+                               'processing_instruction_handler' => function() use ( &$called ) {
+                                       $called = true;
+                               }
+                       )
+               );
+               $this->assertTrue( $called );
+       }
+
 }
index 798e492..6758e94 100644 (file)
@@ -62,6 +62,8 @@ class XMPTest extends MediaWikiTestCase {
                        array( 'gps', 'Handling of exif GPS parameters in XMP' ),
                );
 
+               $xmpFiles[] = array( 'doctype-included', 'XMP includes doctype' );
+
                foreach ( $xmpFiles as $file ) {
                        $xmp = file_get_contents( $xmpPath . $file[0] . '.xmp' );
                        // I'm not sure if this is the best way to handle getting the
@@ -170,4 +172,52 @@ class XMPTest extends MediaWikiTestCase {
 
                $this->assertEquals( $expected, $actual );
        }
+
+       /**
+        * Test for multi-section, hostile XML
+        * @covers checkParseSafety
+        */
+       public function testCheckParseSafety() {
+
+               // Test for detection
+               $xmpPath = __DIR__ . '/../../data/xmp/';
+               $file = fopen( $xmpPath . 'doctype-included.xmp', 'rb' );
+               $valid = false;
+               $reader = new XMPReader();
+               do {
+                       $chunk = fread( $file, 10 );
+                       $valid = $reader->parse( $chunk, feof( $file ) );
+               } while ( !feof( $file ) );
+               $this->assertFalse( $valid, 'Check that doctype is detected in fragmented XML' );
+               $this->assertEquals(
+                       array(),
+                       $reader->getResults(),
+                       'Check that doctype is detected in fragmented XML'
+               );
+               fclose( $file );
+               unset( $reader );
+
+               // Test for false positives
+               $file = fopen( $xmpPath . 'doctype-not-included.xmp', 'rb' );
+               $valid = false;
+               $reader = new XMPReader();
+               do {
+                       $chunk = fread( $file, 10 );
+                       $valid = $reader->parse( $chunk, feof( $file ) );
+               } while ( !feof( $file ) );
+               $this->assertTrue(
+                       $valid,
+                       'Check for false-positive detecting doctype in fragmented XML'
+               );
+               $this->assertEquals(
+                       array(
+                               'xmp-exif' => array(
+                                       'DigitalZoomRatio' => '0/10',
+                                       'Flash' => '9'
+                               )
+                       ),
+                       $reader->getResults(),
+                       'Check that doctype is detected in fragmented XML'
+               );
+       }
 }
index 63ad8c0..9441b77 100644 (file)
@@ -162,6 +162,12 @@ class UploadBaseTest extends MediaWikiTestCase {
                                true,
                                'SVG with javascript xlink (http://html5sec.org/#87)'
                        ),
+                       array(
+                               '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><use xlink:href="data:application/xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGRlZnM+CjxjaXJjbGUgaWQ9InRlc3QiIHI9IjUwIiBjeD0iMTAwIiBjeT0iMTAwIiBzdHlsZT0iZmlsbDogI0YwMCI+CjxzZXQgYXR0cmlidXRlTmFtZT0iZmlsbCIgYXR0cmlidXRlVHlwZT0iQ1NTIiBvbmJlZ2luPSdhbGVydChkb2N1bWVudC5jb29raWUpJwpvbmVuZD0nYWxlcnQoIm9uZW5kIiknIHRvPSIjMDBGIiBiZWdpbj0iMXMiIGR1cj0iNXMiIC8+CjwvY2lyY2xlPgo8L2RlZnM+Cjx1c2UgeGxpbms6aHJlZj0iI3Rlc3QiLz4KPC9zdmc+#test"/> </svg>',
+                               true,
+                               true,
+                               'SVG with Opera image xlink (http://html5sec.org/#88 - c)'
+                       ),
                        array(
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <animation xlink:href="javascript:alert(1)"/> </svg>',
                                true,
@@ -273,6 +279,18 @@ class UploadBaseTest extends MediaWikiTestCase {
                                true,
                                'SVG with animate from (http://html5sec.org/#137)'
                        ),
+                       array(
+                               '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a><text y="1em">Click me</text> <animate attributeName="xlink:href" values="javascript:alert(\'Bang!\')" begin="0s" dur="0.1s" fill="freeze" /> </a></svg>',
+                               true,
+                               true,
+                               'SVG with animate xlink:href (http://html5sec.org/#137)'
+                       ),
+                       array(
+                               '<svg xmlns="http://www.w3.org/2000/svg" xmlns:y="http://www.w3.org/1999/xlink"> <a y:href="#"> <text y="1em">Click me</text> <animate attributeName="y:href" values="javascript:alert(\'Bang!\')" begin="0s" dur="0.1s" fill="freeze" /> </a> </svg>',
+                               true,
+                               true,
+                               'SVG with animate y:href (http://html5sec.org/#137)'
+                       ),
 
                        // Other hostile SVG's
                        array(
@@ -305,6 +323,12 @@ class UploadBaseTest extends MediaWikiTestCase {
                                true,
                                'SVG with @import in style element and child element (bug 69008#c11)'
                        ),
+                       array(
+                               '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@imporT "https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org";</style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
+                               true,
+                               true,
+                               'SVG with case-insensitive @import in style element (bug T85349)'
+                       ),
                        array(
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:url(https://www.google.com/images/srpr/logo11w.png)"/> </svg>',
                                true,
@@ -331,6 +355,25 @@ class UploadBaseTest extends MediaWikiTestCase {
                                true,
                                'SVG with remote background image using image() (bug 69008)'
                        ),
+                       array(
+                               // As reported by Cure53
+                               '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a xlink:href="data:text/html;charset=utf-8;base64, PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ%2BDQo%3D"> <circle r="400" fill="red"></circle> </a> </svg>',
+                               true,
+                               true,
+                               'SVG with data:text/html link target (firefox only)'
+                       ),
+                       array(
+                               '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ <!ENTITY lol "lol"> <!ENTITY lol2 "&#x3C;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x45;&#x44;&#x20;&#x3D;&#x3E;&#x20;&#x27;&#x2B;&#x64;&#x6F;&#x63;&#x75;&#x6D;&#x65;&#x6E;&#x74;&#x2E;&#x64;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x29;&#x3B;&#x3C;&#x2F;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;"> ]> <svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" viewBox="-34 -34 68 68" version="1.1"> <circle cx="0" cy="0" r="24" fill="#c8c8c8"/> <text x="0" y="0" fill="black">&lol2;</text> </svg>',
+                               true,
+                               true,
+                               'SVG with encoded script tag in internal entity (reported by Beyond Security)'
+                       ),
+                       array(
+                               '<?xml version="1.0"?> <!DOCTYPE svg [ <!ENTITY foo SYSTEM "file:///etc/passwd"> ]> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <desc>&foo;</desc> <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,2)" /> </svg>',
+                               false,
+                               false,
+                               'SVG with external entity'
+                       ),
 
                        // Test good, but strange files that we want to allow
                        array(
@@ -345,7 +388,6 @@ class UploadBaseTest extends MediaWikiTestCase {
                                false,
                                'SVG with local urls, including filter: in style'
                        ),
-
                );
        }
 }
index 2c56eea..97a3ae1 100644 (file)
@@ -6,17 +6,40 @@
 
        var text, ipv4,
                simpleMDYDatesInMDY, simpleMDYDatesInDMY, oldMDYDates, complexMDYDates, clobberedDates, MYDates, YDates,
-               currencyData, transformedCurrencyData,
-               config = {
+               currencyData, transformedCurrencyData;
+
+       QUnit.module( 'jquery.tablesorter.parsers', QUnit.newMwEnvironment( {
+               setup: function () {
+                       this.liveMonths = mw.language.months;
+                       mw.language.months = {
+                               'keys': {
+                                       'names': ['january', 'february', 'march', 'april', 'may_long', 'june',
+                                               'july', 'august', 'september', 'october', 'november', 'december'],
+                                       'genitive': ['january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
+                                               'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen'],
+                                       'abbrev': ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
+                                               'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+                               },
+                               'names': ['January', 'February', 'March', 'April', 'May', 'June',
+                                               'July', 'August', 'September', 'October', 'November', 'December'],
+                               'genitive': ['January', 'February', 'March', 'April', 'May', 'June',
+                                               'July', 'August', 'September', 'October', 'November', 'December'],
+                               'abbrev': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+                       };
+               },
+               teardown: function () {
+                       mw.language.months = this.liveMonths;
+               },
+               config: {
                        wgContentLanguage: 'en',
                        /* default date format of the content language */
                        wgDefaultDateFormat: 'dmy',
                        /* These two are important for numeric interpretations */
                        wgSeparatorTransformTable: ['', ''],
                        wgDigitTransformTable: ['', '']
-               };
-
-       QUnit.module( 'jquery.tablesorter.parsers', QUnit.newMwEnvironment( { config: config } ) );
+               }
+       } ) );
 
        /**
         * For a value, check if the parser recognizes it and how it transforms it
index f7700f8..f63aa27 100644 (file)
                ];
 
        QUnit.module( 'jquery.tablesorter', QUnit.newMwEnvironment( {
+               setup: function () {
+                       this.liveMonths = mw.language.months;
+                       mw.language.months = {
+                               'keys': {
+                                       'names': ['january', 'february', 'march', 'april', 'may_long', 'june',
+                                               'july', 'august', 'september', 'october', 'november', 'december'],
+                                       'genitive': ['january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
+                                               'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen'],
+                                       'abbrev': ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
+                                               'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+                               },
+                               'names': ['January', 'February', 'March', 'April', 'May', 'June',
+                                               'July', 'August', 'September', 'October', 'November', 'December'],
+                               'genitive': ['January', 'February', 'March', 'April', 'May', 'June',
+                                               'July', 'August', 'September', 'October', 'November', 'December'],
+                               'abbrev': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+                       };
+               },
+               teardown: function () {
+                       mw.language.months = this.liveMonths;
+               },
                config: {
-                       wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
-                       wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                        wgDefaultDateFormat: 'dmy',
                        wgSeparatorTransformTable: ['', ''],
                        wgDigitTransformTable: ['', ''],
index d9df650..670914e 100644 (file)
@@ -8,6 +8,12 @@
                },
                teardown: function () {
                        mw.language.data.values = this.liveLangData;
+               },
+               messages: {
+                       // mw.language.listToText test
+                       'and': ' and',
+                       'comma-separator': ', ',
+                       'word-separator': ' '
                }
        } ) );
 
        } );
 
        QUnit.test( 'mw.language.commafy test', 9, function ( assert ) {
+               mw.language.setData( 'en', 'digitGroupingPattern', null );
+               mw.language.setData( 'en', 'digitTransformTable', null );
+               mw.language.setData( 'en', 'separatorTransformTable', null );
+
+               mw.config.set( 'wgUserLanguage', 'en' );
                // Number grouping patterns are as per http://cldr.unicode.org/translation/number-patterns
                assert.equal( mw.language.commafy( 1234.567, '###0.#####' ), '1234.567', 'Pattern with no digit grouping separator defined' );
                assert.equal( mw.language.commafy( 123456789.567, '###0.#####' ), '123456789.567', 'Pattern with no digit grouping separator defined, bigger decimal part' );