Problem/Motivation

  • We need support for srcset, this will be used by picture, but contrib can use this as well to output an image with srcset.

Proposed resolution

  • Add srcset attribute to image render

Remaining tasks

  • Add tests for srcset

User interface changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

attiks’s picture

FileSize
1.43 KB

WIP, but first patch

attiks’s picture

Status: Active » Needs review
attiks’s picture

FileSize
7.05 KB

New patching adding transformMimeType to all effects

Status: Needs review » Needs work

The last submitted patch, 3: i2262863-image-srcset-3.patch, failed testing.

attiks’s picture

Status: Needs work » Needs review
FileSize
7.09 KB

Status: Needs review » Needs work

The last submitted patch, 5: i2262863-image-srcset-5.patch, failed testing.

attiks’s picture

Status: Needs work » Needs review
FileSize
7.09 KB
attiks’s picture

andypost’s picture

I think there's no reason to introduce API change here, so just add a new attribute and test for it

+++ b/core/includes/theme.inc
@@ -1276,9 +1276,31 @@ function template_preprocess_links(&$variables) {
+  if (isset($variables['uri']) && !empty($variables['uri'])) {
...
+  if (isset($variables['srcset']) && !empty($variables['srcset'])) {

!empty() is enough

+++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
@@ -312,6 +312,15 @@ public function transformDimensions(array &$dimensions) {
+  public function transformMimeType(&$mime_type) {

+++ b/core/modules/image/lib/Drupal/image/ImageEffectBase.php
@@ -47,6 +47,13 @@ public function transformDimensions(array &$dimensions) {
+  public function transformMimeType(&$mime_type) {
+    $mime_type = NULL;

+++ b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php
@@ -37,6 +37,14 @@ public function applyEffect(ImageInterface $image);
+  public function transformMimeType(&$mime_type);

+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php
@@ -30,6 +30,12 @@ public function transformDimensions(array &$dimensions) {
+  public function transformMimeType(&$mime_type) {
+  }

It's not clear the reason to introduce API change here?

attiks’s picture

The change is needed because an image style might change the file format (ex. from png to jpg), we need to know this so we can output the correct type on the source tag of picture.

attiks’s picture

We need some additions to the image module to support responsive images (picture):

  1. We need support for srcset
  2. We need support for the mime type and we need to be able to determine the mime type of a derivative without generating it.
attiks’s picture

!empty() is enough

andypost’s picture

Issue summary: View changes
Issue tags: +API addition

This is API addition, updated summary.
except tests this one needs at least one usage in core

@attiks please check summary

+++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
@@ -312,6 +312,15 @@ public function transformDimensions(array &$dimensions) {
+  public function transformMimeType(&$mime_type) {

suppose this one should be added to interface as well

attiks’s picture

Issue summary: View changes
attiks’s picture

this one needs at least one usage in core

Is that mandatory?

attiks’s picture

suppose this one should be added to interface as well

It is

andypost’s picture

No, I mean ImageStyleInterface should be updated with the new public method too

attiks’s picture

Jelle_S’s picture

FileSize
11.45 KB
3.56 KB

Added tests for transformMimeType().

Jelle_S’s picture

Issue summary: View changes
yched’s picture

  1. +++ b/core/includes/theme.inc
    @@ -1279,9 +1279,31 @@ function template_preprocess_links(&$variables) {
    +      if (isset($srcset['uri']) && !empty($srcset['uri'])) {
    ...
    +        if (isset($srcset['width']) && !empty($srcset['width'])) {
    ...
    +        elseif (isset($srcset['multiplier']) && !empty($srcset['multiplier'])) {
    

    Why both isset() and !empty() ? The latter should be enough ?

  2. +++ b/core/modules/image/lib/Drupal/image/ImageEffectBase.php
    @@ -47,6 +47,13 @@ public function transformDimensions(array &$dimensions) {
    +  public function transformMimeType(&$mime_type) {
    +    $mime_type = NULL;
    +  }
    

    The base/default implementation coul be "just leave the $mime_type untouched", instead of forcing 99% effects to override that one ?

attiks’s picture

#21:

1/ Bad habits from the past, I'll fix it

2/ TRUE, but transformDimensions does somethin similar, so we kept it the same, I'll (or Jelle_S) change it as well

Jelle_S’s picture

FileSize
8.52 KB
2.31 KB
  1. That is true for the first level of the $variables array, as you can provide default values for each key. But since the 'srcset' key contains an array with multiple srcsets, there are no default values for those keys, so both isset() and !empty() are necessary to prevent PHP notices.
  2. new patch changes transformMimeType in ImageEffectBase to an empty function.

The last submitted patch, 23: i2262863-image-srcset-23.patch, failed testing.

attiks’s picture

RainbowArray’s picture

+++ b/core/modules/image/src/Entity/ImageStyle.php
@@ -333,7 +342,7 @@ public function getEffect($effect) {
-      $this->effectsBag = new ImageEffectBag(\Drupal::service('plugin.manager.image.effect'), $this->effects);
+      $this->effectsBag = new ImageEffectBag($this->getImageEffectPluginManager(), $this->effects);

@@ -377,4 +386,11 @@ public function setName($name) {
+  /**
+   * {@inheritdoc}
+   */
+  public function getImageEffectPluginManager() {
+    return \Drupal::service('plugin.manager.image.effect');
+  }
+

+++ b/core/modules/image/src/Tests/ImageStyleTest.php
@@ -0,0 +1,111 @@
+      ->setMethods(array('getImageEffectPluginManager'))
...
+      ->method('getImageEffectPluginManager')

This is probably a dumb question because I don't understand things, but why I are we creating a method just to wrap around the service call?

Is that for use in ImageStyleTest?

attiks’s picture

#27 It is for testing

Jelle_S’s picture

#2260061-89: Responsive image module does not support sizes/picture polyfill 2.2 point 3 and #2260061-93: Responsive image module does not support sizes/picture polyfill 2.2

So basically, yes it is for use in ImageStyleTest. This way we don't have to mock the container in a UnitTest (which apparently is a big no-no :-) )

yched’s picture

Nitpicks below

  1. +++ b/core/includes/theme.inc
    @@ -1077,9 +1077,30 @@ function template_preprocess_links(&$variables) {
    +    $srcsets = array(); 
    +    foreach ($variables['srcset'] as $srcset) {
    +      // URI is mandatory.
    +      $srcset['src'] = file_create_url($srcset['uri']);
    +      $new_source = $srcset['src'];
    +      if (isset($srcset['width']) && !empty($srcset['width'])) {
    +        $new_source .= ' ' . $srcset['width'];
    +      }
    +      elseif (isset($srcset['multiplier']) && !empty($srcset['multiplier'])) {
    +        $new_source .= ' ' . $srcset['multiplier'];
    +      }
    +      $srcsets[] = $new_source;
    +    }
    +    $variables['attributes']['srcset'] = implode(', ', $srcsets);
    

    Var names could be worked on a bit here.

    - This translates the info in $variable['srcset'] into an $srcsets array suitable for an 'srcset' HTML attribute. Why is one singular and the other plural ? Those two things contain the same info in different shapes.

    - "foreach (srcset as srcset)" is a bit weird. Strictly speaking, an element of an "srcset" is an "src" ? or a "source" ?

    - We don't need to assign back $srcset['src'], it is never used, so why not just $new_dource = file_create_uri(...) ?

    - "new" in $new_source is not really needed, it's the source string we're building in this iteration of the foreach. There is no "old" source here.

  2. +++ b/core/modules/image/src/ImageEffectInterface.php
    @@ -44,6 +44,14 @@ public function applyEffect(ImageInterface $image);
    +   *   MIME type to be modified.
    
    +++ b/core/modules/image/src/ImageStyleInterface.php
    @@ -131,6 +131,14 @@ public function createDerivative($original_uri, $derivative_uri);
    +   *   MIME type to be modified.
    

    Misses an article to be an actual sentence

Jelle_S’s picture

FileSize
9.11 KB
4.65 KB

New patch with remarks from #30 addressed.

yched’s picture

Thanks!

I don't see where the mimetype part of the patch gets used though ? AFAIK, the 'type' attribute is only for <source> tags within a picture, not for srcset on <img> tags, so this seems out of scope here ?

attiks’s picture

@yched you're right it is not used, do we have to split this patch in two parts?

yched’s picture

Well, or keep the mimetype part for a patch that does add support for the 'type' attribute on sources in theme_responsive_image() ?

attiks’s picture

Jelle_S’s picture

FileSize
4.85 KB
8.82 KB

New patch without the MIME type stuff, and with an added test.

Status: Needs review » Needs work

The last submitted patch, 36: i2262863-36.patch, failed testing.

yched’s picture

Not sure "outputted" is actual english ?
Other than that, looks good when green :-)

attiks’s picture

#38 Outputted is the paste tense of output, so it should be good. It is used in other places as well.

Jelle_S’s picture

Status: Needs work » Needs review
FileSize
5.91 KB
4.53 KB

Although "outputted" is actual english, preference seems to go to just "output" (http://english.stackexchange.com/questions/35418/past-tense-of-to-output...), so I changed it just to be on the safe side.

RainbowArray’s picture

You could replace output with processed as another option.

yched’s picture

Status: Needs review » Reviewed & tested by the community

Thanks. Language can be adjusted on commit if deemed necessary.

Jelle_S’s picture

Issue summary: View changes
Issue tags: -Needs tests
Jelle_S’s picture

attiks’s picture

Issue summary: View changes
webchick’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/includes/theme.inc
    @@ -1120,9 +1120,29 @@ function template_preprocess_links(&$variables) {
    + *   - srcset: Array of multiple URI's and sizes/multipliers.
    

    Minor grammar thing: URIs, not URI's. ;) http://theoatmeal.com/comics/apostrophe

    I can fix this on commit, but...

  2. +++ b/core/includes/theme.inc
    @@ -1120,9 +1120,29 @@ function template_preprocess_links(&$variables) {
    -  $variables['attributes']['src'] = file_create_url($variables['uri']);
    +  if (!empty($variables['uri'])) {
    +    $variables['attributes']['src'] = file_create_url($variables['uri']);
    +  }
    

    Reading through http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#attr-... it says:

    The src attribute must be present.

    The srcset attribute may also be present.

    (emphasis mine)

    So why did we turn variables['attributes']['src'] into an optional variable here?

  1. +++ b/core/modules/system/src/Tests/Theme/ImageTest.php
    @@ -0,0 +1,123 @@
    +class ImageTest extends DrupalUnitTestBase {
    

    Yay! Tests! That's great.

    However, AFAIK DUTB is being phased out in favor of KernelTestBase: https://www.drupal.org/node/1829160

  2. +++ b/core/modules/system/src/Tests/Theme/ImageTest.php
    @@ -0,0 +1,123 @@
    +    $this->render($image);
    +    $this->removeWhiteSpace();
    ...
    +    $this->render($image);
    +    $this->removeWhiteSpace();
    

    Unfortunate that we need this method call, and render() doesn't just do what you would expect. :( Is that a separate bug somewhere?

webchick’s picture

Status: Needs review » Needs work

Based on dawehner's comments on the sizes issue, this is actually needs work for the test.

attiks’s picture

#46

The src attribute must be present.

You're right, but we need to be able to suppress the output of the src attribute, because otherwise all the prefetchers will start downloading the src, the only way to avoid this is to output only the srcset attribute.

attiks’s picture

FYI: Another possible solution is to output an empty image as src, but this can only be done once #1342504: Support data URIs gets committed

Jelle_S’s picture

Status: Needs work » Needs review
FileSize
5.43 KB

Changed the test. I didn't want to change anything about the src attribute being optional or not until we can decide on #48 or #49.

RainbowArray’s picture

I just checked with the responsive images community group that came up with the picture element, and yes, while spec says that the img inside picture should always have src, that results in a double download with browsers that don't understand picture. So to make everything groovy when using this in conjunction with Picturefill, no src on the img inside picture. We're going to close our eyes, stick our fingers in our ears, go la la la la, and save the old browsers from two downloads. :)

webchick’s picture

That's a fair explanation, but is that relevant for D8? What "old browsers" are we supporting in D8? Or does IE9 count as an "old browser" in this context?

attiks’s picture

Old browsers are all IE version and safari, chrome 38 will have native support as well as the next Firefox release.

Jelle_S’s picture

In addition to #53:
It seems that in Firefox you'll have to enable a flag: http://caniuse.com/#feat=srcset
Also iOS Safari will only support srcset in iOS8 (To be fair, most people will probably have updated by the time Drupal 8 releases)

The biggest group will probably be the IE users and the Firefox users who haven't enabled the flag for srcset support.

RainbowArray’s picture

The browsers in question are all browsers out today. D8 is supporting browsers like IE11, so using no src on the img is something we need to ge able to do.

Firefox won't always have this behind a flag. That's a temporary thing.

webchick’s picture

Cool, thanks for answering!

attiks’s picture

Status: Needs review » Reviewed & tested by the community

This should be good to get committed, the remarks from dawehner are better handled in a separate issue, since this is not just about these newly added tests.

Jelle_S’s picture

I'm guessing this will need a reroll because #2333395: Add sizes to template_preprocess_image has been committed.

Jelle_S queued 50: i2262863-50.patch for re-testing.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 50: i2262863-50.patch, failed testing.

Jelle_S’s picture

Status: Needs work » Needs review
FileSize
5.95 KB

Rerolled patch

Jelle_S’s picture

Status: Needs review » Reviewed & tested by the community

Since it's just a reroll...

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Ok great! Committed and pushed to 8.x. Thanks!

Almost there. :)

  • webchick committed 7c309f9 on 8.0.x
    Issue #2262863 by attiks, Jelle_S: Add srcset to...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.