jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/347649 )
Change subject: Don't lazy load small images (smaller than 50px or 10ex)
......................................................................
Don't lazy load small images (smaller than 50px or 10ex)
Changes:
- added a logic that skips lazy loading images smaller than 50px
- added a config MFLazyLoadSkipSmallImages to disable/enable this feature
Bug: T162623
Change-Id: I9a631a6de9e5dbf348314571c28b491dff94f4de
---
M extension.json
M includes/MobileFormatter.php
M tests/phpunit/MobileFormatterTest.php
3 files changed, 114 insertions(+), 6 deletions(-)
Approvals:
jenkins-bot: Verified
Jdlrobson: Looks good to me, approved
diff --git a/extension.json b/extension.json
index 836a32d..842101e 100644
--- a/extension.json
+++ b/extension.json
@@ -1771,6 +1771,7 @@
"base": false,
"beta": true
},
+ "MFLazyLoadSkipSmallImages": false,
"MFLazyLoadReferences": {
"base": false,
"beta": false
diff --git a/includes/MobileFormatter.php b/includes/MobileFormatter.php
index 9a88fbb..b983892 100644
--- a/includes/MobileFormatter.php
+++ b/includes/MobileFormatter.php
@@ -13,6 +13,17 @@
* Class name for collapsible section wrappers
*/
const STYLE_COLLAPSIBLE_SECTION_CLASS = 'collapsible-block';
+
+ /**
+ * Do not lazy load images smaller than this size (in pixels)
+ * @var int
+ */
+ const SMALL_IMAGE_DIMENSION_THRESHOLD_IN_PX = 50;
+ /**
+ * Do not lazy load images smaller than this size (in relative to
x-height of the current font)
+ * @var int
+ */
+ const SMALL_IMAGE_DIMENSION_THRESHOLD_IN_EX = 10;
/**
* Whether scripts can be added in the output.
* @var boolean $scriptsEnabled
@@ -383,12 +394,54 @@
}
/**
+ * Is image dimension small enough to not lazy load it
+ *
+ * @param string $dimension in css format, supports only px|ex units
+ * @return bool
+ */
+ public function isDimensionSmallerThanThreshold( $dimension ) {
+ $matches = null;
+ if ( preg_match( '/(\d+)(\.\d+)?(px|ex)/', $dimension, $matches
) === 0 ) {
+ return false;
+ }
+
+ $size = $matches[1];
+ $unit = array_pop( $matches );
+
+ switch ( strtolower( $unit ) ) {
+ case 'px':
+ return $size <=
self::SMALL_IMAGE_DIMENSION_THRESHOLD_IN_PX;
+ case 'ex':
+ return $size <=
self::SMALL_IMAGE_DIMENSION_THRESHOLD_IN_EX;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * @param array $dimensions
+ * @return bool
+ */
+ private function skipLazyLoadingForSmallDimensions( array $dimensions )
{
+ if ( array_key_exists( 'width', $dimensions )
+ && $this->isDimensionSmallerThanThreshold(
$dimensions['width'] ) ) {
+ return true;
+ };
+ if ( array_key_exists( 'height', $dimensions )
+ && $this->isDimensionSmallerThanThreshold(
$dimensions['height'] ) ) {
+ return true;
+ }
+ return false;
+ }
+ /**
* Enables images to be loaded asynchronously
*
* @param DOMElement|DOMDocument $el Element or document to rewrite
images in.
* @param DOMDocument $doc Document to create elements in
*/
private function doRewriteImagesForLazyLoading( $el, DOMDocument $doc )
{
+ $lazyLoadSkipSmallImages =
MobileContext::singleton()->getMFConfig()
+ ->get( 'MFLazyLoadSkipSmallImages' );
foreach ( $el->getElementsByTagName( 'img' ) as $img ) {
$parent = $img->parentNode;
@@ -397,6 +450,11 @@
$dimensionsStyle = ( isset( $dimensions['width'] ) ?
"width: {$dimensions['width']};" : '' ) .
( isset( $dimensions['height'] ) ? "height:
{$dimensions['height']};" : '' );
+ if ( $lazyLoadSkipSmallImages
+ && $this->skipLazyLoadingForSmallDimensions(
$dimensions ) ) {
+ continue;
+ }
+
// HTML only clients
$noscript = $doc->createElement( 'noscript' );
diff --git a/tests/phpunit/MobileFormatterTest.php
b/tests/phpunit/MobileFormatterTest.php
index 05773fc..49f181e 100644
--- a/tests/phpunit/MobileFormatterTest.php
+++ b/tests/phpunit/MobileFormatterTest.php
@@ -72,8 +72,28 @@
$mf->topHeadingTags = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ];
$mf->filterContent( $removeDefaults, $lazyLoadReferences,
$lazyLoadImages,
$showFirstParagraphBeforeInfobox );
+
$html = $mf->getText();
$this->assertEquals( str_replace( "\n", '', $expected ),
str_replace( "\n", '', $html ) );
+ }
+
+ public function testHtmlTransformWhenSkippingLazyLoadingSmallImages() {
+ $smallPic = '<img src="smallPicture.jpg" style="width: 4.4ex;
height:3.34ex;">';
+ $enableSections = function ( MobileFormatter $mf ) {
+ $mf->enableExpandableSections();
+ };
+ $this->setMwGlobals( [
+ 'wgMFLazyLoadSkipSmallImages' => true
+ ] );
+
+ $this->testHtmlTransform(
+ '<p>text</p><h2>heading 1</h2>' . $smallPic,
+ $this->makeSectionHtml( 0, '<p>text</p>' )
+ . $this->makeSectionHeading( 'h2', 'heading 1' )
+ . $this->makeSectionHtml( 1, $smallPic ),
+ $enableSections,
+ false, false, true
+ );
}
public function provideHtmlTransform() {
@@ -88,14 +108,15 @@
$f->setIsMainPage( true );
};
$citeUrl = SpecialPage::getTitleFor( 'MobileCite', '0'
)->getLocalUrl();
- $imageStyles = '<img src="math.jpg" style="vertical-align:
-3.505ex; '
- . 'width: 24.412ex; height:7.343ex; background:none;">';
+ $lazyLoadedImageStyles = '<img src="bigPicture.jpg"
style="vertical-align: -3.505ex; '
+ . 'width: 84.412ex; height:70.343ex;
background:none;">';
+
$placeholderStyles = '<span class="lazy-image-placeholder" '
- . 'style="width: 24.412ex;height: 7.343ex;" '
- . 'data-src="math.jpg">'
+ . 'style="width: 84.412ex;height: 70.343ex;" '
+ . 'data-src="bigPicture.jpg">'
. ' '
. '</span>';
- $noscriptStyles = '<noscript>' . $imageStyles . '</noscript>';
+ $noscriptStyles = '<noscript>' . $lazyLoadedImageStyles .
'</noscript>';
$originalImage = '<img alt="foo" src="foo.jpg" width="100" '
. 'height="100" srcset="foo-1.5x.jpg 1.5x, foo-2x.jpg
2x">';
$placeholder = '<span class="lazy-image-placeholder" '
@@ -157,7 +178,7 @@
],
// Test lazy loading of images with style attributes
[
- '<p>text</p><h2>heading 1</h2><p>text</p>' .
$imageStyles
+ '<p>text</p><h2>heading 1</h2><p>text</p>' .
$lazyLoadedImageStyles
. '<h2>heading 2</h2>abc',
$this->makeSectionHtml( 0, '<p>text</p>' )
. $this->makeSectionHeading( 'h2',
'heading 1' )
@@ -796,6 +817,34 @@
];
}
+ /**
+ * @dataProvider provideIsDimensionSmallerThanThreshold
+ * @covers MobileFormatter::isDimensionSmallerThanThreshold
+ */
+ public function testIsDimensionSmallerThanThreshold( $dimension,
$expected ) {
+ $mf = new MobileFormatter( '', Title::newFromText( 'Test' ) );
+ $this->assertEquals( $expected,
$mf->isDimensionSmallerThanThreshold( $dimension ) );
+ }
+
+ /**
+ * @see https://phabricator.wikimedia.org/T162623
+ */
+ public function provideIsDimensionSmallerThanThreshold() {
+ return [
+ [ '40px', true ],
+ [ '50px', true ],
+ [ '57px', false ],
+ [ '100ox', false ],
+ [ '10', false ],
+ [ '5.12ex', true ],
+ [ '9.89ex', true ],
+ [ '15.1ex', false ],
+ [ '10in', false ],
+ [ 'big', false ],
+ [ '', false ]
+ ];
+ }
+
public function testInsertTOCPlaceholder() {
$input = '<p>Hello world.</p><h2>Heading</h2>Text.';
$mf = new MobileFormatter( $input, Title::newFromText( 'Mobile'
) );
--
To view, visit https://gerrit.wikimedia.org/r/347649
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I9a631a6de9e5dbf348314571c28b491dff94f4de
Gerrit-PatchSet: 10
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Pmiazga <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Pmiazga <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits