CssValueBuilder
The class that is responsible for book-keeping information
about the current CSS value that is been build.
using AngleSharp.Dom.Css;
using AngleSharp.Extensions;
using System.Collections.Generic;
namespace AngleSharp.Parser.Css
{
internal sealed class CssValueBuilder
{
private readonly List<CssToken> _values;
private CssToken _buffer;
private bool _valid;
private bool _important;
private int _open;
public bool IsReady {
get {
if (_open == 0)
return _values.Count > 0;
return false;
}
}
public bool IsValid {
get {
if (_valid)
return IsReady;
return false;
}
}
public bool IsImportant => _important;
public CssValueBuilder()
{
_values = new List<CssToken>();
Reset();
}
public CssValue GetResult()
{
return new CssValue(_values);
}
public void Apply(CssToken token)
{
switch (token.Type) {
case CssTokenType.Comment:
break;
case CssTokenType.RoundBracketOpen:
_open++;
Add(token);
break;
case CssTokenType.Function:
Add(token);
break;
case CssTokenType.Ident:
_important = CheckImportant(token);
break;
case CssTokenType.RoundBracketClose:
_open--;
Add(token);
break;
case CssTokenType.Whitespace:
if (_values.Count > 0 && !IsSlash(_values[_values.Count - 1]))
_buffer = token;
break;
case CssTokenType.String:
case CssTokenType.Url:
case CssTokenType.Color:
case CssTokenType.Number:
case CssTokenType.Percentage:
case CssTokenType.Dimension:
case CssTokenType.Delim:
case CssTokenType.Comma:
Add(token);
break;
default:
_valid = false;
Add(token);
break;
}
}
public CssValueBuilder Reset()
{
_open = 0;
_valid = true;
_buffer = null;
_important = false;
_values.Clear();
return this;
}
private bool CheckImportant(CssToken token)
{
if (_values.Count != 0 && token.Data == Keywords.Important && IsExclamationMark(_values[_values.Count - 1])) {
do {
_values.RemoveAt(_values.Count - 1);
} while (_values.Count > 0 && _values[_values.Count - 1].Type == CssTokenType.Whitespace);
return true;
}
Add(token);
return _important;
}
private void Add(CssToken token)
{
if (_buffer != null && !IsCommaOrSlash(token))
_values.Add(_buffer);
else if (_values.Count != 0 && !IsComma(token) && IsComma(_values[_values.Count - 1])) {
_values.Add(CssToken.Whitespace);
}
_buffer = null;
if (_important)
_valid = false;
_values.Add(token);
}
private static bool IsCommaOrSlash(CssToken token)
{
if (!IsComma(token))
return IsSlash(token);
return true;
}
private static bool IsComma(CssToken token)
{
return token.Type == CssTokenType.Comma;
}
private static bool IsExclamationMark(CssToken token)
{
if (token.Type == CssTokenType.Delim)
return token.Data.Has('!', 0);
return false;
}
private static bool IsSlash(CssToken token)
{
if (token.Type == CssTokenType.Delim)
return token.Data.Has('/', 0);
return false;
}
}
}