diff --git a/docs/tutorials/04-Questions.md b/docs/tutorials/04-Questions.md index d104a628..262a7509 100644 --- a/docs/tutorials/04-Questions.md +++ b/docs/tutorials/04-Questions.md @@ -6,10 +6,10 @@ section: "AngleSharp.Css" ## How to change the color output? -By default, AngleSharp.Css uses `rgba()` for the serialization of `Color`. To change this you can set +By default, AngleSharp.Css uses `rgba()` for the serialization of `CssColorValue`. To change this you can set ```cs -Color.UseHex = true; +CssColorValue.UseHex = true; ``` which will automatically use hex for all non-transparent colors. All other colors would still be represented via the `rgba()` function. @@ -17,13 +17,25 @@ which will automatically use hex for all non-transparent colors. All other color So you'd get: ```cs -Color.UseHex = true; -var color1 = new Color(65, 12, 48); +CssColorValue.UseHex = true; +var color1 = new CssColorValue(65, 12, 48); // color1.CssText = #410C30 -var color2 = new Color(65, 12, 48, 10); +var color2 = new CssColorValue(65, 12, 48, 10); // color2.CssText = rgba(65, 12, 48, 0.04) ``` +Alternatively, you can follow the serialization rules from the CSSOM specification, which omit the alpha channel of an opaque color: + +```cs +CssColorValue.UseSpecSerialization = true; +var color1 = new CssColorValue(65, 12, 48); +// color1.CssText = rgb(65, 12, 48) +var color2 = new CssColorValue(65, 12, 48, 10); +// color2.CssText = rgba(65, 12, 48, 0.04) +``` + +Both switches are global and `UseHex` wins if both are active. + ## Why is my linked stylesheet not loaded? Most commonly, resource loading is not enabled. For external stylesheets, configure a requester and enable resource loading. diff --git a/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs b/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs index 31d97cfd..497a4122 100644 --- a/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs +++ b/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs @@ -16,6 +16,13 @@ namespace AngleSharp.Css.Tests.Library [TestFixture] public class StringRepresentationTests { + [TearDown] + public void ResetColorSerialization() + { + CssColorValue.UseHex = false; + CssColorValue.UseSpecSerialization = false; + } + [Test] public void PrettyStyleFormatterStringifyShouldWork_Issue41() { @@ -50,6 +57,62 @@ public void TransparentColorWorksWithHexOutput_Issue132() Assert.AreEqual("#410C300A", text); } + [Test] + public void OpaqueColorKeepsTheAlphaChannelByDefault_Issue227() + { + var color = new CssColorValue(65, 12, 48); + Assert.AreEqual("rgba(65, 12, 48, 1)", color.CssText); + } + + [Test] + public void OpaqueColorDropsTheAlphaChannelWithSpecOutput_Issue227() + { + var color = new CssColorValue(65, 12, 48); + CssColorValue.UseSpecSerialization = true; + Assert.AreEqual("rgb(65, 12, 48)", color.CssText); + } + + [Test] + public void TransparentColorKeepsTheAlphaChannelWithSpecOutput_Issue227() + { + var color = new CssColorValue(65, 12, 48, 128); + CssColorValue.UseSpecSerialization = true; + Assert.AreEqual("rgba(65, 12, 48, 0.5)", color.CssText); + } + + [Test] + public void OpaqueColorPrefersHexOutputOverSpecOutput_Issue227() + { + var color = new CssColorValue(65, 12, 48); + CssColorValue.UseHex = true; + CssColorValue.UseSpecSerialization = true; + Assert.AreEqual("#410C30", color.CssText); + } + + [Test] + public void TransparentColorPrefersHexOutputOverSpecOutput_Issue227() + { + var color = new CssColorValue(65, 12, 48, 10); + CssColorValue.UseHex = true; + CssColorValue.UseSpecSerialization = true; + Assert.AreEqual("#410C300A", color.CssText); + } + + [Test] + public void CurrentColorIsNotAffectedBySpecOutput_Issue227() + { + CssColorValue.UseSpecSerialization = true; + Assert.AreEqual("currentColor", CssColorValue.CurrentColor.CssText); + } + + [Test] + public void DeclarationUsesSpecOutputForOpaqueColors_Issue227() + { + CssColorValue.UseSpecSerialization = true; + var declaration = ParseDeclaration("color: rgba(255, 0, 0, 1)"); + Assert.AreEqual("color: rgb(255, 0, 0)", declaration.CssText); + } + [Test] public void ShorthandPaddingInheritPropertiesShouldBeIncluded_Issue100() { diff --git a/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs index 5caa2fb2..46be0a84 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs @@ -469,6 +469,12 @@ public static CssColorValue FromHwba(Double h, Double w, Double b, Double alpha) /// public static Boolean UseHex { get; set; } + /// + /// Gets or sets if the CSSOM serialization rules should be used, i.e., + /// if the alpha channel of an opaque color should be omitted. + /// + public static Boolean UseSpecSerialization { get; set; } + /// /// Gets the CSS text representation. /// @@ -495,6 +501,17 @@ public String CssText return color; } + else if (UseSpecSerialization && _alpha == 255) + { + var fn = FunctionNames.Rgb; + var args = String.Join(", ", new[] + { + R.ToString(CultureInfo.InvariantCulture), + G.ToString(CultureInfo.InvariantCulture), + B.ToString(CultureInfo.InvariantCulture), + }); + return fn.CssFunction(args); + } else { var fn = FunctionNames.Rgba;