Skip to content

Commit

Permalink
fix: Add serializer for slate and html blocks - refs #282435
Browse files Browse the repository at this point in the history
  • Loading branch information
dobri1408 authored Jan 30, 2025
1 parent 2c7dac2 commit e7d6875
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 2 deletions.
126 changes: 124 additions & 2 deletions eea/volto/policy/restapi/blocks.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
""" block-related utils """

"""
Serializers and Deserializers for the blocks of the EEA
"""
import copy
from urllib.parse import urlparse
from bs4 import BeautifulSoup
from plone import api
from plone.restapi.behaviors import IBlocks
from plone.restapi.interfaces import IBlockFieldSerializationTransformer
from plone.restapi.serializer.blocks import (
SlateBlockSerializerBase,
uid_to_url,
)
from plone.restapi.deserializer.utils import path2uid
from zope.component import adapter
from zope.interface import implementer
from zope.publisher.interfaces.browser import IBrowserRequest
Expand All @@ -18,6 +26,120 @@
EEAVersionsView = None


def getLink(path):
"""
Get link
"""

URL = urlparse(path)

if URL.netloc.startswith("localhost") and URL.scheme:
return path.replace(URL.scheme + "://" + URL.netloc, "")
return path


class HTMLBlockDeserializerBase:
"""
HTML block Deserializer for the hrefs and src
"""
order = 100
block_type = "html"

def __init__(self, context, request):
self.context = context
self.request = request

def __call__(self, block):
raw_html = block.get("html", "")

if not raw_html:
return block

# Parse the HTML using BeautifulSoup
soup = BeautifulSoup(raw_html, "html.parser")

# Resolve all <a> and <img> tags to UIDs
for tag in soup.find_all(["a", "img"]):
if tag.name == "a" and tag.has_attr("href"):

tag["href"] = path2uid(context=self.context, link=tag["href"])

elif tag.name == "img" and tag.has_attr("src"):
tag["src"] = path2uid(context=self.context, link=tag["src"])

# Serialize the modified HTML back into the block
block["html"] = str(soup)
return block

def _convert_to_uid(self, url, is_image=False):
"""
Convert relative or absolute URLs into resolve UID links.
"""
uid = path2uid(self.context, url)
if uid:
return f"/resolveuid/{uid}"
return url


class HTMLBlockSerializerBase:
"""
HTML block Serializer for the hrefs and src
"""
order = 9999
block_type = "html"

def __init__(self, context, request):
self.context = context
self.request = request

def __call__(self, block):
block_serializer = copy.deepcopy(block)
raw_html = block_serializer.get("html", "")

if not raw_html:
return block

# Parse the HTML using BeautifulSoup
soup = BeautifulSoup(raw_html, "html.parser")

# Resolve all <a> and <img> tags
for tag in soup.find_all(["a", "img"]):
if tag.name == "a" and tag.has_attr("href"):
tag["href"] = self._resolve_uid(tag["href"])
elif tag.name == "img" and tag.has_attr("src"):
tag["src"] = self._resolve_uid(tag["src"], is_image=True)

# Serialize the modified HTML back into the block
block_serializer["html"] = str(soup)
return block_serializer

def _resolve_uid(self, url, is_image=False):
"""
Convert resolve UID URLs into relative links.
If the URL points to an image, append /@@download/image.
"""
if "/resolveuid/" in url:
resolved_url = uid_to_url(url)
if is_image and resolved_url:
return f"{resolved_url}/@@download/image"
return resolved_url or url
return url


class SlateBlockSerializer(SlateBlockSerializerBase):
"""SlateBlockSerializerBase."""

block_type = "slate"

def handle_img(self, child):
"Serializer for the imgs"
if child.get("url"):
if "resolveuid" in child["url"]:
url = uid_to_url(child["url"])
url = "%s/@@download/image" % url
child["url"] = url


@implementer(IBlockFieldSerializationTransformer)
@adapter(IBlocks, IBrowserRequest)
class RestrictedBlockSerializationTransformer:
Expand Down
14 changes: 14 additions & 0 deletions eea/volto/policy/restapi/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@
<subscriber
provides="plone.restapi.interfaces.IBlockFieldSerializationTransformer"
factory=".blocks.RestrictedBlockSerializationTransformer" />
<subscriber
provides="plone.restapi.interfaces.IBlockFieldSerializationTransformer"
factory=".blocks.SlateBlockSerializer"
for="plone.restapi.behaviors.IBlocks zope.publisher.interfaces.browser.IBrowserRequest"/>
<!-- Deserializations -->
<subscriber
provides="plone.restapi.interfaces.IBlockFieldDeserializationTransformer"
factory=".blocks.HTMLBlockDeserializerBase"
for="plone.restapi.behaviors.IBlocks zope.publisher.interfaces.browser.IBrowserRequest"/>
<subscriber
provides="plone.restapi.interfaces.IBlockFieldSerializationTransformer"
factory=".blocks.HTMLBlockSerializerBase"
for="plone.restapi.behaviors.IBlocks zope.publisher.interfaces.browser.IBrowserRequest"/>


<subscriber
provides="plone.restapi.interfaces.IBlockFieldSerializationTransformer"
Expand Down

0 comments on commit e7d6875

Please sign in to comment.