From 3ac0957b3d5174053a65b893808e699533a44ab6 Mon Sep 17 00:00:00 2001
From: David Kallesen <david@lmdk.dk>
Date: Sat, 15 Feb 2025 23:41:47 +0100
Subject: [PATCH 1/2] chore: nuget updates

---
 Directory.Build.props                         |  2 +-
 README.md                                     | 26 +------------------
 sample/Atc.Wpf.Sample/Atc.Wpf.Sample.csproj   |  8 +++---
 .../Atc.Wpf.Controls.Tests.csproj             |  2 +-
 .../Atc.Wpf.SourceGenerators.Tests.csproj     |  2 +-
 test/Atc.Wpf.Tests/Atc.Wpf.Tests.csproj       |  2 +-
 .../Atc.Wpf.Theming.Tests.csproj              |  2 +-
 ...Atc.Wpf.Generator.FontIconResources.csproj |  6 ++---
 8 files changed, 13 insertions(+), 37 deletions(-)

diff --git a/Directory.Build.props b/Directory.Build.props
index e37e0ce8..200e5005 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@
   <ItemGroup Label="Code Analyzers">
     <PackageReference Include="AsyncFixer" Version="1.6.0" PrivateAssets="All" />
     <PackageReference Include="Asyncify" Version="0.9.7" PrivateAssets="All" />
-    <PackageReference Include="Meziantou.Analyzer" Version="2.0.186" PrivateAssets="All" />
+    <PackageReference Include="Meziantou.Analyzer" Version="2.0.187" PrivateAssets="All" />
     <PackageReference Include="SecurityCodeScan.VS2019" Version="5.6.7" PrivateAssets="All" />
     <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.507" PrivateAssets="All" />
     <PackageReference Include="SonarAnalyzer.CSharp" Version="10.6.0.109712" PrivateAssets="All" />
diff --git a/README.md b/README.md
index ab6fa269..f3794c4f 100644
--- a/README.md
+++ b/README.md
@@ -4,30 +4,6 @@
 
 This is a base libraries for building WPF application with the MVVM design pattern.
 
-# Table of contents
-
-- [ATC.Net WPF](#atcnet-wpf)
-- [Table of contents](#table-of-contents)
-  - [Requirements](#requirements)
-  - [NuGet Packages Provided in this Repository](#nuget-packages-provided-in-this-repository)
-- [🔎 Demonstration Application](#-demonstration-application)
-  - [Playground and Viewer for a Given Control or Functionality](#playground-and-viewer-for-a-given-control-or-functionality)
-    - [Initial glimpse at the demonstration application](#initial-glimpse-at-the-demonstration-application)
-- [🚀 How to get started with atc-wpf](#-how-to-get-started-with-atc-wpf)
-  - [WPF with MVVM Easily Separate UI and Business Logic](#wpf-with-mvvm-easily-separate-ui-and-business-logic)
-- [📝 Readme's for each NuGet Package area](#-readmes-for-each-nuget-package-area)
-  - [💟 Atc.Wpf](#-atcwpf)
-    - [Controls](#controls)
-    - [Misc](#misc)
-  - [💟 Atc.Wpf.Controls](#-atcwpfcontrols)
-    - [Controls](#controls-1)
-    - [Misc](#misc-1)
-  - [💟 Atc.Wpf.FontIcons](#-atcwpffonticons)
-    - [Misc](#misc-2)
-  - [💟 Atc.Wpf.Theming](#-atcwpftheming)
-- [⚙️ Source Generators](#️-source-generators)
-- [How to contribute](#how-to-contribute)
-
 ## Requirements
 
 [.NET 9 - Desktop Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)
@@ -72,7 +48,7 @@ The following example is taken from the ReplayCommandAsync which illustrates its
 | Wpf.Theming - ImageButton ![Img](docs/images/lm-wpf-theming-imagebutton.png) | Wpf.Theming - ImageButton ![Img](docs/images/dm-wpf-theming-imagebutton.png) |
 | Wpf.FontIcons - Viewer ![Img](docs/images/lm-wpf-fonicons-viewer.png)        | Wpf.FontIcons - Viewer ![Img](docs/images/dm-wpf-fonicons-viewer.png)        |
 
-# 🚀 How to get started with atc-wpf
+# 🚀 How to get started with Atc's WPF
 
 First of all, include Nuget packages in the `.csproj` file like this:
 
diff --git a/sample/Atc.Wpf.Sample/Atc.Wpf.Sample.csproj b/sample/Atc.Wpf.Sample/Atc.Wpf.Sample.csproj
index 4f725ff3..cace72f3 100644
--- a/sample/Atc.Wpf.Sample/Atc.Wpf.Sample.csproj
+++ b/sample/Atc.Wpf.Sample/Atc.Wpf.Sample.csproj
@@ -54,10 +54,10 @@
   <ItemGroup>
     <PackageReference Include="Atc" Version="2.0.552" />
     <PackageReference Include="ControlzEx" Version="6.0.0" />
-    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
-    <PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.1" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.1" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.1" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
+    <PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/test/Atc.Wpf.Controls.Tests/Atc.Wpf.Controls.Tests.csproj b/test/Atc.Wpf.Controls.Tests/Atc.Wpf.Controls.Tests.csproj
index 4cec11da..bc7e3793 100644
--- a/test/Atc.Wpf.Controls.Tests/Atc.Wpf.Controls.Tests.csproj
+++ b/test/Atc.Wpf.Controls.Tests/Atc.Wpf.Controls.Tests.csproj
@@ -9,7 +9,7 @@
   <ItemGroup>
     <PackageReference Include="Atc" Version="2.0.552" />
     <PackageReference Include="Atc.XUnit" Version="2.0.552" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
     <PackageReference Include="xunit" Version="2.9.3" />
     <PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
       <PrivateAssets>all</PrivateAssets>
diff --git a/test/Atc.Wpf.SourceGenerators.Tests/Atc.Wpf.SourceGenerators.Tests.csproj b/test/Atc.Wpf.SourceGenerators.Tests/Atc.Wpf.SourceGenerators.Tests.csproj
index 1a1faa3f..510748fd 100644
--- a/test/Atc.Wpf.SourceGenerators.Tests/Atc.Wpf.SourceGenerators.Tests.csproj
+++ b/test/Atc.Wpf.SourceGenerators.Tests/Atc.Wpf.SourceGenerators.Tests.csproj
@@ -10,7 +10,7 @@
     <PackageReference Include="Atc" Version="2.0.552" />
     <PackageReference Include="Atc.XUnit" Version="2.0.552" />
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" PrivateAssets="all" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
     <PackageReference Include="xunit" Version="2.9.3" />
     <PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
       <PrivateAssets>all</PrivateAssets>
diff --git a/test/Atc.Wpf.Tests/Atc.Wpf.Tests.csproj b/test/Atc.Wpf.Tests/Atc.Wpf.Tests.csproj
index 88d8b685..71c8eeef 100644
--- a/test/Atc.Wpf.Tests/Atc.Wpf.Tests.csproj
+++ b/test/Atc.Wpf.Tests/Atc.Wpf.Tests.csproj
@@ -9,7 +9,7 @@
   <ItemGroup>
     <PackageReference Include="Atc" Version="2.0.552" />
     <PackageReference Include="Atc.XUnit" Version="2.0.552" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
     <PackageReference Include="xunit" Version="2.9.3" />
     <PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
       <PrivateAssets>all</PrivateAssets>
diff --git a/test/Atc.Wpf.Theming.Tests/Atc.Wpf.Theming.Tests.csproj b/test/Atc.Wpf.Theming.Tests/Atc.Wpf.Theming.Tests.csproj
index c2536838..b7058d0f 100644
--- a/test/Atc.Wpf.Theming.Tests/Atc.Wpf.Theming.Tests.csproj
+++ b/test/Atc.Wpf.Theming.Tests/Atc.Wpf.Theming.Tests.csproj
@@ -9,7 +9,7 @@
   <ItemGroup>
     <PackageReference Include="Atc" Version="2.0.552" />
     <PackageReference Include="Atc.XUnit" Version="2.0.552" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
     <PackageReference Include="xunit" Version="2.9.3" />
     <PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
       <PrivateAssets>all</PrivateAssets>
diff --git a/tool/Atc.Wpf.Generator.FontIconResources/Atc.Wpf.Generator.FontIconResources.csproj b/tool/Atc.Wpf.Generator.FontIconResources/Atc.Wpf.Generator.FontIconResources.csproj
index fae81faa..0cec9243 100644
--- a/tool/Atc.Wpf.Generator.FontIconResources/Atc.Wpf.Generator.FontIconResources.csproj
+++ b/tool/Atc.Wpf.Generator.FontIconResources/Atc.Wpf.Generator.FontIconResources.csproj
@@ -13,9 +13,9 @@
     <PackageReference Include="CssParser" Version="1.3.0">
       <NoWarn>NU1701</NoWarn>
     </PackageReference>
-    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.1" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.1" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
   </ItemGroup>
 
   <ItemGroup>

From 6b073ee103eeaababbb868f1fa7b6d90b004cc42 Mon Sep 17 00:00:00 2001
From: David Kallesen <david@lmdk.dk>
Date: Sat, 15 Feb 2025 23:42:22 +0100
Subject: [PATCH 2/2] fix: suppress and fix some analyzer rules

---
 .editorconfig                                 |  5 +++-
 sample/Atc.Wpf.Sample/MainWindow.xaml.cs      |  3 ++-
 .../SampleViewerViewModel.cs                  | 25 +++++++++++--------
 .../TextFormatters/SourceCode/Format/Code.cs  | 19 +++++++-------
 .../SourceCode/Format/Source.cs               |  7 +++---
 .../Controls/Media/W3cSvg/CssStyleParser.cs   |  3 +--
 src/Atc.Wpf/Controls/Media/W3cSvg/Svg.cs      |  4 +--
 7 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/.editorconfig b/.editorconfig
index e5c5c8a2..6ae56e68 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -574,14 +574,17 @@ dotnet_diagnostic.MA0131.severity = none           # ArgumentNullException.Throw
 
 dotnet_diagnostic.SA1010.severity = none           # Opening square brackets must be spaced correctly
 
+dotnet_diagnostic.S107.severity = none             # Methods should not have too many parameters
 dotnet_diagnostic.S1144.severity = none            # Remove the unused internal class
+dotnet_diagnostic.S1192.severity = none            # String literals should not be duplicated
 dotnet_diagnostic.S2094.severity = none            # Remove this empty class, write its code or make it an "interface"
 dotnet_diagnostic.S2325.severity = none            # Make 'XXX' a static property
 dotnet_diagnostic.S2445.severity = none            # Do not lock on writable field 'items', use a readonly field instead
 dotnet_diagnostic.S2583.severity = none            # https://rules.sonarsource.com/csharp/RSPEC-2583
 dotnet_diagnostic.S2589.severity = none            # https://rules.sonarsource.com/csharp/RSPEC-2589
 dotnet_diagnostic.S3267.severity = none            # Loops should be simplified with "LINQ" expressions
+dotnet_diagnostic.S3776.severity = none            # Cognitive Complexity of methods should not be too high
 dotnet_diagnostic.S6602.severity = none            # "Find" method should be used instead of the "FirstOrDefault" extension method
 dotnet_diagnostic.S6603.severity = none            # The collection-specific "TrueForAll" method should be used instead of the "All" extension
 dotnet_diagnostic.S6605.severity = none            # Collection-specific "Exists" method should be used instead of the "Any" extension
-dotnet_diagnostic.S6608.severity = none            # Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last"
\ No newline at end of file
+dotnet_diagnostic.S6608.severity = none            # Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last"
diff --git a/sample/Atc.Wpf.Sample/MainWindow.xaml.cs b/sample/Atc.Wpf.Sample/MainWindow.xaml.cs
index d850044d..e58c552c 100644
--- a/sample/Atc.Wpf.Sample/MainWindow.xaml.cs
+++ b/sample/Atc.Wpf.Sample/MainWindow.xaml.cs
@@ -9,7 +9,8 @@ public partial class MainWindow
 
     private readonly TreeView[] sampleTreeViews;
 
-    public MainWindow(IMainWindowViewModel viewModel)
+    public MainWindow(
+        IMainWindowViewModel viewModel)
     {
         InitializeComponent();
 
diff --git a/src/Atc.Wpf.Controls.Sample/SampleViewerViewModel.cs b/src/Atc.Wpf.Controls.Sample/SampleViewerViewModel.cs
index efd41b62..5199d176 100644
--- a/src/Atc.Wpf.Controls.Sample/SampleViewerViewModel.cs
+++ b/src/Atc.Wpf.Controls.Sample/SampleViewerViewModel.cs
@@ -3,6 +3,8 @@ namespace Atc.Wpf.Controls.Sample;
 
 public sealed class SampleViewerViewModel : ViewModelBase
 {
+    private const string Error = "Error";
+
     public SampleViewerViewModel()
     {
         Messenger.Default.Register<SampleItemMessage>(this, SampleItemMessageHandler);
@@ -189,13 +191,13 @@ private void SetSelectedViewData(
 
         if (sampleType is null)
         {
-            _ = MessageBox.Show($"Can't find sample by path '{samplePath}'", "Error", MessageBoxButton.OK);
+            _ = MessageBox.Show($"Can't find sample by path '{samplePath}'", Error, MessageBoxButton.OK);
             return;
         }
 
         if (Activator.CreateInstance(sampleType) is not UserControl instance)
         {
-            MessageBox.Show($"Can't create instance of sample by path '{samplePath}'", "Error", MessageBoxButton.OK);
+            MessageBox.Show($"Can't create instance of sample by path '{samplePath}'", Error, MessageBoxButton.OK);
             return;
         }
 
@@ -203,7 +205,7 @@ private void SetSelectedViewData(
         var baseLocation = ExtractBasePath(sampleTypeAssemblyLocation);
         if (baseLocation is null)
         {
-            MessageBox.Show("Can't find sample by invalid base location", "Error", MessageBoxButton.OK);
+            MessageBox.Show("Can't find sample by invalid base location", Error, MessageBoxButton.OK);
             return;
         }
 
@@ -211,7 +213,7 @@ private void SetSelectedViewData(
         var sampleLocation = ExtractSamplePath(baseLocation, classViewName, sampleType);
         if (sampleLocation is null)
         {
-            MessageBox.Show("Can't find sample by invalid location", "Error", MessageBoxButton.OK);
+            MessageBox.Show("Can't find sample by invalid location", Error, MessageBoxButton.OK);
             return;
         }
 
@@ -257,8 +259,15 @@ private void LoadAndRenderMarkdownDocumentIfPossible(
 
         var docSection = sampleLocation.Name.Replace("SamplesWpf", string.Empty, StringComparison.Ordinal);
 
-        var markdownFile = FindMarkdownFile(Path.Combine("docs", docSection, className)) ??
-                           FindMarkdownFile(className + "_Readme");
+        var markdownFile = FindMarkdownFile(Path.Combine("docs", docSection, className));
+        if (markdownFile is null)
+        {
+            markdownFile = FindMarkdownFile(className + "_Readme");
+        }
+        else
+        {
+            StartOnMarkdownDocument = true;
+        }
 
         if (markdownFile is null)
         {
@@ -287,10 +296,6 @@ private void LoadAndRenderMarkdownDocumentIfPossible(
 
             markdownFile ??= FindMarkdownFile(classViewName + "_Readme");
         }
-        else
-        {
-            StartOnMarkdownDocument = true;
-        }
 
         if (markdownFile is null)
         {
diff --git a/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Code.cs b/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Code.cs
index 1d0e9775..2d25f92a 100644
--- a/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Code.cs
+++ b/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Code.cs
@@ -4,7 +4,6 @@ namespace Atc.Wpf.Controls.Documents.TextFormatters.SourceCode.Format;
 /// <summary>
 /// Provides a base class for formatting most programming languages.
 /// </summary>
-[SuppressMessage("Security", "MA0009:Add regex evaluation timeout", Justification = "OK.")]
 [SuppressMessage("Design", "MA0056:Do not call overridable members in constructor", Justification = "OK.")]
 [SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "OK.")]
 public abstract class Code : Source
@@ -15,10 +14,10 @@ public abstract class Code : Source
     protected Code()
     {
         // generate the keyword and preprocessor regexes from the keyword lists
-        var r = new Regex(@"\w+|-\w+|#\w+|@@\w+|#(?:\\(?:s|w)(?:\*|\+)?\w+)+|@\\w\*+");
+        var r = new Regex(@"\w+|-\w+|#\w+|@@\w+|#(?:\\(?:s|w)(?:\*|\+)?\w+)+|@\\w\*+", RegexOptions.None, TimeSpan.FromSeconds(5));
         var regKeyword = r.Replace(Keywords, @"(?<=^|\W)$0(?=\W)");
         var regPreproc = r.Replace(Preprocessors, @"(?<=^|\s)$0(?=\s|$)");
-        r = new Regex(@" +");
+        r = new Regex(@" +", RegexOptions.None, TimeSpan.FromSeconds(5));
         regKeyword = r.Replace(regKeyword, @"|");
         regPreproc = r.Replace(regPreproc, @"|");
 
@@ -48,14 +47,14 @@ protected Code()
         var caseInsensitive = CaseSensitive
             ? RegexOptions.None
             : RegexOptions.IgnoreCase;
-        CodeRegex = new Regex(regAll.ToString(), RegexOptions.Singleline | caseInsensitive);
+        CodeRegex = new Regex(regAll.ToString(), RegexOptions.Singleline | caseInsensitive, TimeSpan.FromSeconds(5));
         CodeParagraphGlobal = new List<Run>();
     }
 
     /// <summary>
-    /// Determines if the language is case sensitive.
+    /// Determines if the language is case-sensitive.
     /// </summary>
-    /// <value><b>true</b> if the language is case sensitive, <b>false</b>
+    /// <value><b>true</b> if the language is case-sensitive, <b>false</b>
     /// otherwise. The default is true.</value>
     /// <remarks>
     /// A case-insensitive language formatter must override this
@@ -135,7 +134,7 @@ protected override string MatchEval(Match match, ThemeMode themeMode)
                 CodeParagraphGlobal.Add(run);
             }
 
-            return "::::::";
+            return FormattingMarker;
         }
 
         // string literal
@@ -150,7 +149,7 @@ protected override string MatchEval(Match match, ThemeMode themeMode)
             };
 
             CodeParagraphGlobal.Add(run);
-            return "::::::";
+            return FormattingMarker;
         }
 
         // preprocessor keyword
@@ -162,7 +161,7 @@ protected override string MatchEval(Match match, ThemeMode themeMode)
             };
 
             CodeParagraphGlobal.Add(run);
-            return "::::::";
+            return FormattingMarker;
         }
 
         // keyword
@@ -177,7 +176,7 @@ protected override string MatchEval(Match match, ThemeMode themeMode)
             };
 
             CodeParagraphGlobal.Add(run);
-            return "::::::";
+            return FormattingMarker;
         }
 
         return string.Empty;
diff --git a/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Source.cs b/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Source.cs
index 97fef496..e0d27747 100644
--- a/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Source.cs
+++ b/src/Atc.Wpf/Controls/Documents/TextFormatters/SourceCode/Format/Source.cs
@@ -22,6 +22,8 @@ namespace Atc.Wpf.Controls.Documents.TextFormatters.SourceCode.Format;
 /// </remarks>
 public abstract class Source
 {
+    public const string FormattingMarker = "::::::";
+
     /// <summary>
     /// Initializes a new instance of the <see cref="Source"/> class.
     /// </summary>
@@ -65,8 +67,7 @@ protected Source()
     /// <summary>
     /// The regular expression used to capture language tokens.
     /// </summary>
-    [SuppressMessage("Security", "MA0009:Add regex evaluation timeout", Justification = "OK.")]
-    protected Regex CodeRegex { get; set; } = new("^");
+    protected Regex CodeRegex { get; set; } = new("^", RegexOptions.None, TimeSpan.FromSeconds(5));
 
     /// <summary>
     /// This is a List of Run's that can be added later to the string of code.
@@ -102,7 +103,7 @@ private Paragraph FormatCodeHelper(string source, ThemeMode themeMode)
         var codeParagraph = new Paragraph();
         var sb = new StringBuilder(source);
         source = CodeRegex.Replace(sb.ToString(), match => MatchEval(match, themeMode));
-        string[] characters = ["::::::"];
+        string[] characters = [FormattingMarker];
 
         var split = source.Split(characters, StringSplitOptions.None);
         var currentChunk = 0;
diff --git a/src/Atc.Wpf/Controls/Media/W3cSvg/CssStyleParser.cs b/src/Atc.Wpf/Controls/Media/W3cSvg/CssStyleParser.cs
index 891f08c7..e290cd4b 100644
--- a/src/Atc.Wpf/Controls/Media/W3cSvg/CssStyleParser.cs
+++ b/src/Atc.Wpf/Controls/Media/W3cSvg/CssStyleParser.cs
@@ -2,9 +2,8 @@ namespace Atc.Wpf.Controls.Media.W3cSvg;
 
 internal static class CssStyleParser
 {
-    [SuppressMessage("Security", "MA0009:Add regex evaluation timeout", Justification = "OK.")]
     [SuppressMessage("Performance", "MA0023:Add RegexOptions.ExplicitCapture", Justification = "OK.")]
-    private static readonly Regex RxStyle = new("([\\.,<>a-zA-Z0-9: \\-#]*){([^}]*)}", RegexOptions.Compiled | RegexOptions.Singleline);
+    private static readonly Regex RxStyle = new("([\\.,<>a-zA-Z0-9: \\-#]*){([^}]*)}", RegexOptions.Compiled | RegexOptions.Singleline, TimeSpan.FromSeconds(5));
 
     public static void ParseStyle(Svg svg, string style)
     {
diff --git a/src/Atc.Wpf/Controls/Media/W3cSvg/Svg.cs b/src/Atc.Wpf/Controls/Media/W3cSvg/Svg.cs
index 161b39ee..808cd4b6 100644
--- a/src/Atc.Wpf/Controls/Media/W3cSvg/Svg.cs
+++ b/src/Atc.Wpf/Controls/Media/W3cSvg/Svg.cs
@@ -3,6 +3,7 @@ namespace Atc.Wpf.Controls.Media.W3cSvg;
 /// <summary>
 /// This is the class that reads and parses the XML file.
 /// </summary>
+[SuppressMessage("Maintainability", "S1144:Unused private types or members should be removed", Justification = "OK.")]
 internal sealed class Svg
 {
     private List<Shape>? elements;
@@ -247,7 +248,6 @@ private void Load(XmlNode svgTag)
         elements = Parse(svgTag);
     }
 
-    [SuppressMessage("Security", "MA0009:Add regex evaluation timeout", Justification = "OK.")]
     [SuppressMessage("Performance", "MA0078:Use 'Cast' instead of 'Select' to cast", Justification = "OK.")]
     private void LoadStyles(XmlNode doc)
     {
@@ -269,7 +269,7 @@ private void LoadStyles(XmlNode doc)
 
         foreach (var node in cssUrlNodes)
         {
-            var url = Regex.Match(node.Data, "href=\"(?<url>.*?)\"").Groups["url"].Value;
+            var url = Regex.Match(node.Data, "href=\"(?<url>.*?)\"", RegexOptions.None, TimeSpan.FromSeconds(5)).Groups["url"].Value;
             var stream = ExternalFileLoader.LoadFile(url, Filename);
             if (stream is null)
             {