Transforming XhtmlString img src

Vote:
 

I need to transform images added via the rich text editor - essentially using the HtmlAgilityPack to extract the width and height from the image tag and apply to the src as a query string so as to automatically resize the images.

I've tried a few ways of doing this, such as replacing the display template for XhtmlStrings however altering the src at this point causes a problem as the link with querystring appened doesn't then get converted to the friendly URL.

I was trying to identify what code / class was responsible for encoding to the friendly URLs before sending out the response to the browser, thinking perhaps I could also do my transformation there, but haven't had much luck.

Has anyone had to look at this sort of thing before or know what module is responsible for making links friendly before sending to the browser that I might modify and replace it?

#194507
Jun 22, 2018 15:38
Vote:
 

Figured out a way to get this working - appears how I had declared my display template was what was causing the problem.

Needed to look like this:

@using EPiServer.Core
@model XhtmlString

@{
    Html.RenderXhtmlString(Model.OptimizeImages());
}

I wasn't using Html.RenderXhtmlString before. The OptimizeImages function is the custom bit I've used to scan for images and modify the src.

using EPiServer.Core;
using HtmlAgilityPack;

    public static class XhtmlStringHelper
    {
        public static XhtmlString OptimizeImages(this XhtmlString html)
        {
            if (html == null)
                return html;

            var doc = new HtmlDocument();
            doc.LoadHtml(html.ToHtmlString());

            var imgs = doc.DocumentNode.SelectNodes("//img");
            if (imgs == null)
                return html;

            foreach (var img in imgs)
            {
                var width = img.Attributes["width"].Value;
                var height = img.Attributes["height"].Value;
                var src = img.Attributes["src"].Value;

                img.SetAttributeValue("src", $"{src}?width={width}&height={height}&mode=stretch");
            }

            return new XhtmlString(doc.DocumentNode.OuterHtml);
        }
    }

Will need a bit of modifying to just check that the attributes existing rather than assuming but seems to do the job.

Would love to hear if anyone has approached this sort of thing in a different way.

#194512
Jun 22, 2018 17:04
Mikael Hansson - Jan 22, 2021 13:40
For reference if someone tries to implement this, you will get a bit of a problem. The method html.ToHtmlString() will drop the extra attributes from, for instance, ContentFragments. This prevents them from being recreated when you create the new XhtmlString in the end.

You should instead use html.ToEditString() as it will keep the attributes intact and make it possible for the XhtmlString constructor to recreate the ContentFragment again.
Vote:
 

I blogged about this some time ago: https://www.dcaric.com/blog/resizing-images-in-episerver

#194515
Jun 22, 2018 18:54
Vote:
 

Ah, if only I'd found that when Googling earlier. Thanks for sharing. Like the idea of include the max width and height just in case.

We were already been handling images in blocks it was just the rich text we hadn't, and wasn't quite sure the best way to do it. That said I might review how we've address those after seeing you post, some great ideas.

#194519
Jun 22, 2018 20:34
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.