diff --git a/src/AngleSharp.Css.Tests/Values/Calc.cs b/src/AngleSharp.Css.Tests/Values/Calc.cs index b3bb8813..0275d163 100644 --- a/src/AngleSharp.Css.Tests/Values/Calc.cs +++ b/src/AngleSharp.Css.Tests/Values/Calc.cs @@ -1,8 +1,13 @@ +#nullable disable namespace AngleSharp.Css.Tests.Values { + using AngleSharp.Css.Dom; using AngleSharp.Css.Parser; + using AngleSharp.Css.Values; + using AngleSharp.Dom; using AngleSharp.Text; using NUnit.Framework; + using System; using static CssConstructionFunctions; [TestFixture] @@ -100,5 +105,47 @@ public void IntegerCanBeUsedWithCalc() Assert.IsTrue(property.HasValue); Assert.AreEqual("calc(21 + 5 - 4 * 2)", property.Value); } + + [Test] + public void CalcAdditionOfLengthsIsComputed() + { + var document = ParseDocument("

"); + var style = document.QuerySelector("p").ComputeCurrentStyle(); + Assert.AreEqual("120px", style.GetWidth()); + } + + [Test] + public void CalcSubtractionOfLengthsIsComputed() + { + var document = ParseDocument("

"); + var style = document.QuerySelector("p").ComputeCurrentStyle(); + Assert.AreEqual("80px", style.GetWidth()); + } + + [Test] + public void CalcAdditionOfTimesIsComputed() + { + var document = ParseDocument("

"); + var style = document.QuerySelector("p").ComputeCurrentStyle(); + Assert.AreEqual("50ms", style.GetTransitionDuration()); + } + + [TestCase(typeof(CssAngleValue))] + [TestCase(typeof(CssFrequencyValue))] + [TestCase(typeof(CssIntegerValue))] + [TestCase(typeof(CssLengthValue))] + [TestCase(typeof(CssNumberValue))] + [TestCase(typeof(CssPercentageValue))] + [TestCase(typeof(CssResolutionValue))] + [TestCase(typeof(CssTimeValue))] + public void MetricValueCanBeCreatedWithAnotherValue(Type type) + { + var template = (ICssMetricValue)Activator.CreateInstance(type, 2.0); + var result = template.WithValue(5.0); + + Assert.IsInstanceOf(type, result); + Assert.AreEqual(5.0, ((ICssMetricValue)result).Value); + Assert.AreEqual(template.UnitString, ((ICssMetricValue)result).UnitString); + } } } diff --git a/src/AngleSharp.Css/Extensions/CssMetricValueExtensions.cs b/src/AngleSharp.Css/Extensions/CssMetricValueExtensions.cs new file mode 100644 index 00000000..caf9d9ff --- /dev/null +++ b/src/AngleSharp.Css/Extensions/CssMetricValueExtensions.cs @@ -0,0 +1,39 @@ +#nullable disable +namespace AngleSharp.Css.Values +{ + using AngleSharp.Css.Dom; + using System; +#if NET5_0_OR_GREATER + using System.Diagnostics.CodeAnalysis; +#endif + + /// + /// A set of helpers for dealing with metric values. + /// + static class CssMetricValueExtensions + { + /// + /// Creates a new metric value of the same type as the given template, but + /// carrying the provided value. + /// + /// The value determining the type to create. + /// The value to use for the created instance. + /// The newly created metric value. +#if NET5_0_OR_GREATER + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssAngleValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssFrequencyValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssIntegerValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssLengthValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssNumberValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssPercentageValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssResolutionValue))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CssTimeValue))] + [UnconditionalSuppressMessage("Trimming", "IL2072", + Justification = "The constructors of the metric values shipped with AngleSharp.Css are preserved via " + + "DynamicDependency. Metric values implemented outside of AngleSharp.Css have to preserve their " + + "public constructor taking a single Double themselves, e.g., via DynamicDependency.")] +#endif + public static ICssValue WithValue(this ICssMetricValue template, Double value) => + (ICssValue)Activator.CreateInstance(template.GetType(), value); + } +} diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs index 2b5add84..ed1bd7f2 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs @@ -60,7 +60,7 @@ ICssValue ICssValue.Compute(ICssComputeContext context) if (left is ICssMetricValue x && right is ICssMetricValue y && x.UnitString == y.UnitString) { var result = x.Value + y.Value; - return (ICssValue)Activator.CreateInstance(x.GetType(), result); + return x.WithValue(result); } return null; diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs index c3fcfdae..324245d2 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs @@ -60,7 +60,7 @@ ICssValue ICssValue.Compute(ICssComputeContext context) if (left is ICssMetricValue x && right is ICssMetricValue y && x.UnitString == y.UnitString) { var result = x.Value / y.Value; - return (ICssValue)Activator.CreateInstance(x.GetType(), result); + return x.WithValue(result); } return null; diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs index 51daa6cb..724fa03f 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs @@ -60,7 +60,7 @@ ICssValue ICssValue.Compute(ICssComputeContext context) if (left is ICssMetricValue x && right is ICssMetricValue y && x.UnitString == y.UnitString) { var result = x.Value * y.Value; - return (ICssValue)Activator.CreateInstance(x.GetType(), result); + return x.WithValue(result); } return null; diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs index e8d7642f..2aa2102f 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs @@ -60,7 +60,7 @@ ICssValue ICssValue.Compute(ICssComputeContext context) if (left is ICssMetricValue x && right is ICssMetricValue y && x.UnitString == y.UnitString) { var result = x.Value - y.Value; - return (ICssValue)Activator.CreateInstance(x.GetType(), result); + return x.WithValue(result); } return null;