Overview
All too often I find that clients want some kind of image gallery to be hosted on dynamic pages. On the surface this doesn't seem like that big of a deal. But in practice this kind of request can become quite unwieldily very quickly -- to the beginning HubSpot developer setting this up could mean creating an image field for each image allowed in the gallery. WEEELLLPPPP. Aside from being a rigid code design that will inevitably lead to a content team's frustration -- this also will create a potentially HUGE hubdb table.
Solution
Use a single Rich Text Editor(RTE) to house all of your images and parse them into image objects using a badass macro and some hubl know-how.
{%- macro split_images(rte) -%}
{# create blank array #}
{% set images_array = []%}
{# split apart your images in RTE #}
{% set images = rte|split('<img') %}
{# Loop through images #}
{% for image in images %}
{# Create image obj #}
{% set image_obj = {
src:"",
alt:""
}%}
{# join the image obj together and split apart at spaces #}
{% set image_temp = image|join('')|split(' ')%}
{# Loop through temp image obj and look for src field #}
{% for item in image_temp %}
{% if item is string_containing "src" %}
{# append src to final image_obj.src #}
{% do image_obj.update({src: item|replace('src=','')|replace('"','')})%}
{% endif %}
{% endfor %}
{# configure image alt string #}
{% set image_alt_temp = image|join('')|split('"')%}
{# helper var to help determine if loop is the actual alt text #}
{% set alt_text = {text: "", is_alt: false} %}
{# Loop thrpough alt text obj and add alt to image_obj.alt #}
{% for item in image_alt_temp %}
{% if alt_text.is_alt %}
{% do alt_text.update({text: item }) %}
{% do alt_text.update({is_alt: false }) %}
{% do image_obj.update({alt: alt_text.text}) %}
{% endif %}
{% if item is string_containing "alt" %}
{% do alt_text.update({is_alt: true})%}
{% endif %}
{% endfor %}
{# append current image_obj to images_array#}
{% do images_array.append(image_obj) %}
{% endfor %}
{# return image array #}
{#
Note that hubl is a templating language.
This means that if you intend to turn this into a gallery
you would want to pass this array into an additional macro
that actually builds the gallery. You will not be able
to call this macro and expect it to return anything other
than a string.
In other words. If you want to pass an actual array into
another macro you need to call that macro here and not in
the file which calls this macro.
In other...other words replace: {{images_array}}
with a new macro that builds the gallery and takes
an array as an argument.
{{ build_gallery(images_array) }}
#}
{{images_array}}
{% endmacro %}
As noted in the code snippet -- this macro is only intended to parse the images in the RTE into an array of image objects. This will not actually build anything out of that array.
If you want to manipulate the array you will need to pass the array directly into an additional macro that does the the manipulating directly from this macro.
Limitations
The only caveat with this approach is that RTE's in HubDB have a 65,000 character limit. The average image tag is about 200-400 characters long so plan on fitting roughly 150-250 images in each RTE. Plan accordingly and know what your client wants.
As always -- if you have any questions reach out on the HubSpot dev slack or reach out to me directly on linkedIn!
Happy building!