Merge "Reinstate small category refresh logic in LinksDeletionUpdate"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 24 Apr 2019 15:33:54 +0000 (15:33 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 24 Apr 2019 15:33:54 +0000 (15:33 +0000)
17 files changed:
.phpcs.xml
autoload.php
includes/DefaultSettings.php
includes/EditPage.php
includes/StubObject.php
includes/api/ApiBase.php
includes/api/ApiErrorFormatter.php
includes/api/ApiErrorFormatter_BackCompat.php [new file with mode: 0644]
includes/specials/SpecialActiveUsers.php
includes/specials/SpecialListUsers.php
includes/specials/pagers/ActiveUsersPager.php
includes/specials/pagers/UsersPager.php
resources/Resources.php
resources/src/mediawiki.action/mediawiki.action.view.metadata.js
resources/src/mediawiki.page.gallery.slideshow.js
resources/src/mediawiki.page.gallery.styles/gallery.css [deleted file]
resources/src/mediawiki.page.gallery.styles/gallery.less [new file with mode: 0644]

index fef07e6..b60a3af 100644 (file)
                        Whitelist existing violations, but enable the sniff to prevent
                        any new occurrences.
                -->
-               <exclude-pattern>*/includes/api/ApiErrorFormatter\.php</exclude-pattern>
                <exclude-pattern>*/includes/parser/Preprocessor_DOM\.php</exclude-pattern>
                <exclude-pattern>*/includes/parser/Preprocessor_Hash\.php</exclude-pattern>
                <exclude-pattern>*/includes/parser/Preprocessor\.php</exclude-pattern>
index 4f41c8a..35137ab 100644 (file)
@@ -39,7 +39,7 @@ $wgAutoloadLocalClasses = [
        'ApiEditPage' => __DIR__ . '/includes/api/ApiEditPage.php',
        'ApiEmailUser' => __DIR__ . '/includes/api/ApiEmailUser.php',
        'ApiErrorFormatter' => __DIR__ . '/includes/api/ApiErrorFormatter.php',
-       'ApiErrorFormatter_BackCompat' => __DIR__ . '/includes/api/ApiErrorFormatter.php',
+       'ApiErrorFormatter_BackCompat' => __DIR__ . '/includes/api/ApiErrorFormatter_BackCompat.php',
        'ApiExpandTemplates' => __DIR__ . '/includes/api/ApiExpandTemplates.php',
        'ApiFeedContributions' => __DIR__ . '/includes/api/ApiFeedContributions.php',
        'ApiFeedRecentChanges' => __DIR__ . '/includes/api/ApiFeedRecentChanges.php',
index 8b51c59..1c76121 100644 (file)
@@ -8996,16 +8996,6 @@ $wgActorTableSchemaMigrationStage = SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_REA
  */
 $wgEnablePartialBlocks = false;
 
-/**
- * Enable stats monitoring when Block Notices are displayed in different places around core
- * and extensions.
- *
- * @since 1.34
- * @deprecated 1.34
- * @var bool
- */
-$wgEnableBlockNoticeStats = false;
-
 /**
  * Origin Trials tokens.
  *
index 6990934..1d9ff05 100644 (file)
@@ -637,13 +637,6 @@ class EditPage {
                                                $this->context->getUser()->spreadAnyEditBlock();
                                        } );
                                }
-
-                               $config = $this->context->getConfig();
-                               if ( $config->get( 'EnableBlockNoticeStats' ) ) {
-                                       $wiki = $config->get( 'DBname' );
-                                       $statsd = MediaWikiServices::getInstance()->getStatsdDataFactory();
-                                       $statsd->increment( 'BlockNotices.' . $wiki . '.WikitextEditor.shown' );
-                               }
                        }
                        $this->displayPermissionsError( $permErrors );
 
index 1583dbf..2052c44 100644 (file)
@@ -79,7 +79,7 @@ class StubObject {
         * @return bool True if $obj is not an instance of StubObject class.
         */
        public static function isRealObject( $obj ) {
-               return is_object( $obj ) && !$obj instanceof StubObject;
+               return is_object( $obj ) && !$obj instanceof self;
        }
 
        /**
@@ -91,7 +91,7 @@ class StubObject {
         * @return void
         */
        public static function unstub( &$obj ) {
-               if ( $obj instanceof StubObject ) {
+               if ( $obj instanceof self ) {
                        $obj = $obj->_unstub( 'unstub', 3 );
                }
        }
@@ -153,7 +153,7 @@ class StubObject {
        public function _unstub( $name = '_unstub', $level = 2 ) {
                static $recursionLevel = 0;
 
-               if ( !$GLOBALS[$this->global] instanceof StubObject ) {
+               if ( !$GLOBALS[$this->global] instanceof self ) {
                        return $GLOBALS[$this->global]; // already unstubbed.
                }
 
index 528ced8..8ab92af 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 use Wikimedia\Rdbms\IDatabase;
-use MediaWiki\MediaWikiServices;
 
 /**
  * This abstract class implements many basic API functions, and is the base of
@@ -2138,11 +2137,6 @@ abstract class ApiBase extends ContextSource {
                }
 
                if ( $errors ) {
-                       // track block notices
-                       if ( $this->getConfig()->get( 'EnableBlockNoticeStats' ) ) {
-                               $this->trackBlockNotices( $errors );
-                       }
-
                        if ( !empty( $options['autoblock'] ) ) {
                                $user->spreadAnyEditBlock();
                        }
@@ -2151,30 +2145,6 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
-       /**
-        * Keep track of errors messages resulting from a block
-        *
-        * @param array $errors
-        */
-       private function trackBlockNotices( array $errors ) {
-               $errorMessageKeys = [
-                       'blockedtext',
-                       'blockedtext-partial',
-                       'autoblockedtext',
-                       'systemblockedtext',
-               ];
-
-               $statsd = MediaWikiServices::getInstance()->getStatsdDataFactory();
-
-               foreach ( $errors as $error ) {
-                       if ( in_array( $error[0], $errorMessageKeys ) ) {
-                               $wiki = $this->getConfig()->get( 'DBname' );
-                               $statsd->increment( 'BlockNotices.' . $wiki . '.MediaWikiApi.returned' );
-                               break;
-                       }
-               }
-       }
-
        /**
         * Will only set a warning instead of failing if the global $wgDebugAPI
         * is set to true. Otherwise behaves exactly as self::dieWithError().
index 9669464..8049cd8 100644 (file)
@@ -388,111 +388,3 @@ class ApiErrorFormatter {
                }
        }
 }
-
-/**
- * Format errors and warnings in the old style, for backwards compatibility.
- * @since 1.25
- * @deprecated Only for backwards compatibility, do not use
- * @ingroup API
- */
-// phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
-class ApiErrorFormatter_BackCompat extends ApiErrorFormatter {
-
-       /**
-        * @param ApiResult $result Into which data will be added
-        */
-       public function __construct( ApiResult $result ) {
-               parent::__construct( $result, Language::factory( 'en' ), 'none', false );
-       }
-
-       public function getFormat() {
-               return 'bc';
-       }
-
-       public function arrayFromStatus( StatusValue $status, $type = 'error', $format = null ) {
-               if ( $status->isGood() || !$status->getErrors() ) {
-                       return [];
-               }
-
-               $result = [];
-               foreach ( $status->getErrorsByType( $type ) as $error ) {
-                       $msg = ApiMessage::create( $error );
-                       $error = [
-                               'message' => $msg->getKey(),
-                               'params' => $msg->getParams(),
-                               'code' => $msg->getApiCode(),
-                       ] + $error;
-                       ApiResult::setIndexedTagName( $error['params'], 'param' );
-                       $result[] = $error;
-               }
-               ApiResult::setIndexedTagName( $result, $type );
-
-               return $result;
-       }
-
-       protected function formatMessageInternal( $msg, $format ) {
-               return [
-                       'code' => $msg->getApiCode(),
-                       'info' => $msg->text(),
-               ] + $msg->getApiData();
-       }
-
-       /**
-        * Format an exception as an array
-        * @since 1.29
-        * @param Exception|Throwable $exception
-        * @param array $options See parent::formatException(), plus
-        *  - bc: (bool) Return only the string, not an array
-        * @return array|string
-        */
-       public function formatException( $exception, array $options = [] ) {
-               $ret = parent::formatException( $exception, $options );
-               return empty( $options['bc'] ) ? $ret : $ret['info'];
-       }
-
-       protected function addWarningOrError( $tag, $modulePath, $msg ) {
-               $value = self::stripMarkup( $msg->text() );
-
-               if ( $tag === 'error' ) {
-                       // In BC mode, only one error
-                       $existingError = $this->result->getResultData( [ 'error' ] );
-                       if ( !is_array( $existingError ) ||
-                               !isset( $existingError['code'] ) || !isset( $existingError['info'] )
-                       ) {
-                               $value = [
-                                       'code' => $msg->getApiCode(),
-                                       'info' => $value,
-                               ] + $msg->getApiData();
-                               $this->result->addValue( null, 'error', $value,
-                                       ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
-                       }
-               } else {
-                       if ( $modulePath === null ) {
-                               $moduleName = 'unknown';
-                       } else {
-                               $i = strrpos( $modulePath, '+' );
-                               $moduleName = $i === false ? $modulePath : substr( $modulePath, $i + 1 );
-                       }
-
-                       // Don't add duplicate warnings
-                       $tag .= 's';
-                       $path = [ $tag, $moduleName ];
-                       $oldWarning = $this->result->getResultData( [ $tag, $moduleName, $tag ] );
-                       if ( $oldWarning !== null ) {
-                               $warnPos = strpos( $oldWarning, $value );
-                               // If $value was found in $oldWarning, check if it starts at 0 or after "\n"
-                               if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
-                                       // Check if $value is followed by "\n" or the end of the $oldWarning
-                                       $warnPos += strlen( $value );
-                                       if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
-                                               return;
-                                       }
-                               }
-                               // If there is a warning already, append it to the existing one
-                               $value = "$oldWarning\n$value";
-                       }
-                       $this->result->addContentValue( $path, $tag, $value,
-                               ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
-               }
-       }
-}
diff --git a/includes/api/ApiErrorFormatter_BackCompat.php b/includes/api/ApiErrorFormatter_BackCompat.php
new file mode 100644 (file)
index 0000000..6aee4cb
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+/**
+ * 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
+ */
+
+/**
+ * Format errors and warnings in the old style, for backwards compatibility.
+ * @since 1.25
+ * @deprecated Only for backwards compatibility, do not use
+ * @ingroup API
+ */
+// phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
+class ApiErrorFormatter_BackCompat extends ApiErrorFormatter {
+
+       /**
+        * @param ApiResult $result Into which data will be added
+        */
+       public function __construct( ApiResult $result ) {
+               parent::__construct( $result, Language::factory( 'en' ), 'none', false );
+       }
+
+       public function getFormat() {
+               return 'bc';
+       }
+
+       public function arrayFromStatus( StatusValue $status, $type = 'error', $format = null ) {
+               if ( $status->isGood() || !$status->getErrors() ) {
+                       return [];
+               }
+
+               $result = [];
+               foreach ( $status->getErrorsByType( $type ) as $error ) {
+                       $msg = ApiMessage::create( $error );
+                       $error = [
+                               'message' => $msg->getKey(),
+                               'params' => $msg->getParams(),
+                               'code' => $msg->getApiCode(),
+                       ] + $error;
+                       ApiResult::setIndexedTagName( $error['params'], 'param' );
+                       $result[] = $error;
+               }
+               ApiResult::setIndexedTagName( $result, $type );
+
+               return $result;
+       }
+
+       protected function formatMessageInternal( $msg, $format ) {
+               return [
+                       'code' => $msg->getApiCode(),
+                       'info' => $msg->text(),
+               ] + $msg->getApiData();
+       }
+
+       /**
+        * Format an exception as an array
+        * @since 1.29
+        * @param Exception|Throwable $exception
+        * @param array $options See parent::formatException(), plus
+        *  - bc: (bool) Return only the string, not an array
+        * @return array|string
+        */
+       public function formatException( $exception, array $options = [] ) {
+               $ret = parent::formatException( $exception, $options );
+               return empty( $options['bc'] ) ? $ret : $ret['info'];
+       }
+
+       protected function addWarningOrError( $tag, $modulePath, $msg ) {
+               $value = self::stripMarkup( $msg->text() );
+
+               if ( $tag === 'error' ) {
+                       // In BC mode, only one error
+                       $existingError = $this->result->getResultData( [ 'error' ] );
+                       if ( !is_array( $existingError ) ||
+                               !isset( $existingError['code'] ) || !isset( $existingError['info'] )
+                       ) {
+                               $value = [
+                                       'code' => $msg->getApiCode(),
+                                       'info' => $value,
+                               ] + $msg->getApiData();
+                               $this->result->addValue( null, 'error', $value,
+                                       ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
+                       }
+               } else {
+                       if ( $modulePath === null ) {
+                               $moduleName = 'unknown';
+                       } else {
+                               $i = strrpos( $modulePath, '+' );
+                               $moduleName = $i === false ? $modulePath : substr( $modulePath, $i + 1 );
+                       }
+
+                       // Don't add duplicate warnings
+                       $tag .= 's';
+                       $path = [ $tag, $moduleName ];
+                       $oldWarning = $this->result->getResultData( [ $tag, $moduleName, $tag ] );
+                       if ( $oldWarning !== null ) {
+                               $warnPos = strpos( $oldWarning, $value );
+                               // If $value was found in $oldWarning, check if it starts at 0 or after "\n"
+                               if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
+                                       // Check if $value is followed by "\n" or the end of the $oldWarning
+                                       $warnPos += strlen( $value );
+                                       if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
+                                               return;
+                                       }
+                               }
+                               // If there is a warning already, append it to the existing one
+                               $value = "$oldWarning\n$value";
+                       }
+                       $this->result->addContentValue( $path, $tag, $value,
+                               ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
+               }
+       }
+}
index f52a6f3..7995e3e 100644 (file)
@@ -67,6 +67,7 @@ class SpecialActiveUsers extends SpecialPage {
                                Html::rawElement( 'ul', [], $usersBody ) .
                                $pager->getNavigationBar()
                        );
+                       $out->addModuleStyles( 'mediawiki.interface.helpers.styles' );
                } else {
                        $out->addWikiMsg( 'activeusers-noresult' );
                }
index 7aef4ae..f8aac32 100644 (file)
@@ -59,7 +59,9 @@ class SpecialListUsers extends IncludableSpecialPage {
                        $s .= $this->msg( 'listusers-noresult' )->parseAsBlock();
                }
 
-               $this->getOutput()->addHTML( $s );
+               $out = $this->getOutput();
+               $out->addHTML( $s );
+               $out->addModuleStyles( 'mediawiki.interface.helpers.styles' );
        }
 
        /**
index 39da076..368c6d1 100644 (file)
@@ -225,7 +225,18 @@ class ActiveUsersPager extends UsersPager {
                $userName = $row->user_name;
 
                $ulinks = Linker::userLink( $row->user_id, $userName );
-               $ulinks .= Linker::userToolLinks( $row->user_id, $userName );
+               $ulinks .= Linker::userToolLinks(
+                       $row->user_id,
+                       $userName,
+                       // Should the contributions link be red if the user has no edits (using default)
+                       false,
+                       // Customisation flags (using default 0)
+                       0,
+                       // User edit count (using default)
+                       null,
+                       // do not wrap the message in parentheses (CSS will provide these)
+                       false
+               );
 
                $lang = $this->getLanguage();
 
index 8dd6e23..4453772 100644 (file)
@@ -178,7 +178,9 @@ class UsersPager extends AlphabeticPager {
                $ulinks .= Linker::userToolLinksRedContribs(
                        $row->user_id,
                        $userName,
-                       (int)$row->edits
+                       (int)$row->edits,
+                       // don't render parentheses in HTML markup (CSS will provide)
+                       false
                );
 
                $lang = $this->getLanguage();
index 87488eb..b923832 100644 (file)
@@ -1681,7 +1681,7 @@ return [
        ],
        'mediawiki.page.gallery.styles' => [
                'styles' => [
-                       'resources/src/mediawiki.page.gallery.styles/gallery.css',
+                       'resources/src/mediawiki.page.gallery.styles/gallery.less',
                        'resources/src/mediawiki.page.gallery.styles/print.css' => [ 'media' => 'print' ],
                ],
                'targets' => [ 'desktop', 'mobile' ],
index b61349b..393846d 100644 (file)
                                )
                        );
                } );
-
-               // Initial collapsed state
-               // (For back-compat with cached HTML from before ImagePage.php
-               // did this by default)
-               $tables.addClass( 'collapsed' );
        } );
-
 }() );
index dd52767..4ea1999 100644 (file)
                        .removeClass( 'slideshow-current' );
                $imageLi.addClass( 'slideshow-current' );
 
-               // 2. Create and show thumbnail
                this.$thumbnail = $imageLi.find( 'img' );
-               this.$img = $( '<img>' ).attr( {
-                       src: this.$thumbnail.attr( 'src' ),
-                       alt: this.$thumbnail.attr( 'alt' )
-               } );
-               // 'image' class required for detection by MultimediaViewer
-               $imgLink = $( '<a>' ).addClass( 'image' )
-                       .attr( 'href', $imageLi.find( 'a' ).eq( 0 ).attr( 'href' ) )
-                       .append( this.$img );
+               if ( this.$thumbnail.length ) {
+                       // 2. Create and show thumbnail
+                       this.$img = $( '<img>' ).attr( {
+                               src: this.$thumbnail.attr( 'src' ),
+                               alt: this.$thumbnail.attr( 'alt' )
+                       } );
+                       // 'image' class required for detection by MultimediaViewer
+                       $imgLink = $( '<a>' ).addClass( 'image' )
+                               .attr( 'href', $imageLi.find( 'a' ).eq( 0 ).attr( 'href' ) )
+                               .append( this.$img );
 
-               this.$imgContainer.empty().append( $imgLink );
+                       this.$imgContainer.empty().append( $imgLink );
+               } else {
+                       // 2b. No image found (e.g. file doesn't exist)
+                       this.$imgContainer.text( $imageLi.find( '.thumb' ).text() );
+               }
 
                // 3. Copy caption
                this.$imgCaption
                        .empty()
                        .append( $caption.clone() );
 
+               if ( !this.$thumbnail.length ) {
+                       return;
+               }
+
                // 4. Stretch thumbnail to correct size
                this.setImageSize();
 
                                // Pre-fetch the next image
                                this.loadImage( this.getNextImage().find( 'img' ) );
                        }
+               }.bind( this ) ).fail( function () {
+                       // Image didn't load
+                       var title = mw.Title.newFromImg( this.$img );
+                       this.$imgContainer.text( title ? title.getMainText() : '' );
                }.bind( this ) );
        };
 
diff --git a/resources/src/mediawiki.page.gallery.styles/gallery.css b/resources/src/mediawiki.page.gallery.styles/gallery.css
deleted file mode 100644 (file)
index b7a424f..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/* stylelint-disable selector-class-pattern */
-
-/* Galleries */
-/* These display attributes look nonsensical, but are needed to support IE and FF2 */
-/* Don't forget to update gallery.print.css */
-li.gallerybox {
-       vertical-align: top;
-       display: -moz-inline-box;
-       display: inline-block;
-}
-
-ul.gallery,
-li.gallerybox {
-       zoom: 1;
-       *display: inline;
-}
-
-ul.gallery {
-       margin: 2px;
-       padding: 2px;
-       display: block;
-}
-
-li.gallerycaption {
-       font-weight: bold;
-       text-align: center;
-       display: block;
-       word-wrap: break-word;
-}
-
-li.gallerybox div.thumb {
-       text-align: center;
-       margin: 2px;
-}
-
-li.gallerybox div.thumb img {
-       display: block;
-       margin: 0 auto;
-}
-
-div.gallerytext {
-       overflow: hidden;
-       font-size: 94%;
-       padding: 2px 4px;
-       word-wrap: break-word;
-}
-
-.galleryfilename {
-       display: block;
-}
-
-.galleryfilename-truncate {
-       white-space: nowrap;
-       overflow: hidden;
-       text-overflow: ellipsis;
-}
-
-/* new gallery stuff */
-ul.mw-gallery-nolines li.gallerybox div.thumb {
-       background-color: transparent;
-       border: 0;
-}
-
-ul.mw-gallery-nolines li.gallerybox div.gallerytext {
-       text-align: center;
-}
-
-/* height constrained gallery */
-
-ul.mw-gallery-packed li.gallerybox div.thumb,
-ul.mw-gallery-packed-overlay li.gallerybox div.thumb,
-ul.mw-gallery-packed-hover li.gallerybox div.thumb {
-       background-color: transparent;
-       border: 0;
-}
-
-ul.mw-gallery-packed li.gallerybox div.thumb img,
-ul.mw-gallery-packed-overlay li.gallerybox div.thumb img,
-ul.mw-gallery-packed-hover li.gallerybox div.thumb img {
-       margin: 0 auto;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox,
-ul.mw-gallery-packed-overlay li.gallerybox {
-       position: relative;
-}
-
-ul.mw-gallery-packed-hover div.gallerytextwrapper {
-       overflow: hidden;
-       height: 0;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
-ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
-ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
-       position: absolute;
-       background: #fff;
-       background: rgba( 255, 255, 255, 0.8 );
-       padding: 5px 10px;
-       bottom: 0;
-       left: 0; /* Needed for IE */
-       height: auto;
-       max-height: 40%;
-       overflow: hidden;
-       font-weight: bold;
-       margin: 2px; /* correspond to style on div.thumb */
-}
-
-ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper p,
-ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper p,
-ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper p {
-       text-overflow: ellipsis;
-       white-space: nowrap;
-       overflow: hidden;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox div.gallerytextwrapper:hover,
-ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper:hover,
-ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper:hover {
-       overflow: visible;
-       max-height: none;
-}
-
-ul.mw-gallery-packed-hover li.gallerybox div.gallerytextwrapper:hover p,
-ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper:hover p,
-ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper:hover p {
-       text-overflow: clip;
-       white-space: normal;
-       overflow: visible;
-}
-
-ul.mw-gallery-packed-hover,
-ul.mw-gallery-packed-overlay,
-ul.mw-gallery-packed {
-       text-align: center;
-}
-
-/* Slideshow */
-ul.gallery.mw-gallery-slideshow {
-       display: block;
-       margin: 4em 0;
-}
-
-ul.gallery.mw-gallery-slideshow .gallerycaption {
-       font-size: 1.3em;
-       margin: 0;
-}
-
-ul.gallery.mw-gallery-slideshow .gallerycarousel.mw-gallery-slideshow-thumbnails-toggled {
-       margin-bottom: 1.3em;
-}
-
-ul.gallery.mw-gallery-slideshow .mw-gallery-slideshow-buttons {
-       opacity: 0.5;
-       padding: 1.3em 0;
-}
-
-ul.gallery.mw-gallery-slideshow .mw-gallery-slideshow-buttons .oo-ui-buttonElement {
-       margin: 0 2em;
-}
-
-.mw-gallery-slideshow li.gallerybox.slideshow-current {
-       background: #efefef;
-}
-
-.mw-gallery-slideshow .gallerybox > div {
-       max-width: 120px;
-}
-
-ul.mw-gallery-slideshow li.gallerybox div.thumb {
-       border: 0;
-       background: transparent;
-}
-
-ul.mw-gallery-slideshow li.gallerycarousel {
-       display: block;
-       text-align: center;
-}
-
-.mw-gallery-slideshow-img-container a {
-       display: block;
-}
-
-@media screen {
-       /* Background and border colors are defined separately for print mode */
-       li.gallerybox div.thumb {
-               border: 1px solid #c8ccd1;
-               background-color: #f8f9fa;
-       }
-}
diff --git a/resources/src/mediawiki.page.gallery.styles/gallery.less b/resources/src/mediawiki.page.gallery.styles/gallery.less
new file mode 100644 (file)
index 0000000..61bf5c3
--- /dev/null
@@ -0,0 +1,196 @@
+/* stylelint-disable selector-class-pattern */
+
+/* Galleries */
+/* These display attributes look nonsensical, but are needed to support IE and FF2 */
+/* Don't forget to update gallery.print.css */
+
+ul.gallery {
+       margin: 2px;
+       padding: 2px;
+       display: block;
+}
+
+li.gallerycaption {
+       font-weight: bold;
+       text-align: center;
+       display: block;
+       word-wrap: break-word;
+}
+
+li.gallerybox {
+       vertical-align: top;
+       display: -moz-inline-box;
+       display: inline-block;
+
+       div.thumb {
+               text-align: center;
+               margin: 2px;
+
+               img {
+                       display: block;
+                       margin: 0 auto;
+               }
+       }
+}
+
+ul.gallery,
+li.gallerybox {
+       zoom: 1;
+       *display: inline;
+}
+
+div.gallerytext {
+       overflow: hidden;
+       font-size: 94%;
+       padding: 2px 4px;
+       word-wrap: break-word;
+}
+
+.galleryfilename {
+       display: block;
+
+       &-truncate {
+               white-space: nowrap;
+               overflow: hidden;
+               text-overflow: ellipsis;
+       }
+}
+
+/* new gallery stuff */
+ul.mw-gallery-nolines li.gallerybox {
+       div.thumb {
+               background-color: transparent;
+               border: 0;
+       }
+
+       div.gallerytext {
+               text-align: center;
+       }
+}
+
+/* height constrained gallery */
+
+ul.mw-gallery-packed,
+ul.mw-gallery-packed-overlay,
+ul.mw-gallery-packed-hover {
+       text-align: center;
+
+       li.gallerybox div.thumb {
+               background-color: transparent;
+               border: 0;
+
+               img {
+                       margin: 0 auto;
+               }
+       }
+}
+
+ul.mw-gallery-packed-hover,
+ul.mw-gallery-packed-overlay {
+       li.gallerybox {
+               position: relative;
+       }
+}
+
+ul.mw-gallery-packed-hover div.gallerytextwrapper {
+       overflow: hidden;
+       height: 0;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
+       position: absolute;
+       background: #fff;
+       background: rgba( 255, 255, 255, 0.8 );
+       padding: 5px 10px;
+       bottom: 0;
+       left: 0; /* Needed for IE */
+       height: auto;
+       max-height: 40%;
+       overflow: hidden;
+       font-weight: bold;
+       margin: 2px; /* correspond to style on div.thumb */
+
+       p {
+               text-overflow: ellipsis;
+               white-space: nowrap;
+               overflow: hidden;
+       }
+
+       &:hover {
+               overflow: visible;
+               max-height: none;
+
+               p {
+                       text-overflow: clip;
+                       white-space: normal;
+                       overflow: visible;
+               }
+       }
+}
+
+/* Slideshow */
+ul.gallery.mw-gallery-slideshow {
+       display: block;
+       margin: 4em 0;
+
+       .gallerycaption {
+               font-size: 1.3em;
+               margin: 0;
+       }
+
+       .gallerycarousel {
+               display: block;
+               text-align: center;
+
+               &.mw-gallery-slideshow-thumbnails-toggled {
+                       margin-bottom: 1.3em;
+               }
+       }
+
+       .mw-gallery-slideshow-buttons {
+               opacity: 0.5;
+               padding: 1.3em 0;
+               white-space: nowrap;
+
+               .oo-ui-buttonElement {
+                       margin: 0 2em;
+
+                       &:first-child {
+                               margin-left: 0;
+                       }
+
+                       &:last-child {
+                               margin-right: 0;
+                       }
+               }
+       }
+
+       .gallerybox {
+               &.slideshow-current {
+                       background: #efefef;
+               }
+
+               > div {
+                       max-width: 120px;
+               }
+
+               div.thumb {
+                       border: 0;
+                       background: transparent;
+               }
+       }
+}
+
+.mw-gallery-slideshow-img-container a {
+       display: block;
+}
+
+@media screen {
+       /* Background and border colors are defined separately for print mode */
+       li.gallerybox div.thumb {
+               border: 1px solid #c8ccd1;
+               background-color: #f8f9fa;
+       }
+}