-
Notifications
You must be signed in to change notification settings - Fork 26
Caching SVG doesn't cache CSS class name and Viewbox settings #67
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
base: main
Are you sure you want to change the base?
Changes from 3 commits
6571a2b
dbb8403
c35b0b8
9f24f4a
adf5fc0
ec6f2ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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()})"; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+105
to
+106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using GetHashCode() for cache keys can cause collisions since GetHashCode() is not guaranteed to be unique or consistent across application restarts. Consider using a more deterministic approach like combining the actual values or using a cryptographic hash.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||||||||||||||||||||
private int FetchCacheMinutes () | ||||||||||||||||||||||||||||||||||||||||||||||||
warrenbuckley marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
=> 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 | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -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)); | ||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -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() | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -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) { | ||||||||||||||||||||||||||||||||||||||||||||||||
warrenbuckley marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
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")); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -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; | ||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.