Skip to content

Commit 6e5cd31

Browse files
committed
set sizes for picture-tags, fixes #179
1 parent 104815e commit 6e5cd31

File tree

5 files changed

+101
-18
lines changed

5 files changed

+101
-18
lines changed

news/179.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
set sizes attribute on picture-tags [MrTango]

news/180.feature

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
allow to set lazy to false, to suppress the loading="lazy" attribute
2+
[MrTango]

plone/namedfile/picture.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,19 @@ def get_scale_width(self, scale):
4747
return scale_info[0]
4848

4949
def create_picture_tag(
50-
self, sourceset, attributes, uid=None, fieldname=None, resolve_urls=False
50+
self,
51+
sourceset,
52+
attributes,
53+
uid=None,
54+
fieldname=None,
55+
resolve_urls=False,
56+
lazy=True,
5157
):
5258
"""Converts the img tag to a picture tag with picture_variant definition"""
5359
width = None
5460
height = None
61+
target_width = None
62+
sizes = ""
5563
src = attributes.get("src")
5664
if not uid and not src:
5765
raise TypeError("Either uid or attributes['src'] need to be given.")
@@ -68,6 +76,7 @@ def create_picture_tag(
6876
for i, source in enumerate(sourceset):
6977
target_scale = source["scale"]
7078
media = source.get("media")
79+
sizes = source.get("sizes")
7180

7281
additional_scales = source.get("additionalScales", None)
7382
if additional_scales is None:
@@ -78,6 +87,8 @@ def create_picture_tag(
7887
source_srcset = []
7988
for scale in source_scales:
8089
scale_width = self.get_scale_width(scale)
90+
if scale == target_scale:
91+
target_width = scale_width
8192
if not scale_width:
8293
logger.warning("No width found for scale %s.", scale)
8394
continue
@@ -86,13 +97,13 @@ def create_picture_tag(
8697
scale_obj = scale_view.scale(fieldname, scale, pre=True)
8798
scale_url = scale_obj.url
8899
else:
89-
# obj = self.resolve_uid_url(src)
90-
# scale_view = obj.unrestrictedTraverse("@@images", None)
91-
# scale_obj = scale_view.scale(fieldname, scale, pre=True)
92-
# scale_url = scale_obj.url
93100
scale_url = self.update_src_scale(src=src, scale=scale)
94101
source_srcset.append(f"{scale_url} {scale_width}w")
95-
source_tag = soup.new_tag("source", srcset=",\n".join(source_srcset))
102+
if not sizes:
103+
sizes = f"(min-width: 576px) {target_width}px, 98vw"
104+
source_tag = soup.new_tag(
105+
"source", srcset=",\n".join(source_srcset), sizes=sizes
106+
)
96107
if media:
97108
source_tag["media"] = media
98109
picture_tag.append(source_tag)
@@ -104,19 +115,14 @@ def create_picture_tag(
104115
width = scale_obj.width
105116
height = scale_obj.height
106117
else:
107-
# obj = self.resolve_uid_url(src)
108-
# scale_view = obj.unrestrictedTraverse("@@images", None)
109-
# scale_obj = scale_view.scale(fieldname, target_scale, pre=True)
110-
# scale_url = scale_obj.url
111-
# width = scale_obj.width
112-
# height = scale_obj.height
113118
scale_url = self.update_src_scale(src=src, scale=target_scale)
114119
img_tag = soup.new_tag("img", src=scale_url)
115120
for k, attr in attributes.items():
116121
if k in ["src", "srcset"]:
117122
continue
118123
img_tag.attrs[k] = attr
119-
img_tag["loading"] = "lazy"
124+
if lazy:
125+
img_tag["loading"] = "lazy"
120126
if width:
121127
img_tag["width"] = width
122128
if height:

plone/namedfile/scaling.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ def picture(
691691
alt=None,
692692
css_class=None,
693693
title=_marker,
694+
lazy=True,
694695
**kwargs,
695696
):
696697
img2picturetag = Img2PictureTag()
@@ -737,6 +738,7 @@ def picture(
737738
resolve_urls=True,
738739
uid=scale.context.UID(),
739740
fieldname=fieldname,
741+
lazy=lazy,
740742
).prettify()
741743

742744

plone/namedfile/tests/test_scaling.py

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ def patch_Img2PictureTag_picture_variants():
8888
"sourceset": [
8989
{
9090
"scale": "preview",
91-
"additionalScales": ["preview", "large", "larger"],
91+
"additionalScales": ["large", "larger"],
92+
"sizes": "(min-width: 576px) 350px, (min-width: 768px) 600px, 98vw",
9293
}
9394
],
9495
},
@@ -538,22 +539,93 @@ def testGetPictureTagByName(self, mock_uuid_to_object):
538539
mock_uuid_to_object.return_value = self.item
539540
tag = self.scaling.picture("image", picture_variant="medium")
540541
expected = """<picture>
541-
<source srcset="http://nohost/item/@@images/image-600-....png 600w,
542+
<source...srcset="http://nohost/item/@@images/image-600-....png 600w,
542543
http://nohost/item/@@images/image-400-....png 400w,
543544
http://nohost/item/@@images/image-800-....png 800w,
544545
http://nohost/item/@@images/image-1000-....png 1000w,
545-
http://nohost/item/@@images/image-1200-....png 1200w"/>
546+
http://nohost/item/@@images/image-1200-....png 1200w".../>
546547
<img...src="http://nohost/item/@@images/image-600-....png".../>
547548
</picture>"""
548549
self.assertTrue(_ellipsis_match(expected, tag.strip()))
550+
# The exact placement of the img tag attributes can differ, especially
551+
# with different beautifulsoup versions.
552+
# So check here that all attributes are present.
553+
self.assertIn('height="200"', tag)
554+
self.assertIn('loading="lazy"', tag)
555+
self.assertIn('title="foo"', tag)
556+
self.assertIn('width="200"', tag)
557+
self.assertIn('sizes="(min-width: 576px) 600px, 98vw"', tag)
558+
559+
@patch.object(
560+
plone.namedfile.scaling,
561+
"get_picture_variants",
562+
new=patch_Img2PictureTag_picture_variants,
563+
spec=True,
564+
)
565+
@patch.object(
566+
plone.namedfile.picture,
567+
"get_allowed_scales",
568+
new=patch_Img2PictureTag_allowed_scales,
569+
spec=True,
570+
)
571+
@patch.object(plone.namedfile.picture, "uuidToObject", spec=True)
572+
def testGetPictureTagByNameNotLazy(self, mock_uuid_to_object):
573+
ImageScaling._sizes = patch_Img2PictureTag_allowed_scales()
574+
mock_uuid_to_object.return_value = self.item
575+
tag = self.scaling.picture("image", picture_variant="medium", lazy=False)
576+
print(tag)
577+
expected = """<picture>
578+
<source...srcset="http://nohost/item/@@images/image-600-....png 600w,
579+
http://nohost/item/@@images/image-400-....png 400w,
580+
http://nohost/item/@@images/image-800-....png 800w,
581+
http://nohost/item/@@images/image-1000-....png 1000w,
582+
http://nohost/item/@@images/image-1200-....png 1200w".../>
583+
<img...src="http://nohost/item/@@images/image-600-....png".../>
584+
</picture>"""
585+
self.assertTrue(_ellipsis_match(expected, tag.strip()))
586+
# The exact placement of the img tag attributes can differ, especially
587+
# with different beautifulsoup versions.
588+
# So check here that all attributes are present.
589+
self.assertIn('height="200"', tag)
590+
self.assertNotIn('loading="lazy"', tag)
591+
self.assertIn('title="foo"', tag)
592+
self.assertIn('width="200"', tag)
593+
self.assertIn('sizes="(min-width: 576px) 600px, 98vw"', tag)
549594

595+
@patch.object(
596+
plone.namedfile.scaling,
597+
"get_picture_variants",
598+
new=patch_Img2PictureTag_picture_variants,
599+
spec=True,
600+
)
601+
@patch.object(
602+
plone.namedfile.picture,
603+
"get_allowed_scales",
604+
new=patch_Img2PictureTag_allowed_scales,
605+
spec=True,
606+
)
607+
@patch.object(plone.namedfile.picture, "uuidToObject", spec=True)
608+
def testGetPictureTagCustomSizes(self, mock_uuid_to_object):
609+
ImageScaling._sizes = patch_Img2PictureTag_allowed_scales()
610+
mock_uuid_to_object.return_value = self.item
611+
tag = self.scaling.picture("image", picture_variant="small")
612+
expected = """<picture>
613+
<source...srcset="http://nohost/item/@@images/image-400-....png 400w,
614+
http://nohost/item/@@images/image-800-....png 800w,
615+
http://nohost/item/@@images/image-1000-....png 1000w".../>
616+
<img...src="http://nohost/item/@@images/image-400-....png".../>
617+
</picture>"""
618+
self.assertTrue(_ellipsis_match(expected, tag.strip()))
550619
# The exact placement of the img tag attributes can differ, especially
551620
# with different beautifulsoup versions.
552621
# So check here that all attributes are present.
553622
self.assertIn('height="200"', tag)
554623
self.assertIn('loading="lazy"', tag)
555624
self.assertIn('title="foo"', tag)
556625
self.assertIn('width="200"', tag)
626+
self.assertIn(
627+
'sizes="(min-width: 576px) 350px, (min-width: 768px) 600px, 98vw"', tag
628+
)
557629

558630
@patch.object(
559631
plone.namedfile.scaling,
@@ -579,11 +651,11 @@ def testGetPictureTagWithAltAndTitle(self, mock_uuid_to_object):
579651
)
580652
base = self.item.absolute_url()
581653
expected = f"""<picture>
582-
<source srcset="{base}/@@images/image-600-....png 600w,
654+
<source...srcset="{base}/@@images/image-600-....png 600w,
583655
{base}/@@images/image-400-....png 400w,
584656
{base}/@@images/image-800-....png 800w,
585657
{base}/@@images/image-1000-....png 1000w,
586-
{base}/@@images/image-1200-....png 1200w"/>
658+
{base}/@@images/image-1200-....png 1200w".../>
587659
<img...src="{base}/@@images/image-600-....png".../>
588660
</picture>"""
589661
self.assertTrue(_ellipsis_match(expected, tag.strip()))

0 commit comments

Comments
 (0)