Skip to content

Instantly share code, notes, and snippets.

@MineshS
Last active September 12, 2023 18:04
Show Gist options
  • Save MineshS/7aeb9eb73192bc00147ca469c8880a31 to your computer and use it in GitHub Desktop.
Save MineshS/7aeb9eb73192bc00147ca469c8880a31 to your computer and use it in GitHub Desktop.
Edge Image Tag Helper
using System.Reflection;
using EPiServer.Core;
using EPiServer.Web.Routing;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Hosting;
using Netcel.Optimizely.Core.Interfaces;
using Netcel.Optimizely.Domain.Attributes;
using Netcel.Optimizely.Domain.Models.Interfaces;
using Netcel.Optimizely.Domain.Models.Media;
namespace Netcel.Optimizely.Core.TagHelpers;
[HtmlTargetElement("img", Attributes = "image-for")]
public class EdgeImageTagHelper : TagHelper
{
private readonly IUrlResolver _urlResolver;
private readonly IContentLoaderService _contentLoader;
private readonly IWebHostEnvironment _webHostEnvironment;
public ModelExpression ImageFor { get; set; }
public string CssClass { get; set; }
public string Fit {get; set; }
public EdgeImageTagHelper(IUrlResolver urlResolver, IContentLoaderService contentLoader, IWebHostEnvironment webHostEnvironment)
{
_urlResolver = urlResolver;
_contentLoader = contentLoader;
_webHostEnvironment = webHostEnvironment;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (ImageFor.Model is not ContentReference edgeImage) return;
if(ContentReference.IsNullOrEmpty(edgeImage)) return;
if(!_contentLoader.TryGet(edgeImage, out ImageFile imageFile)) return;
var actualUrl = _urlResolver.GetUrl(edgeImage);
var property = ImageFor
.Metadata
.ContainerType
.GetProperties()
.FirstOrDefault(x => x.Name == ImageFor.Metadata.PropertyName);
if (property == null)
{
RenderNonResponsiveImage(output, actualUrl);
return;
}
var shouldSkipEdgeResizing = _webHostEnvironment.IsDevelopment() || _contentLoader.IsContentInEditMode;
var imageSize = property.GetCustomAttributes<ImageSizeAttribute>().ToList();
var imageSizes = property.GetCustomAttribute<ImageSizesAttribute>();
var defaultImageSize = imageSize.FirstOrDefault(x => x.IsDefault);
if (defaultImageSize == null)
{
RenderNonResponsiveImage(output, actualUrl);
return;
}
var srcSetUrls = imageSize
.OrderBy(x => x.Width)
.Select(s => GetEdgeUrl(actualUrl, s.Width, shouldSkipEdgeResizing)).ToList();
SetAttribute(output, "src", GetEdgeUrl(actualUrl, defaultImageSize.Width, shouldSkipEdgeResizing, true));
SetAttribute(output, "srcset", string.Join(",", srcSetUrls));
if (imageSizes != null) SetAttribute(output, "sizes", imageSizes.Sizes);
SetAttribute(output, "alt", imageFile.AlternativeText);
SetAttribute(output, "loading", "lazy");
SetAttribute(output, "decoding", "auto");
SetAttribute(output, "fetchpriority", "auto");
SetAttribute(output, "class", CssClass);
if (imageFile is not IHasPixelSize pixelSize) return;
if (pixelSize.Width > 0)
{
SetAttribute(output,"width", pixelSize.Width.ToString());
}
if (pixelSize.Height > 0)
{
SetAttribute(output, "height", pixelSize.Height.ToString());
}
}
private void RenderNonResponsiveImage(TagHelperOutput output, string url)
{
SetAttribute(output, "src", url);
SetAttribute(output, "class", CssClass);
}
private string GetEdgeUrl(string actualUrl, int width, bool isLocal, bool isDefault = false)
{
if (!isLocal)
{
return isDefault
? $"/cdn-cgi/image/{GetEdgeImageOptions(width)}{actualUrl}"
: $"/cdn-cgi/image/{GetEdgeImageOptions(width)}{actualUrl} {width}w";
}
else
{
return isDefault
? $"{actualUrl}?{GetLocalImageOptions(width)}"
: $"{actualUrl}?{GetLocalImageOptions(width)} {width}w";
}
}
private string GetLocalImageOptions(int width)
{
var options = $"width={width}";
if (!string.IsNullOrWhiteSpace(Fit))
{
options += $"&fit={Fit}";
}
return options;
}
private string GetEdgeImageOptions(int width)
{
var options = string.Empty;
if (!string.IsNullOrWhiteSpace(Fit))
{
options = $"fit={Fit},";
}
options += $"width={width}";
return options;
}
private void SetAttribute(TagHelperOutput output, string key, string value)
{
if (!string.IsNullOrWhiteSpace(value))
{
output.Attributes.SetAttribute(key, value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment