Skip to content

Commit 46b9c9a

Browse files
committed
Implemented conic-gradient #101
1 parent 0751cbe commit 46b9c9a

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Released on Tuesday, May 31 2022.
66
- Updated to use AngleSharp 0.17
77
- Fixed casing issue with color, timing, and gradient functions (#109)
88
- Fixed shorthand properties using `inherit` being omitted (#100)
9+
- Added support for `conic-gradient` (#101)
910

1011
# 0.16.4
1112

src/AngleSharp.Css.Tests/Library/StringRepresentation.cs

+10
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,15 @@ public void ShorthandBorderInheritPropertiesShouldBeIncluded_Issue100()
7373
var css = styleSheet.ToCss();
7474
Assert.AreEqual("#x div { border: inherit }", css);
7575
}
76+
77+
[Test]
78+
public void ConicGradientNotParsedCorrectly_Issue101()
79+
{
80+
var html = @"<style>div { background: conic-gradient(red, yellow, green); }</style>";
81+
var dom = ParseDocument(html);
82+
var styleSheet = dom.StyleSheets[0] as ICssStyleSheet;
83+
var css = styleSheet.ToCss();
84+
Assert.AreEqual("div { background: conic-gradient(rgba(255, 0, 0, 1), rgba(255, 255, 0, 1), rgba(0, 128, 0, 1)) }", css);
85+
}
7686
}
7787
}

src/AngleSharp.Css/Constants/FunctionNames.cs

+10
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public static class FunctionNames
8787
/// </summary>
8888
public static readonly String RadialGradient = "radial-gradient";
8989

90+
/// <summary>
91+
/// The conic-gradient function.
92+
/// </summary>
93+
public static readonly String ConicGradient = "conic-gradient";
94+
9095
/// <summary>
9196
/// The repeating-linear-gradient function.
9297
/// </summary>
@@ -97,6 +102,11 @@ public static class FunctionNames
97102
/// </summary>
98103
public static readonly String RepeatingRadialGradient = "repeating-radial-gradient";
99104

105+
/// <summary>
106+
/// The repeating-conic-gradient function.
107+
/// </summary>
108+
public static readonly String RepeatingConicGradient = "repeating-conic-gradient";
109+
100110
/// <summary>
101111
/// The image function.
102112
/// </summary>

src/AngleSharp.Css/Parser/Micro/GradientParser.cs

+70
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ static class GradientParser
1414
{ FunctionNames.RepeatingLinearGradient, ParseRepeatingLinearGradient },
1515
{ FunctionNames.RadialGradient, ParseRadialGradient },
1616
{ FunctionNames.RepeatingRadialGradient, ParseRepeatingRadialGradient },
17+
{ FunctionNames.ConicGradient, ParseConicGradient },
18+
{ FunctionNames.RepeatingConicGradient, ParseRepeatingConicGradient },
1719
};
1820

1921
public static ICssGradientFunctionValue ParseGradient(this StringSource source)
@@ -128,6 +130,74 @@ private static ICssGradientFunctionValue ParseRadialGradient(StringSource source
128130
return null;
129131
}
130132

133+
private static ICssGradientFunctionValue ParseConicGradient(StringSource source)
134+
{
135+
return ParseConicGradient(source, false);
136+
}
137+
138+
private static ICssGradientFunctionValue ParseRepeatingConicGradient(StringSource source)
139+
{
140+
return ParseConicGradient(source, true);
141+
}
142+
143+
/// <summary>
144+
/// Parses a conic gradient.
145+
/// https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient
146+
/// </summary>
147+
private static ICssGradientFunctionValue ParseConicGradient(StringSource source, Boolean repeating)
148+
{
149+
ICssValue angle = null;
150+
ICssValue center = null;
151+
152+
source.SkipSpacesAndComments();
153+
154+
if (source.IsIdentifier(CssKeywords.From))
155+
{
156+
source.SkipSpacesAndComments();
157+
angle = source.ParseAngleOrCalc();
158+
159+
if (angle == null)
160+
{
161+
return null;
162+
}
163+
164+
source.SkipSpacesAndComments();
165+
}
166+
167+
if (source.IsIdentifier(CssKeywords.At))
168+
{
169+
source.SkipSpacesAndComments();
170+
center = source.ParsePoint();
171+
172+
if (center == null)
173+
{
174+
return null;
175+
}
176+
}
177+
178+
if (angle != null || center != null)
179+
{
180+
var current = source.SkipSpacesAndComments();
181+
182+
if (current != Symbols.Comma)
183+
{
184+
return null;
185+
}
186+
187+
source.SkipCurrentAndSpaces();
188+
}
189+
190+
var stops = ParseGradientStops(source);
191+
192+
if (stops != null && source.Current == Symbols.RoundBracketClose)
193+
{
194+
source.SkipCurrentAndSpaces();
195+
return new CssConicGradientValue(angle, center, stops, repeating);
196+
}
197+
198+
return null;
199+
}
200+
131201
private static CssGradientStopValue[] ParseGradientStops(StringSource source)
132202
{
133203
var stops = new List<CssGradientStopValue>();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
namespace AngleSharp.Css.Values
2+
{
3+
using AngleSharp.Css.Dom;
4+
using AngleSharp.Text;
5+
using System;
6+
using System.Linq;
7+
8+
/// <summary>
9+
/// Represents a linear gradient:
10+
/// https://drafts.csswg.org/css-images-4/#conic-gradients
11+
/// </summary>
12+
sealed class CssConicGradientValue : ICssGradientFunctionValue
13+
{
14+
#region Fields
15+
16+
private readonly CssGradientStopValue[] _stops;
17+
private readonly ICssValue _center;
18+
private readonly ICssValue _angle;
19+
private readonly Boolean _repeating;
20+
21+
#endregion
22+
23+
#region ctor
24+
25+
/// <summary>
26+
/// Creates a new conic gradient.
27+
/// </summary>
28+
/// <param name="angle">The angle of the conic gradient.</param>
29+
/// <param name="center">The center to use.</param>
30+
/// <param name="stops">The stops to use.</param>
31+
/// <param name="repeating">Indicates if the gradient is repeating.</param>
32+
public CssConicGradientValue(ICssValue angle, ICssValue center, CssGradientStopValue[] stops, Boolean repeating = false)
33+
{
34+
_stops = stops;
35+
_center = center;
36+
_angle = angle;
37+
_repeating = repeating;
38+
}
39+
40+
#endregion
41+
42+
#region Properties
43+
44+
/// <summary>
45+
/// Gets the name of the function.
46+
/// </summary>
47+
public String Name => _repeating ? FunctionNames.RepeatingConicGradient : FunctionNames.ConicGradient;
48+
49+
/// <summary>
50+
/// Gets the arguments.
51+
/// </summary>
52+
public ICssValue[] Arguments
53+
{
54+
get
55+
{
56+
var args = _stops.Cast<ICssValue>().ToList();
57+
58+
if (_center != null)
59+
{
60+
args.Insert(0, _center);
61+
}
62+
63+
if (_angle != null)
64+
{
65+
args.Insert(0, _angle);
66+
}
67+
68+
return args.ToArray();
69+
}
70+
}
71+
72+
/// <summary>
73+
/// Gets the CSS text representation.
74+
/// </summary>
75+
public String CssText
76+
{
77+
get
78+
{
79+
var defaultAngle = _angle as Angle?;
80+
var defaultPosition = _center as Point?;
81+
var offset = (defaultAngle.HasValue ? 1 : 0) + (defaultPosition.HasValue ? 1 : 0);
82+
var args = new String[_stops.Length + offset];
83+
84+
if (defaultAngle.HasValue)
85+
{
86+
args[0] = $"from {defaultAngle.Value.CssText}";
87+
}
88+
89+
if (defaultPosition.HasValue)
90+
{
91+
args[offset - 1] = $"at {defaultPosition.Value.CssText}";
92+
}
93+
94+
for (var i = 0; i < _stops.Length; i++)
95+
{
96+
args[offset++] = _stops[i].CssText;
97+
}
98+
99+
return Name.CssFunction(String.Join(", ", args));
100+
}
101+
}
102+
103+
/// <summary>
104+
/// Gets the angle of the conic gradient.
105+
/// </summary>
106+
public ICssValue Angle => _angle ?? Values.Angle.Half;
107+
108+
/// <summary>
109+
/// Gets the position of the conic gradient.
110+
/// </summary>
111+
public ICssValue Center => _center ?? Point.Center;
112+
113+
/// <summary>
114+
/// Gets all stops.
115+
/// </summary>
116+
public CssGradientStopValue[] Stops => _stops;
117+
118+
/// <summary>
119+
/// Gets if the gradient is repeating.
120+
/// </summary>
121+
public Boolean IsRepeating => _repeating;
122+
123+
#endregion
124+
}
125+
}

0 commit comments

Comments
 (0)