One more thought.. so you don’t have to revisit content.. is to override the PropertyValueConvertor and update instances of http:// to https:// when frontend calls for the rendering.
(that way database still holds the incorrect http:// but we’ve corrected it at the point of use, and universal across all rtes)
here’s a v17 override, that’s removing empty trailing
, though for v13 I think it’s probably
Umbraco-CMS/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs at release-13.14.0 · umbraco/Umbraco-CMS
or maybe…
Umbraco-CMS/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs at release-13.14.0 · umbraco/Umbraco-CMS
using HtmlAgilityPack;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Blocks;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Core.Templates;
namespace Lvl.Code.Extensions.PropertyValueConvertors;
// We inherit from the core class so we satisfy the "IsConverter" check
public class CustomRtePropertyValueConverter : RteBlockRenderingValueConverter
{
public CustomRtePropertyValueConverter(HtmlLocalLinkParser linkParser, HtmlUrlParser urlParser, HtmlImageSourceParser imageSourceParser, IApiRichTextElementParser apiRichTextElementParser, IApiRichTextMarkupParser apiRichTextMarkupParser, IPartialViewBlockEngine partialViewBlockEngine, BlockEditorConverter blockEditorConverter, IJsonSerializer jsonSerializer, IApiElementBuilder apiElementBuilder, RichTextBlockPropertyValueConstructorCache constructorCache, ILogger<CustomRtePropertyValueConverter> logger, IVariationContextAccessor variationContextAccessor, BlockEditorVarianceHandler blockEditorVarianceHandler, IOptionsMonitor<DeliveryApiSettings> deliveryApiSettingsMonitor) : base(linkParser, urlParser, imageSourceParser, apiRichTextElementParser, apiRichTextMarkupParser, partialViewBlockEngine, blockEditorConverter, jsonSerializer, apiElementBuilder, constructorCache, logger, variationContextAccessor, blockEditorVarianceHandler, deliveryApiSettingsMonitor)
{
}
public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview)
{
// 1. Let the base class do ALL the heavy lifting (parsing links, rendering blocks, etc.)
var baseResult = base.ConvertIntermediateToObject(owner, propertyType, referenceCacheLevel, inter, preview);
if (baseResult is not IHtmlEncodedString htmlEncoded)
{
return new HtmlEncodedString(string.Empty);
}
var rawHtml = htmlEncoded.ToHtmlString();
if (string.IsNullOrWhiteSpace(rawHtml))
{
return new HtmlEncodedString(string.Empty);
}
// 2. Perform your surgical strike on the finished HTML string
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(rawHtml);
bool modified = false;
while (htmlDoc.DocumentNode.LastChild != null && IsNodeEmpty(htmlDoc.DocumentNode.LastChild))
{
htmlDoc.DocumentNode.LastChild.Remove();
modified = true;
}
return modified
? new HtmlEncodedString(htmlDoc.DocumentNode.OuterHtml)
: htmlEncoded;
}
private static bool IsNodeEmpty(HtmlNode node)
{
if (node.Name is "p" or "br")
{
var text = node.InnerText.Replace(" ", "").Trim();
return string.IsNullOrWhiteSpace(text);
}
return node.NodeType == HtmlNodeType.Text && string.IsNullOrWhiteSpace(node.InnerText);
}
public class RteConverterComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
// 1. Remove the standard RTE converter (the "enhanced" one)
builder.PropertyValueConverters().Remove<RteBlockRenderingValueConverter>();
// 2. Just in case, remove the simple one (though Umbraco likely already did)
builder.PropertyValueConverters().Remove<SimpleRichTextValueConverter>();
// 3. Add yours to the end of the collection
builder.PropertyValueConverters().Append<CustomRtePropertyValueConverter>();
}
}
}