From 1c379d4aa18750d9c276fa1842896dd169c40bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Apr 2026 00:32:51 +0200 Subject: [PATCH 1/3] Ignore empty CSS declarations --- .../Compatibility/SvgCssCompatibilityProcessor.cs | 5 +++++ .../Compatibility/SvgInlineStyleAttributeParser.cs | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Svg.Custom/Compatibility/SvgCssCompatibilityProcessor.cs b/src/Svg.Custom/Compatibility/SvgCssCompatibilityProcessor.cs index be26275d0d..197932707a 100644 --- a/src/Svg.Custom/Compatibility/SvgCssCompatibilityProcessor.cs +++ b/src/Svg.Custom/Compatibility/SvgCssCompatibilityProcessor.cs @@ -105,6 +105,11 @@ List CreateAppliedDeclarations() var result = new List(); foreach (var declaration in rule.Style) { + if (string.IsNullOrWhiteSpace(declaration.Original)) + { + continue; + } + result.Add(new AppliedDeclaration(declaration.Name, declaration.Original)); } diff --git a/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs b/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs index 533105a4a4..bb83a1d02d 100644 --- a/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs +++ b/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs @@ -25,6 +25,11 @@ public void ApplyStyles(SvgElement element, string styleText) { foreach (var declaration in rule.Style) { + if (string.IsNullOrWhiteSpace(declaration.Original)) + { + continue; + } + element.AddStyle(declaration.Name, declaration.Original, SvgElement.StyleSpecificity_InlineStyle); } } @@ -55,6 +60,11 @@ private static bool TryApplyInlineDeclarations(SvgElement element, string styleT return false; } + if (string.IsNullOrWhiteSpace(value)) + { + continue; + } + element.AddStyle(name, value, SvgElement.StyleSpecificity_InlineStyle); } } From 847ebb30d765e3e2434f7b8fb3d89a27b033770e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Apr 2026 00:32:58 +0200 Subject: [PATCH 2/3] Add empty CSS declaration regressions --- .../SvgDocumentCompatibilityLoaderTests.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs b/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs index ba780cdf04..3459d21d95 100644 --- a/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs +++ b/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs @@ -920,6 +920,78 @@ public void FromSvg_ParsesInlineStyleAttributesCaseInsensitively() Assert.Equal(Color.Orange.ToArgb(), fill.Colour.ToArgb()); } + [Fact] + public void FromSvg_IgnoresInlineStyleDeclarationsWithoutValues() + { + const string svg = """ + + + + + + """; + + var document = SvgDocumentCompatibilityLoader.FromSvg(svg); + var top = document.Descendants().OfType().Single(static element => element.ID == "top"); + var middle = document.Descendants().OfType().Single(static element => element.ID == "middle"); + var bottom = document.Descendants().OfType().Single(static element => element.ID == "bottom"); + var topFill = Assert.IsType(top.Fill); + var middleFill = Assert.IsType(middle.Fill); + var bottomFill = Assert.IsType(bottom.Fill); + var topStroke = Assert.IsType(top.Stroke); + var middleStroke = Assert.IsType(middle.Stroke); + var bottomStroke = Assert.IsType(bottom.Stroke); + + Assert.Equal(Color.Blue.ToArgb(), topFill.Colour.ToArgb()); + Assert.Equal(Color.FromArgb(244, 58, 32).ToArgb(), middleFill.Colour.ToArgb()); + Assert.Equal(Color.Blue.ToArgb(), bottomFill.Colour.ToArgb()); + Assert.Equal(Color.White.ToArgb(), topStroke.Colour.ToArgb()); + Assert.Equal(Color.White.ToArgb(), middleStroke.Colour.ToArgb()); + Assert.Equal(Color.White.ToArgb(), bottomStroke.Colour.ToArgb()); + } + + [Fact] + public void FromSvg_IgnoresFallbackInlineStyleDeclarationsWithoutValues() + { + const string svg = """ + + + + """; + + var document = SvgDocumentCompatibilityLoader.FromSvg(svg); + var rect = document.Descendants().OfType().Single(static element => element.ID == "target"); + var fill = Assert.IsType(rect.Fill); + var stroke = Assert.IsType(rect.Stroke); + + Assert.Equal(Color.Blue.ToArgb(), fill.Colour.ToArgb()); + Assert.Equal(Color.White.ToArgb(), stroke.Colour.ToArgb()); + } + + [Fact] + public void FromSvg_IgnoresStylesheetDeclarationsWithoutValues() + { + const string svg = """ + + + + + """; + + var document = SvgDocumentCompatibilityLoader.FromSvg(svg); + var rect = document.Descendants().OfType().Single(static element => element.ID == "target"); + var fill = Assert.IsType(rect.Fill); + var stroke = Assert.IsType(rect.Stroke); + + Assert.Equal(Color.Blue.ToArgb(), fill.Colour.ToArgb()); + Assert.Equal(Color.White.ToArgb(), stroke.Colour.ToArgb()); + } + [Fact] public void FromSvg_ParsesInlineStyleAttributesWithEmptyDeclarationsAndWhitespace() { From 3af7e47ba9b46e1c44c034df5203ef4f156157f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Sat, 9 May 2026 18:56:27 +0200 Subject: [PATCH 3/3] Preserve empty inline custom properties --- .../SvgInlineStyleAttributeParser.cs | 6 ++-- .../SvgDocumentCompatibilityLoaderTests.cs | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs b/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs index 639da71e45..d1206762af 100644 --- a/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs +++ b/src/Svg.Custom/Compatibility/SvgInlineStyleAttributeParser.cs @@ -25,7 +25,8 @@ public void ApplyStyles(SvgElement element, string styleText) { foreach (var declaration in rule.Style) { - if (string.IsNullOrWhiteSpace(declaration.Original)) + if (string.IsNullOrWhiteSpace(declaration.Original) && + !SvgCssVariableResolver.IsCustomPropertyName(declaration.Name)) { continue; } @@ -60,7 +61,8 @@ private static bool TryApplyInlineDeclarations(SvgElement element, string styleT return false; } - if (string.IsNullOrWhiteSpace(value)) + if (string.IsNullOrWhiteSpace(value) && + !SvgCssVariableResolver.IsCustomPropertyName(name)) { continue; } diff --git a/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs b/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs index 009534710a..a927826075 100644 --- a/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs +++ b/tests/Svg.Skia.UnitTests/SvgDocumentCompatibilityLoaderTests.cs @@ -968,6 +968,42 @@ public void FromSvg_IgnoresFallbackInlineStyleDeclarationsWithoutValues() Assert.Equal(Color.White.ToArgb(), stroke.Colour.ToArgb()); } + [Fact] + public void FromSvg_PreservesEmptyInlineCustomPropertyDeclarations() + { + const string svg = """ + + + + + + """; + + var document = SvgDocumentCompatibilityLoader.FromSvg(svg); + var rect = document.Descendants().OfType().Single(static element => element.ID == "target"); + var fill = Assert.IsType(rect.Fill); + + Assert.Equal(Color.Black.ToArgb(), fill.Colour.ToArgb()); + } + + [Fact] + public void FromSvg_PreservesFallbackEmptyInlineCustomPropertyDeclarations() + { + const string svg = """ + + + + + + """; + + var document = SvgDocumentCompatibilityLoader.FromSvg(svg); + var rect = document.Descendants().OfType().Single(static element => element.ID == "target"); + var fill = Assert.IsType(rect.Fill); + + Assert.Equal(Color.Black.ToArgb(), fill.Colour.ToArgb()); + } + [Fact] public void FromSvg_IgnoresStylesheetDeclarationsWithoutValues() {