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;