Insights

How To Setup Image Extensions For Sitecore Scriban Templates

Introduction

Scriban templates are incredibly easy to use and out-of-the-box are quite powerful on their own. What happens when we are presented with a problem that requires access to field details that are not accessible? We build an extension.

In our case, we needed to build a component, such as a banner, that showed one image for desktop and another for mobile. You can already produce a responsive image in a Scriban template, but showing two images and determining which to show based upon screen size. For example:

<picture>
    <source srcset="image-2.png" media="(min-width: 800px)">
    <img src="image-1.png" alt="" />
</picture>

In the above setup, we are showing image-1.png by default. When the screen size is larger than 800px wide, we substitute image-2.png.

It's all fine and dandy but to do this in a Scriban template we need to know the image url. If you've built a custom rendering and can control the model passed in, i.e. the o_model then you could build this functionality in.

What if you don't have that? What if we wanted something simpler that can be re-used across multiple Scriban templates. Let's build an image extension for Scriban templates.

Setup The Config

For the configuration file, we need to add the extension to the pipeline.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
    <sitecore>
        <pipelines>
        <generateScribanContext>
            <processor type="ABCCompany.Foundation.Extensions.Pipelines.ImageExtensions, ABCCompany.Foundation.Extensions" resolve="true" />
        </generateScribanContext>
        </pipelines>
    </sitecore>
</configuration>

Create The Image Model

Now for the purposes of this example, we've kept things pretty simple. You could obviously extend this even further if desired. Ultimately we're just trying to connect the ImageField attributes with our Scriban model.

using Sitecore.Data.Fields;
using System;

namespace ABCCompany.Foundation.Extensions.Models
{
    public class ImageInfo
    {
    public string src { get; set; }
    public string alt { get; set; }
    public string classname { get; set; }
    public ImageInfo() { }

    public ImageInfo(ImageField item)
    {
        try
        {
        src = Sitecore.Resources.Media.MediaManager.GetMediaUrl(item.MediaItem);

        }
        catch (Exception e)
        {
        src = null;
        }
        alt = item.Alt;
        classname = item.Class;
    }
    }
}

Build The Extension

With the model setup, all that's left to do is to create the extension that recognizes the scriban function we're setting up and applies the model to it such we can get the information we need.

using Scriban.Runtime;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.XA.Foundation.Abstractions;
using Sitecore.XA.Foundation.Scriban.Pipelines.GenerateScribanContext;
using System;
using ABCCompany.Foundation.Extensions.Models;

namespace ABCCompany.Foundation.Extensions.Pipelines
{
    public class ImageExtensions : IGenerateScribanContextProcessor
    {
    protected readonly IPageMode PageMode;
    private readonly IContext context;
    private delegate ImageInfo ImageInfoDelegate(Item item, object imageFieldName);

    public ImageExtensions(IPageMode pageMode, IContext context)
    {
        PageMode = pageMode;
        this.context = context;
    }

    // Setup the sc_image_info scriban function
    public void Process(GenerateScribanContextPipelineArgs args)
    {
        var imageInfo = new ImageInfoDelegate(GetImageInfo);
        args.GlobalScriptObject.Import("sc_image_info", (Delegate)imageInfo);
    }

    // Gather the information from the ImageField and apply it to the Model we want returned.
    public ImageInfo GetImageInfo(Item item, object field)
    {
        if (item == null
            || String.IsNullOrWhiteSpace((string)field)
            || item.Fields[(string)field] == null
            )
        {
        return null;
        }

        ImageField imgField = (ImageField)item.Fields[(string)field];
        if (imgField == null)
        {
        return null;
        }

        return new ImageInfo(imgField);
    }
    }

}

Returning null, while not always ideal, is ok in this case as we can easily detect it within the scriban script.

Scriban Code

Now with the extension in place, if we want to utilize it within a Rendering Varianty we can simply call it as follows:

{{- image = (sc_image_info i_item 'Image') -}}

When we want to access the attributes we can do so as shown below.

<img  src="{{image.src }}"  alt="{{image.alt}}" class="{{image.class}}"/>

This gives us a lot of options when we want to setup not only responsive image design but also for things like improving accessibility. Now obviously in this example I've only extracted a small portion of what you can retrieve from the ImageField so expanding upon it should be a no brainer. Have fun!

👋 Hey Sitecore Enthusiasts!

Sign up to our bi-weekly newsletter for a bite-sized curation of valuable insight from the Sitecore community.

What’s in it for you?

  • Stay up-to-date with the latest Sitecore news
  • New to Sitecore? Learn tips and tricks to help you navigate this powerful tool
  • Sitecore pro? Expand your skill set and discover troubleshooting tips
  • Browse open careers and opportunities
  • Get a chance to be featured in upcoming editions
  • Learn our secret handshake
  • And more!
Sitecore Snack a newsletter by Fishtank Consulting
 

Meet David Austin

Development Team Lead | Sitecore Technology MVP x 3

📷🕹️👪

David is a decorated Development Team Lead with Sitecore Technology MVP and Coveo MVP awards, as well as Sitecore CDP & Personalize Certified. He's worked in IT for 25 years; everything ranging from Developer to Business Analyst to Group Lead helping manage everything from Intranet and Internet sites to facility management and application support. David is a dedicated family man who loves to spend time with his girls. He's also an avid photographer and loves to explore new places.

Connect with David