Skip to content

Commit

Permalink
Merge pull request #113 from plone/pre-scale
Browse files Browse the repository at this point in the history
Call new pre_scale and get_or_generate from plone.scale.
  • Loading branch information
mauritsvanrees authored Jun 9, 2022
2 parents 1a340ae + 26ce3a8 commit 30f59c5
Show file tree
Hide file tree
Showing 12 changed files with 969 additions and 226 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ include
lib
parts
requirements-*-mxdev.txt
sources/
2 changes: 2 additions & 0 deletions news/113.feature.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Creating a tag no longer generates the actual scale.
[maurits]
5 changes: 5 additions & 0 deletions news/113.feature.2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Add ``@@images-test`` page for Editors.
This shows various variants from the image field of the current context.
It shows a list of stored scales.
It allows purging the stored scales.
[maurits]
5 changes: 5 additions & 0 deletions news/113.feature.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Add picture method to to ImageScaling and include it in @@image-test.
Picture tags only work on Plone 6, with several other branches for picture variants merged.
See `plip-image-srcsets.cfg <https://github.com/plone/buildout.coredev/blob/6.0/plips/plip-image-srcsets.cfg>`_.
If not available (like on Plone 5.2), an ordinary image tag is created.
[MrTango]
143 changes: 143 additions & 0 deletions plone/namedfile/picture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import logging
import re

from plone.namedfile.interfaces import IAvailableSizes
from plone.app.uuid.utils import uuidToObject
from plone.registry.interfaces import IRegistry
from zope.component import getUtility
from zope.component import queryUtility
from bs4 import BeautifulSoup

try:
from plone.base.interfaces import IImagingSchema
except ImportError:
from Products.CMFPlone.interfaces.controlpanel import IImagingSchema


logger = logging.getLogger("plone.outputfilter.picture_variant")
appendix_re = re.compile("^(.*)([?#].*)$")
resolveuid_re = re.compile("^[./]*resolve[Uu]id/([^/]*)/?(.*)$")


def get_allowed_scales():
sizes_util = queryUtility(IAvailableSizes)
if sizes_util is None:
return {}
sizes = sizes_util()
if sizes is None:
return {}
return sizes


def get_picture_variants():
registry = getUtility(IRegistry)
settings = registry.forInterface(IImagingSchema, prefix="plone", check=False)
return getattr(settings, "picture_variants", {})


class Img2PictureTag(object):
def get_scale_name(self, scale_line):
parts = scale_line.split(" ")
return parts and parts[0] or ""

def get_scale_width(self, scale):
"""get width from allowed_scales line
large 800:65536
"""
allowed_scales = get_allowed_scales()
scale_info = allowed_scales.get(scale)
return scale_info[0]

def create_picture_tag(
self, sourceset, attributes, uid=None, fieldname=None, resolve_urls=False
):
"""Converts the img tag to a picture tag with picture_variant definition"""
width = None
height = None
src = attributes.get("src")
if not uid and not src:
raise TypeError("Either uid or attributes['src'] need to be given.")
soup = BeautifulSoup("", "html.parser")
allowed_scales = get_allowed_scales()
if uid:
obj = uuidToObject(uid)
else:
obj = self.resolve_uid_url(src)
picture_tag = soup.new_tag("picture")
css_classes = attributes.get("class", [])
if "captioned" in css_classes:
picture_tag["class"] = "captioned"
for i, source in enumerate(sourceset):
target_scale = source["scale"]
media = source.get("media")

additional_scales = source.get("additionalScales", None)
if additional_scales is None:
additional_scales = [
self.get_scale_name(s) for s in allowed_scales if s != target_scale
]
source_scales = [target_scale] + additional_scales
source_srcset = []
for scale in source_scales:
if resolve_urls and obj:
scale_view = obj.unrestrictedTraverse("@@images", None)
scale_obj = scale_view.scale(fieldname, scale, pre=True)
scale_url = scale_obj.url
else:
# obj = self.resolve_uid_url(src)
# scale_view = obj.unrestrictedTraverse("@@images", None)
# scale_obj = scale_view.scale(fieldname, scale, pre=True)
# scale_url = scale_obj.url
scale_url = self.update_src_scale(src=src, scale=scale)
scale_width = self.get_scale_width(scale)
source_srcset.append("{0} {1}w".format(scale_url, scale_width))
source_tag = soup.new_tag("source", srcset=",\n".join(source_srcset))
if media:
source_tag["media"] = media
picture_tag.append(source_tag)
if i == len(sourceset) - 1:
if resolve_urls and obj:
scale_view = obj.unrestrictedTraverse("@@images", None)
scale_obj = scale_view.scale(fieldname, target_scale, pre=True)
scale_url = scale_obj.url
width = scale_obj.width
height = scale_obj.height
else:
# obj = self.resolve_uid_url(src)
# scale_view = obj.unrestrictedTraverse("@@images", None)
# scale_obj = scale_view.scale(fieldname, target_scale, pre=True)
# scale_url = scale_obj.url
# width = scale_obj.width
# height = scale_obj.height
scale_url = self.update_src_scale(src=src, scale=target_scale)
img_tag = soup.new_tag("img", src=scale_url)
for k, attr in attributes.items():
if k in ["src", "srcset"]:
continue
img_tag.attrs[k] = attr
img_tag["loading"] = "lazy"
if width:
img_tag["width"] = width
if height:
img_tag["height"] = height
picture_tag.append(img_tag)
return picture_tag

def resolve_uid_url(self, href):
obj = None
subpath = href
match = resolveuid_re.match(subpath)
if match is not None:
uid, _subpath = match.groups()
obj = uuidToObject(uid)
return obj

def update_src_scale(self, src, scale):
parts = src.split("/")
if "." in parts[-1]:
field_name = parts[-1].split("-")[0]
src_scale = "/".join(parts[:-1]) + "/{0}/{1}".format(field_name, scale)
src_scale
else:
src_scale = "/".join(parts[:-1]) + "/{}".format(scale)
return src_scale
Loading

0 comments on commit 30f59c5

Please sign in to comment.