Convert a rich text editor filled with images into an array of image objects -- dang thats cool.

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.

helpers.html (macro-file)
{%- 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!