* (bug 34876) jquery.makeCollapsible has been improved in performance.
* Added ContentHandler facility to allow extensions to support other content than wikitext.
See docs/contenthandler.txt for details.
+* $wgResponsiveImages is added to support images on high-DPI mobile and desktop displays.
=== Bug fixes in 1.21 ===
* (bug 40353) SpecialDoubleRedirect should support interwiki redirects.
*/
$wgDirectoryMode = 0777;
+/**
+ * Generate and use thumbnails suitable for screens with 1.5 and 2.0 pixel densities.
+ *
+ * This means a 320x240 use of an image on the wiki will also generate 480x360 and 640x480
+ * thumbnails, output via data-src-1-5 and data-src-2-0. Runtime JavaScript switches the
+ * images in after loading the original low-resolution versions depending on the reported
+ * window.devicePixelRatio.
+ */
+$wgResponsiveImages = true;
+
/**
* @name DJVU settings
* @{
return $s;
}
+
+ /**
+ * Generate a srcset attribute value from an array mapping pixel densities
+ * to URLs. Note that srcset supports width and height values as well, which
+ * are not used here.
+ *
+ * @param array $urls
+ * @return string
+ */
+ static function srcSet( $urls ) {
+ $candidates = array();
+ foreach( $urls as $density => $url ) {
+ // Image candidate syntax per current whatwg live spec, 2012-09-23:
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#attr-img-srcset
+ $candidates[] = "{$url} {$density}x";
+ }
+ return implode( ", ", $candidates );
+ }
}
if ( !$thumb ) {
$s = self::makeBrokenImageLinkObj( $title, $fp['title'], '', '', '', $time == true );
} else {
+ self::processResponsiveImages( $file, $thumb, $hp );
$params = array(
'alt' => $fp['alt'],
'title' => $fp['title'],
$hp['width'] = isset( $fp['upright'] ) ? 130 : 180;
}
$thumb = false;
+ $noscale = false;
if ( !$exists ) {
$outerWidth = $hp['width'] + 2;
} elseif ( isset( $fp['framed'] ) ) {
// Use image dimensions, don't scale
$thumb = $file->getUnscaledThumb( $hp );
+ $noscale = true;
} else {
# Do not present an image bigger than the source, for bitmap-style images
# This is a hack to maintain compatibility with arbitrary pre-1.10 behaviour
$s .= wfMessage( 'thumbnail_error', '' )->escaped();
$zoomIcon = '';
} else {
+ if ( !$noscale ) {
+ self::processResponsiveImages( $file, $thumb, $hp );
+ }
$params = array(
'alt' => $fp['alt'],
'title' => $fp['title'],
return str_replace( "\n", ' ', $s );
}
+ /**
+ * Process responsive images: add 1.5x and 2x subimages to the thumbnail, where
+ * applicable.
+ *
+ * @param File $file
+ * @param MediaOutput $thumb
+ * @param array $hp image parameters
+ */
+ protected static function processResponsiveImages( $file, $thumb, $hp ) {
+ global $wgResponsiveImages;
+ if ( $wgResponsiveImages ) {
+ $hp15 = $hp;
+ $hp15['width'] = round( $hp['width'] * 1.5 );
+ $hp20 = $hp;
+ $hp20['width'] = $hp['width'] * 2;
+ if ( isset( $hp['height'] ) ) {
+ $hp15['height'] = round( $hp['height'] * 1.5 );
+ $hp20['height'] = $hp['height'] * 2;
+ }
+
+ $thumb15 = $file->transform( $hp15 );
+ $thumb20 = $file->transform( $hp20 );
+ if ( $thumb15->url !== $thumb->url ) {
+ $thumb->responsiveUrls['1.5'] = $thumb15->url;
+ }
+ if ( $thumb20->url !== $thumb->url ) {
+ $thumb->responsiveUrls['2'] = $thumb20->url;
+ }
+ }
+ }
+
/**
* Make a "broken" link to an image
*
*/
private function addDefaultModules() {
global $wgIncludeLegacyJavaScript, $wgPreloadJavaScriptMwUtil, $wgUseAjax,
- $wgAjaxWatch;
+ $wgAjaxWatch, $wgResponsiveImages;
// Add base resources
$this->addModules( array(
if ( $this->isArticle() && $this->getUser()->getOption( 'editondblclick' ) ) {
$this->addModules( 'mediawiki.action.view.dblClickEdit' );
}
+
+ // Support for high-density display images
+ if ( $wgResponsiveImages ) {
+ $this->addModules( 'mediawiki.hidpi' );
+ }
}
/**
var $file;
var $width, $height, $url, $page, $path;
+
+ /**
+ * @var array Associative array mapping optional supplementary image files
+ * from pixel density (eg 1.5 or 2) to additional URLs.
+ */
+ public $responsiveUrls = array();
+
protected $storagePath = false;
/**
'alt' => $alt,
'src' => $this->url,
'width' => $this->width,
- 'height' => $this->height,
+ 'height' => $this->height
);
if ( !empty( $options['valign'] ) ) {
$attribs['style'] = "vertical-align: {$options['valign']}";
if ( !empty( $options['img-class'] ) ) {
$attribs['class'] = $options['img-class'];
}
+
+ // Additional densities for responsive images, if specified.
+ if ( !empty( $this->responsiveUrls ) ) {
+ $attribs['srcset'] = Html::srcSet( $this->responsiveUrls );
+ }
return $this->linkWrap( $linkAttribs, Xml::element( 'img', $attribs ) );
}
'jquery.getAttrs' => array(
'scripts' => 'resources/jquery/jquery.getAttrs.js',
),
+ 'jquery.hidpi' => array(
+ 'scripts' => 'resources/jquery/jquery.hidpi.js',
+ ),
'jquery.highlightText' => array(
'scripts' => 'resources/jquery/jquery.highlightText.js',
'dependencies' => 'jquery.mwExtension',
'feedback-bugnew',
),
),
+ 'mediawiki.hidpi' => array(
+ 'scripts' => 'resources/mediawiki/mediawiki.hidpi.js',
+ 'dependencies' => array(
+ 'jquery.hidpi',
+ ),
+ ),
'mediawiki.htmlform' => array(
'scripts' => 'resources/mediawiki/mediawiki.htmlform.js',
),
--- /dev/null
+/**
+ * Responsive images based on 'srcset' and 'window.devicePixelRatio' emulation where needed.
+ *
+ * Call $().hidpi() on a document or part of a document to replace image srcs in that section.
+ *
+ * $.devicePixelRatio() can be used to supplement window.devicePixelRatio with support on
+ * some additional browsers.
+ */
+( function ( $ ) {
+
+/**
+ * Detect reported or approximate device pixel ratio.
+ * 1.0 means 1 CSS pixel is 1 hardware pixel
+ * 2.0 means 1 CSS pixel is 2 hardware pixels
+ * etc
+ *
+ * Uses window.devicePixelRatio if available, or CSS media queries on IE.
+ *
+ * @method
+ * @returns {number} Device pixel ratio
+ */
+$.devicePixelRatio = function () {
+ if ( window.devicePixelRatio !== undefined ) {
+ // Most web browsers:
+ // * WebKit (Safari, Chrome, Android browser, etc)
+ // * Opera
+ // * Firefox 18+
+ return window.devicePixelRatio;
+ } else if ( window.msMatchMedia !== undefined ) {
+ // Windows 8 desktops / tablets, probably Windows Phone 8
+ //
+ // IE 10 doesn't report pixel ratio directly, but we can get the
+ // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
+ // simplicity, but you may get different values depending on zoom
+ // factor, size of screen and orientation in Metro IE.
+ if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
+ return 2;
+ } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
+ return 1.5;
+ } else {
+ return 1;
+ }
+ } else {
+ // Legacy browsers...
+ // Assume 1 if unknown.
+ return 1;
+ }
+};
+
+/**
+ * Implement responsive images based on srcset attributes, if browser has no
+ * native srcset support.
+ *
+ * @method
+ * @returns {jQuery} This selection
+ */
+$.fn.hidpi = function () {
+ var $target = this,
+ // @todo add support for dpi media query checks on Firefox, IE
+ devicePixelRatio = $.devicePixelRatio(),
+ testImage = new Image();
+
+ if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
+ // No native srcset support.
+ $target.find( 'img' ).each( function () {
+ var $img = $( this ),
+ srcset = $img.attr( 'srcset' ),
+ match;
+ if ( typeof srcset === 'string' && srcset !== '' ) {
+ match = $.matchSrcSet( devicePixelRatio, srcset );
+ if (match !== null ) {
+ $img.attr( 'src', match );
+ }
+ }
+ });
+ }
+
+ return $target;
+};
+
+/**
+ * Match a srcset entry for the given device pixel ratio
+ *
+ * @param {number} devicePixelRatio
+ * @param {string} srcset
+ * @return {mixed} null or the matching src string
+ *
+ * Exposed for testing.
+ */
+$.matchSrcSet = function ( devicePixelRatio, srcset ) {
+ var candidates,
+ candidate,
+ bits,
+ src,
+ i,
+ ratioStr,
+ ratio,
+ selectedRatio = 1,
+ selectedSrc = null;
+ candidates = srcset.split( / *, */ );
+ for ( i = 0; i < candidates.length; i++ ) {
+ candidate = candidates[i];
+ bits = candidate.split( / +/ );
+ src = bits[0];
+ if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
+ ratioStr = bits[1].substr( 0, bits[1].length - 1 );
+ ratio = parseFloat( ratioStr );
+ if ( ratio > devicePixelRatio ) {
+ // Too big, skip!
+ } else if ( ratio > selectedRatio ) {
+ selectedRatio = ratio;
+ selectedSrc = src;
+ }
+ }
+ }
+ return selectedSrc;
+};
+
+}( jQuery ) );
--- /dev/null
+$( function() {
+ // Apply hidpi images on DOM-ready
+ // Some may have already partly preloaded at low resolution.
+ $( 'body' ).hidpi();
+} );
\ No newline at end of file
'wgNoFollowLinks' => true,
'wgNoFollowDomainExceptions' => array(),
'wgThumbnailScriptPath' => false,
- 'wgUseImageResize' => false,
+ 'wgUseImageResize' => true,
'wgLocaltimezone' => 'UTC',
'wgAllowExternalImages' => true,
'wgUseTidy' => false,
!! input
[[Image:foobar.jpg|thumb|link=http://example.com/|Title]]
!! result
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="http://example.com/"><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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
!! end
!! input
[[Image:foobar.jpg|thumb|http://example.com]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
!! end
!! input
[[Image:foobar.jpg|thumb|http://example.com|alt=Alteration]]
!! result
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" 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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
!! end
!! input
[[Image:foobar.jpg|thumb|ISBN 1235467890]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
!! end
!! input
[[Image:foobar.jpg|thumb|This is RFC 12354]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
!! end
!! input
[[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
!! end
!! input
[[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&wpDestFile=Icon.png" class="new" title="File:Icon.png">image</a> inside it!</div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&wpDestFile=Icon.png" class="new" title="File:Icon.png">image</a> inside it!</div></div></div>
!! end
!! input
[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
!! result
-<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/3/3a/Foobar.jpg" width="200" height="23" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></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>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></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>
!! end
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
<div class="gallerytext">
<p>some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a foo-bar." src="http://example.com/images/3/3a/Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a foo-bar." src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
<div class="gallerytext">
<p>Blabla|blabla.
</p>
!! result
<ul class="gallery">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
-<p><a href="/wiki/File:Foobar.jpg" class="image" title="desc"><img alt="inneralt" src="http://example.com/images/3/3a/Foobar.jpg" width="20" height="2" /></a>
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="desc"><img alt="inneralt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" width="20" height="2" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg 2x" /></a>
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p>This is a test template
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p><a href="/wiki/File:Foobar.jpg" title="File:Foobar.jpg">Foobar.jpg</a><br />
some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p><a href="/wiki/File:Foobar.jpg" title="File:Foobar.jpg">Foobar.jpg</a><br />
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
!! input
[[Image:foobar.jpg|640x480px]]
!! result
-<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="640" height="73" /></a>
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
</p>
!!end
!! input
[[Image:foobar.jpg|640px]]
!! result
-<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="640" height="73" /></a>
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
</p>
!!end
!! input
[[Image:foobar.jpg|640px ]]
!! result
-<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="640" height="73" /></a>
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
</p>
!!end
!! input
[[Image:foobar.jpg| 640px]]
!! result
-<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="640" height="73" /></a>
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
</p>
!!end
!! input
[[image:Foobar.jpg|thumb|An [http://test/?param1=|left|¶m2=|x external] URL]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&param2=%7Cx">external</a> URL</div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&param2=%7Cx">external</a> URL</div></div></div>
!!end
!! input
[[Image:Foobar.jpg|thumb|http://x|hello]]
!! result
-<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/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>hello</div></div></div>
+<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"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>hello</div></div></div>
!! end
!! result
<ul class="gallery">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
!! result
<ul class="gallery">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
!! result
<ul class="gallery">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/3/3a/Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
'wgNoFollowLinks' => true,
'wgNoFollowDomainExceptions' => array(),
'wgThumbnailScriptPath' => false,
- 'wgUseImageResize' => false,
+ 'wgUseImageResize' => true,
'wgUseTeX' => isset( $opts['math'] ),
'wgMathDirectory' => $uploadDir . '/math',
'wgLocaltimezone' => 'UTC',
'tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js',
'tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js',
'tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js',
+ 'tests/qunit/suites/resources/jquery/jquery.hidpi.test.js',
'tests/qunit/suites/resources/jquery/jquery.highlightText.test.js',
'tests/qunit/suites/resources/jquery/jquery.localize.test.js',
'tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js',
'jquery.colorUtil',
'jquery.delayedBind',
'jquery.getAttrs',
+ 'jquery.hidpi',
'jquery.highlightText',
'jquery.localize',
'jquery.mwExtension',
--- /dev/null
+QUnit.module( 'jquery.hidpi', QUnit.newMwEnvironment() );
+
+QUnit.test( 'devicePixelRatio', function ( assert ) {
+ var devicePixelRatio = $.devicePixelRatio();
+ assert.equal( typeof devicePixelRatio, 'number', '$.devicePixelRatio() returns a number' );
+});
+
+QUnit.test( 'matchSrcSet', function ( assert ) {
+ var srcset = 'onefive.png 1.5x, two.png 2x';
+
+ // Nice exact matches
+ assert.equal( $.matchSrcSet( 1, srcset ), null, '1.0 gives no match' );
+ assert.equal( $.matchSrcSet( 1.5, srcset ), 'onefive.png', '1.5 gives match' );
+ assert.equal( $.matchSrcSet( 2, srcset ), 'two.png', '2 gives match' );
+
+ // Non-exact matches; should return the next-biggest specified
+ assert.equal( $.matchSrcSet( 1.25, srcset ), null, '1.25 gives no match' );
+ assert.equal( $.matchSrcSet( 1.75, srcset ), 'onefive.png', '1.75 gives match to 1.5' );
+ assert.equal( $.matchSrcSet( 2.25, srcset ), 'two.png', '2.25 gives match to 2' );
+});