From ffe274ad7e0aa4ef5f4f08486190fbd4fa100d66 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Thu, 22 Jun 2023 16:53:50 +0530 Subject: [PATCH 1/9] refactor: use image scales from restapi refs#254622 --- src/PreviewImage.js | 15 ++++++------ src/blocks/Item/Edit.jsx | 3 ++- src/blocks/Item/Item.jsx | 29 +++++++++++++++++++--- src/blocks/Item/View.jsx | 3 ++- src/helpers.js | 52 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/PreviewImage.js b/src/PreviewImage.js index bcda9e34..86f2ba23 100644 --- a/src/PreviewImage.js +++ b/src/PreviewImage.js @@ -2,13 +2,10 @@ import React from 'react'; import { Image } from 'semantic-ui-react'; -import { flattenToAppURL } from '@plone/volto/helpers'; +import { getImageScaleParams } from '@eeacms/volto-listing-block/helpers'; import DefaultImageSVG from './default-image.svg'; -const getSrc = (item, size) => - flattenToAppURL(`${item['@id']}/@@images/${item.image_field}/${size}`); - // TODO: do we still need volto-depiction compatibility? // import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/default-image.svg'; // const makeImage = (item, style) => ( @@ -40,15 +37,15 @@ function PreviewImage(props) { label, ...rest } = props; - const src = preview_image?.[0] - ? getSrc(preview_image[0], size) + const params = preview_image?.[0] + ? getImageScaleParams(preview_image?.[0], size) : item.image_field - ? getSrc(item, size) + ? getImageScaleParams(item, size) : DefaultImageSVG; return ( {item.title} ); } diff --git a/src/blocks/Item/Edit.jsx b/src/blocks/Item/Edit.jsx index d84a5c0d..d6ab244e 100644 --- a/src/blocks/Item/Edit.jsx +++ b/src/blocks/Item/Edit.jsx @@ -27,6 +27,7 @@ const Edit = (props) => { properties, onChangeBlock, onSelectBlock, + id, } = props; const { description } = data; const schema = React.useMemo(() => getSchema(props), [props]); @@ -47,7 +48,7 @@ const Edit = (props) => { return ( <> - + { + if (imageUrl) { + dispatch(getContent(flattenToAppURL(imageUrl), null, block)); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [imageUrl]); + + const imageParams = useSelector( + (state) => state.content.subrequests[block]?.data?.image, + ); + + const scaledImage = setImageSize(imageUrl, imageParams, imageSize); + + const image = getFieldURL(imageUrl); return ( {assetType === 'image' && image && ( )} {assetType === 'icon' && icon && ( diff --git a/src/blocks/Item/View.jsx b/src/blocks/Item/View.jsx index 9357ba61..29855e41 100644 --- a/src/blocks/Item/View.jsx +++ b/src/blocks/Item/View.jsx @@ -9,10 +9,11 @@ export const serializeText = (text) => { }; const View = (props) => { - const { data = {} } = props; + const { data = {}, id } = props; return ( ); diff --git a/src/helpers.js b/src/helpers.js index 0954929f..ea0badec 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -17,3 +17,55 @@ export const getFieldURL = (data) => { if (isString(url) && isInternalURL(url)) return flattenToAppURL(url); return url; }; + +export function getImageScaleParams(image, size) { + const imageScale = size || 'preview'; + if (isInternalURL(image['@id'])) { + if (image?.image_scales?.[image?.image_field]) { + const scale = + image.image_scales[image.image_field]?.[0].scales[imageScale] || + image.image_scales[image.image_field]?.[0]; + + const url = flattenToAppURL(`${image['@id']}/${scale?.download}`); + const width = scale?.width; + const height = scale?.height; + + return { + url, + width, + height, + }; + } else { + return flattenToAppURL( + `${image['@id']}/@@images/${image.image_field}/${imageScale}`, + ); + } + } else { + return image['@id']; + } +} + +export const setImageSize = (image, imageParams, size) => { + const imageScaled = isInternalURL(image) + ? (() => { + if (imageParams) { + const { scales = null } = imageParams; + if (scales) { + if (size === 'big') return scales.huge; + if (size === 'medium') return scales.large; + if (size === 'small') return scales.mini; + if (size === 'preview') return scales.preview; + if (size === 'tiny') return scales.thumb; + return scales.large; + } else + return { + download: imageParams?.download, + width: imageParams?.width, + height: imageParams?.height, + }; + } + })() + : { download: image, width: '100%', height: '100%' }; + + return imageScaled; +}; From 8bb31c1f098d5c847e2c62b00e61842b51230e9b Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Thu, 22 Jun 2023 17:59:55 +0530 Subject: [PATCH 2/9] remove: old getTeaserImageUrl method in favour of scales --- src/blocks/Teaser/utils.js | 18 --------- src/blocks/Teaser/utils.test.js | 65 --------------------------------- src/helpers.js | 5 ++- 3 files changed, 4 insertions(+), 84 deletions(-) delete mode 100644 src/blocks/Teaser/utils.js delete mode 100644 src/blocks/Teaser/utils.test.js diff --git a/src/blocks/Teaser/utils.js b/src/blocks/Teaser/utils.js deleted file mode 100644 index f7f99589..00000000 --- a/src/blocks/Teaser/utils.js +++ /dev/null @@ -1,18 +0,0 @@ -import { isInternalURL } from '@plone/volto/helpers'; -import config from '@plone/volto/registry'; - -export function getTeaserImageURL(href, image) { - const imageScale = - config.blocks.blocksConfig['teaser'].imageScale || 'preview'; - if (image) { - if (isInternalURL(image['@id'])) { - return `${image['@id']}/@@images/image/${imageScale}`; - } else { - return image['@id']; - } - } else { - return `${href['@id']}/@@images/${ - href.image_field || 'preview_image' - }/${imageScale}`; - } -} diff --git a/src/blocks/Teaser/utils.test.js b/src/blocks/Teaser/utils.test.js deleted file mode 100644 index 9a68288e..00000000 --- a/src/blocks/Teaser/utils.test.js +++ /dev/null @@ -1,65 +0,0 @@ -import { getTeaserImageURL } from './utils'; -import { isInternalURL } from '@plone/volto/helpers'; -import config from '@plone/volto/registry'; - -beforeAll(() => { - config.blocks.blocksConfig = { - ...config.blocks.blocksConfig, - teaser: { - ...config.blocks.blocksConfig.teaser, - imageScale: 'test_scale', - }, - }; -}); - -jest.mock('@plone/volto/helpers', () => ({ - isInternalURL: jest.fn(), -})); - -describe('test', () => { - it('should return the scaled image URL if image is provided and is an internal URL', () => { - const image = { - '@id': 'internalURL', - }; - isInternalURL.mockReturnValue(true); - const result = getTeaserImageURL('', image); - - expect(isInternalURL).toHaveBeenCalledWith('internalURL'); - expect(result).toBe(`internalURL/@@images/image/test_scale`); - }); - - it('should return the image URL if image is provided and is not an internal URL', () => { - const image = { - '@id': 'internalURL', - }; - isInternalURL.mockReturnValue(false); - const result = getTeaserImageURL('', image); - - expect(isInternalURL).toHaveBeenCalledWith('internalURL'); - expect(result).toBe('internalURL'); - }); - - it('should return the default image URL if no image is provided without image_field', () => { - const href = { - '@id': 'https://example.com/item', - image_field: null, - }; - const result = getTeaserImageURL(href, ''); - - expect(result).toBe( - 'https://example.com/item/@@images/preview_image/test_scale', - ); - }); - - it('should return the default image URL if no image is provided with image_field', () => { - const href = { - '@id': 'https://example.com/item', - image_field: 'mock_image', - }; - const result = getTeaserImageURL(href, ''); - - expect(result).toBe( - 'https://example.com/item/@@images/mock_image/test_scale', - ); - }); -}); diff --git a/src/helpers.js b/src/helpers.js index ea0badec..c89daf5a 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,6 +1,7 @@ import isArray from 'lodash/isArray'; import isObject from 'lodash/isObject'; import isString from 'lodash/isString'; +import config from '@plone/volto/registry'; import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers'; export const getFieldURL = (data) => { @@ -19,7 +20,9 @@ export const getFieldURL = (data) => { }; export function getImageScaleParams(image, size) { - const imageScale = size || 'preview'; + const imageScale = + config.blocks.blocksConfig['teaser'].imageScale || size || 'preview'; //listings use preview scale + if (isInternalURL(image['@id'])) { if (image?.image_scales?.[image?.image_field]) { const scale = From e408c2fae2a6bb8fbdd0d637b2496643a6c36b42 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Thu, 22 Jun 2023 18:28:14 +0530 Subject: [PATCH 3/9] fix: backwards compatibility when no scales are present --- src/PreviewImage.js | 2 +- src/helpers.js | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/PreviewImage.js b/src/PreviewImage.js index 86f2ba23..4bd14b50 100644 --- a/src/PreviewImage.js +++ b/src/PreviewImage.js @@ -45,7 +45,7 @@ function PreviewImage(props) { return ( {item.title} Date: Thu, 22 Jun 2023 20:17:35 +0530 Subject: [PATCH 4/9] fix: tests --- src/helpers.js | 2 +- src/helpers.test.js | 107 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/helpers.test.js diff --git a/src/helpers.js b/src/helpers.js index f70f023c..e86532bf 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -26,7 +26,7 @@ export function getImageScaleParams(image, size) { if (isInternalURL(image['@id'])) { if (image?.image_scales?.[image?.image_field]) { const scale = - image.image_scales[image.image_field]?.[0].scales[imageScale] || + image.image_scales[image.image_field]?.[0].scales?.[imageScale] || image.image_scales[image.image_field]?.[0]; const download = flattenToAppURL(`${image['@id']}/${scale?.download}`); diff --git a/src/helpers.test.js b/src/helpers.test.js new file mode 100644 index 00000000..a223f8d5 --- /dev/null +++ b/src/helpers.test.js @@ -0,0 +1,107 @@ +import { getImageScaleParams } from './helpers'; +import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers'; +import config from '@plone/volto/registry'; + +beforeAll(() => { + config.blocks.blocksConfig = { + ...config.blocks.blocksConfig, + teaser: { + ...config.blocks.blocksConfig.teaser, + imageScale: 'test_scale', + }, + }; +}); + +jest.mock('@plone/volto/helpers', () => ({ + isInternalURL: jest.fn(), + flattenToAppURL: jest.fn(), +})); + +describe('test', () => { + it('should return the scaled image URL if image scales are provided and is an internal URL', () => { + const image = { + '@id': 'internalURL', + image_field: 'test_field', + image_scales: { + test_field: [ + { + download: '/en/@@images/test_field-example.jpg', + scales: { + test_scale: { + download: '/en/@@images/test_field-example-123.jpg', + }, + }, + }, + ], + }, + }; + isInternalURL.mockReturnValue(true); + flattenToAppURL.mockReturnValue('/en/@@images/test_field-example-123.jpg'); + const result = getImageScaleParams(image); + + expect(isInternalURL).toHaveBeenCalledWith('internalURL'); + expect(result.download).toBe(`/en/@@images/test_field-example-123.jpg`); + }); + + it('should return the default scaled image URL if image scales are not provided', () => { + const image = { + '@id': 'internalURL', + image_field: 'test_field', + image_scales: { + test_field: [ + { + download: '/en/@@images/test_field-example.jpg', + }, + ], + }, + }; + isInternalURL.mockReturnValue(true); + flattenToAppURL.mockReturnValue('/en/@@images/test_field-example.jpg'); + const result = getImageScaleParams(image); + + expect(isInternalURL).toHaveBeenCalledWith('internalURL'); + expect(result.download).toBe(`/en/@@images/test_field-example.jpg`); + }); + + it('should return the image URL if image is provided and is not an internal URL', () => { + const image = { + '@id': 'internalURL', + }; + isInternalURL.mockReturnValue(false); + const result = getImageScaleParams(image); + + expect(isInternalURL).toHaveBeenCalledWith('internalURL'); + expect(result.download).toBe('internalURL'); + }); + + // ensure backward compatibilty tests + it('should return the default image URL if no image is provided without image_field', () => { + const image = { + '@id': 'internalURL', + image_field: null, + }; + isInternalURL.mockReturnValue(true); + flattenToAppURL.mockReturnValue( + 'internalURL/@@images/preview_image/test_scale', + ); + const result = getImageScaleParams(image); + + expect(result.download).toBe( + 'internalURL/@@images/preview_image/test_scale', + ); + }); + + it('should return the default image URL if no image scales are provided with image_field', () => { + const image = { + '@id': 'internalURL', + image_field: 'mock_image', + image_scales: null, + }; + isInternalURL.mockReturnValue(true); + const result = getImageScaleParams(image); + + expect(result.download).toBe( + 'internalURL/@@images/preview_image/test_scale', + ); + }); +}); From 1d25a39e281a5daf9e981c132c46b1c3a0cd982e Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Tue, 27 Jun 2023 22:13:13 +0530 Subject: [PATCH 5/9] fix: ege case --- src/helpers.js | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/helpers.js b/src/helpers.js index e86532bf..86eeae5f 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -22,34 +22,35 @@ export const getFieldURL = (data) => { export function getImageScaleParams(image, size) { const imageScale = config.blocks.blocksConfig['teaser'].imageScale || size || 'preview'; //listings use preview scale + if (image) { + if (isInternalURL(image['@id'])) { + if (image?.image_scales?.[image?.image_field]) { + const scale = + image.image_scales[image.image_field]?.[0].scales?.[imageScale] || + image.image_scales[image.image_field]?.[0]; - if (isInternalURL(image['@id'])) { - if (image?.image_scales?.[image?.image_field]) { - const scale = - image.image_scales[image.image_field]?.[0].scales?.[imageScale] || - image.image_scales[image.image_field]?.[0]; + const download = flattenToAppURL(`${image['@id']}/${scale?.download}`); + const width = scale?.width; + const height = scale?.height; - const download = flattenToAppURL(`${image['@id']}/${scale?.download}`); - const width = scale?.width; - const height = scale?.height; - - return { - download, - width, - height, - }; - //fallback if we do not have scales + return { + download, + width, + height, + }; + //fallback if we do not have scales + } else { + return { + download: flattenToAppURL( + `${image['@id']}/@@images/${ + image.image_field || 'preview_image' + }/${imageScale}`, + ), + }; + } } else { - return { - download: flattenToAppURL( - `${image['@id']}/@@images/${ - image.image_field || 'preview_image' - }/${imageScale}`, - ), - }; + return { download: image['@id'] }; } - } else { - return { download: image['@id'] }; } } From 87dfab7a0a98a69f0466a13806c9d57203251604 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Thu, 29 Jun 2023 16:08:04 +0530 Subject: [PATCH 6/9] refactor: use getFieldUrl in getImageScales --- src/blocks/Item/Item.jsx | 24 ++++------------ src/blocks/Item/schema.js | 1 + src/helpers.js | 58 ++++++++++++++++++--------------------- 3 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/blocks/Item/Item.jsx b/src/blocks/Item/Item.jsx index 80a14692..b0ff59fe 100644 --- a/src/blocks/Item/Item.jsx +++ b/src/blocks/Item/Item.jsx @@ -1,9 +1,10 @@ -import { useEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; import cx from 'classnames'; import { Item as UiItem, Icon } from 'semantic-ui-react'; -import { getFieldURL, setImageSize } from '@eeacms/volto-listing-block/helpers'; -import { getContent } from '@plone/volto/actions'; +import { + getFieldURL, + getImageScaleParams, +} from '@eeacms/volto-listing-block/helpers'; + import { flattenToAppURL } from '@plone/volto/helpers'; function Item({ @@ -23,20 +24,7 @@ function Item({ image: imageUrl, ...props }) { - const dispatch = useDispatch(); - - useEffect(() => { - if (imageUrl) { - dispatch(getContent(flattenToAppURL(imageUrl), null, block)); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [imageUrl]); - - const imageParams = useSelector( - (state) => state.content.subrequests[block]?.data?.image, - ); - - const scaledImage = setImageSize(imageUrl, imageParams, imageSize); + const scaledImage = getImageScaleParams(imageUrl, imageSize); const image = getFieldURL(imageUrl); return ( diff --git a/src/blocks/Item/schema.js b/src/blocks/Item/schema.js index 0fa52129..95475931 100644 --- a/src/blocks/Item/schema.js +++ b/src/blocks/Item/schema.js @@ -35,6 +35,7 @@ export default ({ data }) => { image: { title: 'Image', widget: 'attachedimage', + selectedItemAttrs: ['image_field', 'image_scales', '@type'], }, imageSize: { title: 'Image size', diff --git a/src/helpers.js b/src/helpers.js index 86eeae5f..fdecd15d 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -21,15 +21,34 @@ export const getFieldURL = (data) => { export function getImageScaleParams(image, size) { const imageScale = - config.blocks.blocksConfig['teaser'].imageScale || size || 'preview'; //listings use preview scale + config.blocks.blocksConfig['teaser'].imageScale || size || 'preview'; + + if (isString(image)) + return isInternalURL(image) + ? flattenToAppURL(`${image}/@@images/image/${imageScale}`) + : image; + if (image) { - if (isInternalURL(image['@id'])) { + if (isInternalURL(getFieldURL(image))) { if (image?.image_scales?.[image?.image_field]) { const scale = image.image_scales[image.image_field]?.[0].scales?.[imageScale] || image.image_scales[image.image_field]?.[0]; - const download = flattenToAppURL(`${image['@id']}/${scale?.download}`); + const download = flattenToAppURL( + `${getFieldURL(image)}/${scale?.download}`, + ); + const width = scale?.width; + const height = scale?.height; + + return { + download, + width, + height, + }; + } else if (image?.image?.scales) { + const scale = image.image?.scales?.[imageScale] || image.image; + const download = flattenToAppURL(scale?.download); const width = scale?.width; const height = scale?.height; @@ -38,43 +57,18 @@ export function getImageScaleParams(image, size) { width, height, }; - //fallback if we do not have scales } else { + //fallback if we do not have scales return { download: flattenToAppURL( - `${image['@id']}/@@images/${ - image.image_field || 'preview_image' + `${getFieldURL(image)}/@@images/${ + image.image_field || 'image' }/${imageScale}`, ), }; } } else { - return { download: image['@id'] }; + return { download: getFieldURL(image) }; } } } - -export const setImageSize = (image, imageParams, size) => { - const imageScaled = isInternalURL(image) - ? (() => { - if (imageParams) { - const { scales = null } = imageParams; - if (scales) { - if (size === 'big') return scales.huge; - if (size === 'medium') return scales.large; - if (size === 'small') return scales.mini; - if (size === 'preview') return scales.preview; - if (size === 'tiny') return scales.thumb; - return scales.large; - } else - return { - download: imageParams?.download, - width: imageParams?.width, - height: imageParams?.height, - }; - } - })() - : { download: image, width: '100%', height: '100%' }; - - return imageScaled; -}; From 55144639a422d601c85f45d3efdbe0c5ff9e7f12 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Thu, 20 Jul 2023 13:51:40 +0530 Subject: [PATCH 7/9] fix: url when string --- src/helpers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers.js b/src/helpers.js index fdecd15d..e6c01744 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -25,8 +25,8 @@ export function getImageScaleParams(image, size) { if (isString(image)) return isInternalURL(image) - ? flattenToAppURL(`${image}/@@images/image/${imageScale}`) - : image; + ? { download: flattenToAppURL(`${image}/@@images/image/${imageScale}`) } + : { download: image }; if (image) { if (isInternalURL(getFieldURL(image))) { From a0ae1246eec777d62af4f17ac30310f3e3499a29 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Fri, 21 Jul 2023 15:25:59 +0530 Subject: [PATCH 8/9] fix: preview_image rendering when no image_scales --- src/PreviewImage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PreviewImage.js b/src/PreviewImage.js index 4bd14b50..1c8ea4f5 100644 --- a/src/PreviewImage.js +++ b/src/PreviewImage.js @@ -39,7 +39,7 @@ function PreviewImage(props) { } = props; const params = preview_image?.[0] ? getImageScaleParams(preview_image?.[0], size) - : item.image_field + : item ? getImageScaleParams(item, size) : DefaultImageSVG; From 87d6f9c5c375b79af7138d64705a6adf5ea08ee8 Mon Sep 17 00:00:00 2001 From: nileshgulia1 Date: Tue, 7 Nov 2023 19:50:24 +0530 Subject: [PATCH 9/9] fix tests --- src/blocks/Listing/item-templates/ItemTemplates.test.jsx | 1 + src/blocks/Listing/item-templates/SearchItemTemplate.test.jsx | 3 ++- .../item-templates/__snapshots__/ItemTemplates.test.jsx.snap | 2 +- .../__snapshots__/SearchItemTemplate.test.jsx.snap | 4 ++-- src/helpers.js | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/blocks/Listing/item-templates/ItemTemplates.test.jsx b/src/blocks/Listing/item-templates/ItemTemplates.test.jsx index ccdc9ab0..90ce7207 100644 --- a/src/blocks/Listing/item-templates/ItemTemplates.test.jsx +++ b/src/blocks/Listing/item-templates/ItemTemplates.test.jsx @@ -14,6 +14,7 @@ describe('ItemTemplates', () => { description: 'Default listing description', meta: 'Default listing meta', EffectiveDate: '2023-10-05T08:21:00+02:00', + url: '/my-item-url', }; const itemModel = { diff --git a/src/blocks/Listing/item-templates/SearchItemTemplate.test.jsx b/src/blocks/Listing/item-templates/SearchItemTemplate.test.jsx index 71520fac..3e218d12 100644 --- a/src/blocks/Listing/item-templates/SearchItemTemplate.test.jsx +++ b/src/blocks/Listing/item-templates/SearchItemTemplate.test.jsx @@ -2,12 +2,13 @@ import React from 'react'; import renderer from 'react-test-renderer'; import { SearchItemLayout } from './SearchItemTemplate'; -describe('SimpleItemTemplates', () => { +describe('SearchItemTemplates', () => { it('renders correctly', () => { const item = { title: 'Search listing title', description: 'Search listing description', meta: 'Search listing meta', + url: '/my-item-url', }; const itemModel = { diff --git a/src/blocks/Listing/item-templates/__snapshots__/ItemTemplates.test.jsx.snap b/src/blocks/Listing/item-templates/__snapshots__/ItemTemplates.test.jsx.snap index 306b94ba..b6080602 100644 --- a/src/blocks/Listing/item-templates/__snapshots__/ItemTemplates.test.jsx.snap +++ b/src/blocks/Listing/item-templates/__snapshots__/ItemTemplates.test.jsx.snap @@ -16,7 +16,7 @@ exports[`ItemTemplates renders correctly 1`] = ` Default listing title
@@ -21,7 +21,7 @@ exports[`SimpleItemTemplates renders correctly 1`] = ` Search listing title
{ export function getImageScaleParams(image, size) { const imageScale = - config.blocks.blocksConfig['teaser'].imageScale || size || 'preview'; + config.blocks.blocksConfig['teaser']?.imageScale || size || 'preview'; if (isString(image)) return isInternalURL(image)