Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caching SVG doesn't cache CSS class name and Viewbox settings #67

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 79 additions & 27 deletions Our.Umbraco.TagHelpers/InlineSvgTagHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,31 @@ public InlineSvgTagHelper(MediaFileManager mediaFileManager, IWebHostEnvironment
[HtmlAttributeName("ignore-appsettings")]
public bool IgnoreAppSettings { get; set; }



private string CalculateSvgContentCacheKey () {
if (MediaItem is not null)
{
return string.Concat("MediaItem-SvgContents (", MediaItem.Key.ToString(), ")");
}

if (string.IsNullOrWhiteSpace(FileSource) == false)
{
return string.Concat("File-SvgContents (", FileSource, ")");
}

return string.Empty;
}

private string CalculateSetAttrsCacheKey (string cleanedFileContents)
=> $"SvgWithAttributes ({CssClass?.GetHashCode()}_{cleanedFileContents.GetHashCode()})";

private int FetchCacheMinutes ()
=> CacheMinutes > 0 ? CacheMinutes : _globalSettings.OurSVG.CacheMinutes;

private bool FetchEnsureViewBoxStatus () =>
EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings);

public override void Process(TagHelperContext context, TagHelperOutput output)
{
// Can only use media-item OR src
Expand All @@ -99,23 +124,14 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
}

string? cleanedFileContents = null;

if(Cache || (_globalSettings.OurSVG.Cache && !IgnoreAppSettings))
var doCache = Cache || (_globalSettings.OurSVG.Cache && !IgnoreAppSettings);
if (doCache)
{
var cacheName = string.Empty;
var cacheMins = CacheMinutes > 0 ? CacheMinutes : _globalSettings.OurSVG.CacheMinutes;

if (MediaItem is not null)
{
cacheName = string.Concat("MediaItem-SvgContents (", MediaItem.Key.ToString(), ")");
}
else if (string.IsNullOrWhiteSpace(FileSource) == false)
{
cacheName = string.Concat("File-SvgContents (", FileSource, ")");
}
var cacheKey = CalculateSvgContentCacheKey();
var cacheMins = FetchCacheMinutes();

cleanedFileContents = _appCaches.RuntimeCache.GetCacheItem(cacheName, () =>
{
cleanedFileContents = _appCaches.RuntimeCache.GetCacheItem(cacheKey, () =>
{
return GetFileContents();
}, TimeSpan.FromMinutes(cacheMins));
}
Expand All @@ -130,12 +146,28 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
return;
}

string svgWithAttributes;
if (doCache)
{
var cacheKey = CalculateSetAttrsCacheKey(cleanedFileContents);
var cacheMins = FetchCacheMinutes();

svgWithAttributes = _appCaches.RuntimeCache.GetCacheItem(cacheKey, () =>
{
return ParseAndSetAttrs(cleanedFileContents);
}, TimeSpan.FromMinutes(cacheMins));
}
else
{
svgWithAttributes = ParseAndSetAttrs(cleanedFileContents);
}

// Remove the src attribute or media-item from the <svg>
output.Attributes.RemoveAll("src");
output.Attributes.RemoveAll("media-item");

output.TagName = null; // Remove <our-svg>
output.Content.SetHtmlContent(cleanedFileContents);
output.Content.SetHtmlContent(svgWithAttributes);
}

private string? GetFileContents()
Expand Down Expand Up @@ -201,18 +233,38 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
@"syntax:error:",
RegexOptions.IgnoreCase | RegexOptions.Singleline);

if ((EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings)) || !string.IsNullOrEmpty(CssClass))
return cleanedFileContents;
}

/// <summary>
/// Set CSS Class, Viewbox, and/or width/height
/// </summary>
/// <param name="cleanedFileContents">SVG file contents</param>
/// <returns>SVG file contents with attributes</returns>
private string ParseAndSetAttrs (string cleanedFileContents) {
var doEnsureViewBox = FetchEnsureViewBoxStatus();
var hasCssClass = !string.IsNullOrEmpty(CssClass);

// No work to do (save the unnecessary LoadHtml)
if (!doEnsureViewBox && !hasCssClass)
{
return cleanedFileContents;
}

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(cleanedFileContents);
var svgs = doc.DocumentNode.SelectNodes("//svg");
foreach (var svgNode in svgs)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(cleanedFileContents);
var svgs = doc.DocumentNode.SelectNodes("//svg");
foreach (var svgNode in svgs)
if (hasCssClass)
{
if (!string.IsNullOrEmpty(CssClass))
{
svgNode.AddClass(CssClass);
}
if ((EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings)) && svgNode.Attributes.Contains("width") && svgNode.Attributes.Contains("height") && !svgNode.Attributes.Contains("viewbox"))
svgNode.AddClass(CssClass);
}

if (doEnsureViewBox)
{
var hasDimensionsAndNoViewbox = svgNode.Attributes.Contains("width") && svgNode.Attributes.Contains("height") && !svgNode.Attributes.Contains("viewbox");
if (hasDimensionsAndNoViewbox)
{
var width = StringUtils.GetDecimal(svgNode.GetAttributeValue("width", "0"));
var height = StringUtils.GetDecimal(svgNode.GetAttributeValue("height", "0"));
Expand All @@ -222,8 +274,8 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
svgNode.Attributes.Remove("height");
}
}
cleanedFileContents = doc.DocumentNode.OuterHtml;
}
cleanedFileContents = doc.DocumentNode.OuterHtml;

return cleanedFileContents;
}
Expand Down
Loading