Commit 535abaf8 authored by Tebjan Halm's avatar Tebjan Halm
Browse files

Merge pull request #90 from erdomke/master

Initial Work on W3C Test Compliance
parents 4b1ff3d4 bd05ecbc
......@@ -17,17 +17,9 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
{
get
{
//var path = new GraphicsPath();
//AddPaths(this, path);
return GetPaths(this);
}
protected set
{ }
return GetPaths(this, renderer);
}
/// <summary>
......@@ -73,12 +65,14 @@ namespace Svg
if (!Visible || !Displayable)
return;
this.PushTransforms(renderer);
if (this.PushTransforms(renderer))
{
this.SetClip(renderer);
base.RenderChildren(renderer);
this.ResetClip(renderer);
this.PopTransforms(renderer);
}
}
public override SvgElement DeepCopy()
......
......@@ -17,17 +17,9 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
{
get
{
//var path = new GraphicsPath();
//AddPaths(this, path);
return GetPaths(this);
}
protected set
{ }
return GetPaths(this, renderer);
}
/// <summary>
......
......@@ -38,10 +38,12 @@ namespace Svg
/// Applies the required transforms to <see cref="SvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected internal override void PushTransforms(SvgRenderer renderer)
protected internal override bool PushTransforms(SvgRenderer renderer)
{
base.PushTransforms(renderer);
renderer.TranslateTransform(this.X.ToDeviceValue(this), this.Y.ToDeviceValue(this, true));
if (!base.PushTransforms(renderer)) return false;
renderer.TranslateTransform(this.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
this.Y.ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
return true;
}
/// <summary>
......@@ -53,15 +55,10 @@ namespace Svg
this.Y = 0;
}
public override System.Drawing.Drawing2D.GraphicsPath Path
{
get
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
{
SvgVisualElement element = (SvgVisualElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
return (element != null) ? element.Path : null;
}
protected set
{ }
return (element != null) ? element.Path(renderer) : null;
}
public override System.Drawing.RectangleF Bounds
......
......@@ -17,17 +17,9 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
{
get
{
//var path = new GraphicsPath();
//AddPaths(this, path);
return GetPaths(this);
}
protected set
{ }
return GetPaths(this, renderer);
}
/// <summary>
......
namespace ExCSS
{
public interface IToString
{
string ToString(bool friendlyFormat, int indentation = 0);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using ExCSS.Model;
using ExCSS.Model.TextBlocks;
// ReSharper disable once CheckNamespace
namespace ExCSS
{
sealed class Lexer
{
private readonly StringBuilder _buffer;
private readonly StylesheetReader _stylesheetReader;
private bool _ignoreWhitespace;
private bool _ignoreComments;
internal Action<ParserError, string> ErrorHandler { get; set; }
internal Lexer(StylesheetReader source)
{
_buffer = new StringBuilder();
_stylesheetReader = source;
ErrorHandler = (err, msg) => { };
}
private Block DataBlock(char current)
{
switch (current)
{
case Specification.LineFeed:
case Specification.CarriageReturn:
case Specification.Tab:
case Specification.Space:
do
{
current = _stylesheetReader.Next;
}
while (current.IsSpaceCharacter());
if (_ignoreWhitespace)
{
return DataBlock(current);
}
_stylesheetReader.Back();
return SpecialCharacter.Whitespace;
case Specification.DoubleQuote:
return DoubleQuoteString(_stylesheetReader.Next);
case Specification.Hash:
return HashStart(_stylesheetReader.Next);
case Specification.DollarSign:
current = _stylesheetReader.Next;
return current == Specification.EqualSign
? MatchBlock.Suffix
: Block.Delim(_stylesheetReader.Previous);
case Specification.SingleQuote:
return SingleQuoteString(_stylesheetReader.Next);
case Specification.ParenOpen:
return BracketBlock.OpenRound;
case Specification.ParenClose:
return BracketBlock.CloseRound;
case Specification.Asterisk:
current = _stylesheetReader.Next;
return current == Specification.EqualSign
? MatchBlock.Substring
: Block.Delim(_stylesheetReader.Previous);
case Specification.PlusSign:
{
var nextFirst = _stylesheetReader.Next;
if (nextFirst == Specification.EndOfFile)
{
_stylesheetReader.Back();
}
else
{
var nextSEcond = _stylesheetReader.Next;
_stylesheetReader.Back(2);
if (nextFirst.IsDigit() || (nextFirst == Specification.Period && nextSEcond.IsDigit()))
{
return NumberStart(current);
}
}
return Block.Delim(current);
}
case Specification.Comma:
return SpecialCharacter.Comma;
case Specification.Period:
{
var c = _stylesheetReader.Next;
return c.IsDigit()
? NumberStart(_stylesheetReader.Previous)
: Block.Delim(_stylesheetReader.Previous);
}
case Specification.MinusSign:
{
var nextFirst = _stylesheetReader.Next;
if (nextFirst == Specification.EndOfFile)
{
_stylesheetReader.Back();
}
else
{
var nextSecond = _stylesheetReader.Next;
_stylesheetReader.Back(2);
if (nextFirst.IsDigit() || (nextFirst == Specification.Period && nextSecond.IsDigit()))
{
return NumberStart(current);
}
if (nextFirst.IsNameStart())
{
return IdentStart(current);
}
if (nextFirst == Specification.ReverseSolidus && !nextSecond.IsLineBreak() && nextSecond != Specification.EndOfFile)
{
return IdentStart(current);
}
if (nextFirst != Specification.MinusSign || nextSecond != Specification.GreaterThan)
{
return Block.Delim(current);
}
_stylesheetReader.Advance(2);
return _ignoreComments
? DataBlock(_stylesheetReader.Next)
: CommentBlock.Close;
}
return Block.Delim(current);
}
case Specification.Solidus:
current = _stylesheetReader.Next;
return current == Specification.Asterisk
? Comment(_stylesheetReader.Next)
: Block.Delim(_stylesheetReader.Previous);
case Specification.ReverseSolidus:
current = _stylesheetReader.Next;
if (current.IsLineBreak() || current == Specification.EndOfFile)
{
ErrorHandler(current == Specification.EndOfFile
? ParserError.EndOfFile
: ParserError.UnexpectedLineBreak,
ErrorMessages.LineBreakEof);
return Block.Delim(_stylesheetReader.Previous);
}
return IdentStart(_stylesheetReader.Previous);
case Specification.Colon:
return SpecialCharacter.Colon;
case Specification.Simicolon:
return SpecialCharacter.Semicolon;
case Specification.LessThan:
current = _stylesheetReader.Next;
if (current == Specification.Em)
{
current = _stylesheetReader.Next;
if (current == Specification.MinusSign)
{
current = _stylesheetReader.Next;
if (current == Specification.MinusSign)
{
return _ignoreComments
? DataBlock(_stylesheetReader.Next)
: CommentBlock.Open;
}
current = _stylesheetReader.Previous;
}
current = _stylesheetReader.Previous;
}
return Block.Delim(_stylesheetReader.Previous);
case Specification.At:
return AtKeywordStart(_stylesheetReader.Next);
case Specification.SquareBracketOpen:
return BracketBlock.OpenSquare;
case Specification.SquareBracketClose:
return BracketBlock.CloseSquare;
case Specification.Accent:
current = _stylesheetReader.Next;
return current == Specification.EqualSign
? MatchBlock.Prefix
: Block.Delim(_stylesheetReader.Previous);
case Specification.CurlyBraceOpen:
return BracketBlock.OpenCurly;
case Specification.CurlyBraceClose:
return BracketBlock.CloseCurly;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return NumberStart(current);
case 'U':
case 'u':
current = _stylesheetReader.Next;
if (current == Specification.PlusSign)
{
current = _stylesheetReader.Next;
if (current.IsHex() || current == Specification.QuestionMark)
return UnicodeRange(current);
current = _stylesheetReader.Previous;
}
return IdentStart(_stylesheetReader.Previous);
case Specification.Pipe:
current = _stylesheetReader.Next;
if (current == Specification.EqualSign)
{
return MatchBlock.Dash;
}
if (current == Specification.Pipe)
{
return Block.Column;
}
return Block.Delim(_stylesheetReader.Previous);
case Specification.Tilde:
current = _stylesheetReader.Next;
if (current == Specification.EqualSign)
{
return MatchBlock.Include;
}
return Block.Delim(_stylesheetReader.Previous);
case Specification.EndOfFile:
return null;
case Specification.Em:
current = _stylesheetReader.Next;
return current == Specification.EqualSign
? MatchBlock.Not
: Block.Delim(_stylesheetReader.Previous);
default:
return current.IsNameStart()
? IdentStart(current)
: Block.Delim(current);
}
}
private Block DoubleQuoteString(char current)
{
while (true)
{
switch (current)
{
case Specification.DoubleQuote:
case Specification.EndOfFile:
return StringBlock.Plain(FlushBuffer());
case Specification.FormFeed:
case Specification.LineFeed:
ErrorHandler(ParserError.UnexpectedLineBreak, ErrorMessages.DoubleQuotedString);
_stylesheetReader.Back();
return StringBlock.Plain(FlushBuffer(), true);
case Specification.ReverseSolidus:
current = _stylesheetReader.Next;
if (current.IsLineBreak())
{
_buffer.AppendLine();
}
else if (current != Specification.EndOfFile)
{
_buffer.Append(ConsumeEscape(current));
}
else
{
ErrorHandler(ParserError.EndOfFile, ErrorMessages.DoubleQuotedStringEof);
_stylesheetReader.Back();
return StringBlock.Plain(FlushBuffer(), true);
}
break;
default:
_buffer.Append(current);
break;
}
current = _stylesheetReader.Next;
}
}
private Block SingleQuoteString(char current)
{
while (true)
{
switch (current)
{
case Specification.SingleQuote:
case Specification.EndOfFile:
return StringBlock.Plain(FlushBuffer());
case Specification.FormFeed:
case Specification.LineFeed:
ErrorHandler(ParserError.UnexpectedLineBreak, ErrorMessages.SingleQuotedString);
_stylesheetReader.Back();
return (StringBlock.Plain(FlushBuffer(), true));
case Specification.ReverseSolidus:
current = _stylesheetReader.Next;
if (current.IsLineBreak())
{
_buffer.AppendLine();
}
else if (current != Specification.EndOfFile)
{
_buffer.Append(ConsumeEscape(current));
}
else
{
ErrorHandler(ParserError.EndOfFile, ErrorMessages.SingleQuotedStringEof);
_stylesheetReader.Back();
return (StringBlock.Plain(FlushBuffer(), true));
}
break;
default:
_buffer.Append(current);
break;
}
current = _stylesheetReader.Next;
}
}
private Block HashStart(char current)
{
if (current.IsNameStart())
{
_buffer.Append(current);
return HashRest(_stylesheetReader.Next);
}
if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
return HashRest(_stylesheetReader.Next);
}
if (current != Specification.ReverseSolidus)
{
_stylesheetReader.Back();
return Block.Delim(Specification.Hash);
}
ErrorHandler(ParserError.InvalidCharacter, ErrorMessages.InvalidCharacterAfterHash);
return Block.Delim(Specification.Hash);
}
private Block HashRest(char current)
{
while (true)
{
if (current.IsName())
{
_buffer.Append(current);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
else if (current == Specification.ReverseSolidus)
{
ErrorHandler(ParserError.InvalidCharacter, ErrorMessages.InvalidCharacterAfterHash);
_stylesheetReader.Back();
return SymbolBlock.Hash(FlushBuffer());
}
else
{
_stylesheetReader.Back();
return SymbolBlock.Hash(FlushBuffer());
}
current = _stylesheetReader.Next;
}
}
private Block Comment(char current)
{
while (true)
{
switch (current)
{
case Specification.Asterisk:
current = _stylesheetReader.Next;
if (current == Specification.Solidus)
{
return DataBlock(_stylesheetReader.Next);
}
break;
case Specification.Solidus:
{
if (_stylesheetReader.Previous == Specification.Asterisk)
{
return DataBlock(_stylesheetReader.Next);
}
current = _stylesheetReader.Next;
break;
}
case Specification.EndOfFile:
ErrorHandler(ParserError.EndOfFile, ErrorMessages.ExpectedCommentEnd);
return DataBlock(current);
}
current = _stylesheetReader.Next;
}
}
private Block AtKeywordStart(char current)
{
if (current == Specification.MinusSign)
{
current = _stylesheetReader.Next;
if (current.IsNameStart() || IsValidEscape(current))
{
_buffer.Append(Specification.MinusSign);
return AtKeywordRest(current);
}
_stylesheetReader.Back(2);
return Block.Delim(Specification.At);
}
if (current.IsNameStart())
{
_buffer.Append(current);
return AtKeywordRest(_stylesheetReader.Next);
}
if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
return AtKeywordRest(_stylesheetReader.Next);
}
_stylesheetReader.Back();
return Block.Delim(Specification.At);
}
private Block AtKeywordRest(char current)
{
while (true)
{
if (current.IsName())
{
_buffer.Append(current);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
else
{
_stylesheetReader.Back();
return SymbolBlock.At(FlushBuffer());
}
current = _stylesheetReader.Next;
}
}
private Block IdentStart(char current)
{
if (current == Specification.MinusSign)
{
current = _stylesheetReader.Next;
if (current.IsNameStart() || IsValidEscape(current))
{
_buffer.Append(Specification.MinusSign);
return IdentRest(current);
}
_stylesheetReader.Back();
return Block.Delim(Specification.MinusSign);
}
if (current.IsNameStart())
{
_buffer.Append(current);
return IdentRest(_stylesheetReader.Next);
}
if (current != Specification.ReverseSolidus)
{
return DataBlock(current);
}
if (!IsValidEscape(current))
{
return DataBlock(current);
}
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
return IdentRest(_stylesheetReader.Next);
}
private Block IdentRest(char current)
{
while (true)
{
if (current.IsName())
{
_buffer.Append(current);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
else if (current == Specification.ParenOpen)
{
switch (_buffer.ToString().ToLower())
{
case "url":
_buffer.Length = 0;
return UrlStart(_stylesheetReader.Next);//, GrammarSegment.Url);
case "domain":
_buffer.Length = 0;
return UrlStart(_stylesheetReader.Next);//, GrammarSegment.Domain);
case "url-prefix":
_buffer.Length = 0;
return UrlStart(_stylesheetReader.Next);//, GrammarSegment.UrlPrefix);
default:
return SymbolBlock.Function(FlushBuffer());
}
}
else
{
_stylesheetReader.Back();
return SymbolBlock.Ident(FlushBuffer());
}
current = _stylesheetReader.Next;
}
}
private Block NumberStart(char current)
{
while (true)
{
switch (current)
{
case Specification.MinusSign:
case Specification.PlusSign:
_buffer.Append(current);
current = _stylesheetReader.Next;
if (current == Specification.Period)
{
_buffer.Append(current);
_buffer.Append(_stylesheetReader.Next);
return NumberFraction(_stylesheetReader.Next);
}
_buffer.Append(current);
return NumberRest(_stylesheetReader.Next);
case Specification.Period:
_buffer.Append(current);
_buffer.Append(_stylesheetReader.Next);
return NumberFraction(_stylesheetReader.Next);
default:
if (current.IsDigit())
{
_buffer.Append(current);
return NumberRest(_stylesheetReader.Next);
}
break;
}
current = _stylesheetReader.Next;
}
}
private Block NumberRest(char current)
{
while (true)
{
if (current.IsDigit())
{
_buffer.Append(current);
}
else if (current.IsNameStart())
{
var number = FlushBuffer();
_buffer.Append(current);
return Dimension(_stylesheetReader.Next, number);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
var number = FlushBuffer();
_buffer.Append(ConsumeEscape(current));
return Dimension(_stylesheetReader.Next, number);
}
else
{
break;
}
current = _stylesheetReader.Next;
}
switch (current)
{
case Specification.Period:
current = _stylesheetReader.Next;
if (current.IsDigit())
{
_buffer.Append(Specification.Period).Append(current);
return NumberFraction(_stylesheetReader.Next);
}
_stylesheetReader.Back();
return Block.Number(FlushBuffer());
case '%':
return UnitBlock.Percentage(FlushBuffer());
case 'e':
case 'E':
return NumberExponential(current);
case Specification.MinusSign:
return NumberDash(current);
default:
_stylesheetReader.Back();
return Block.Number(FlushBuffer());
}
}
private Block NumberFraction(char current)
{
while (true)
{
if (current.IsDigit())
{
_buffer.Append(current);
}
else if (current.IsNameStart())
{
var number = FlushBuffer();
_buffer.Append(current);
return Dimension(_stylesheetReader.Next, number);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
var number = FlushBuffer();
_buffer.Append(ConsumeEscape(current));
return Dimension(_stylesheetReader.Next, number);
}
else
{
break;
}
current = _stylesheetReader.Next;
}
switch (current)
{
case 'e':
case 'E':
return NumberExponential(current);
case '%':
return UnitBlock.Percentage(FlushBuffer());
case Specification.MinusSign:
return NumberDash(current);
default:
_stylesheetReader.Back();
return Block.Number(FlushBuffer());
}
}
private Block Dimension(char current, string number)
{
while (true)
{
if (current.IsName())
{
_buffer.Append(current);
}
else if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
else
{
_stylesheetReader.Back();
return UnitBlock.Dimension(number, FlushBuffer());
}
current = _stylesheetReader.Next;
}
}
private Block SciNotation(char current)
{
while (true)
{
if (current.IsDigit())
{
_buffer.Append(current);
}
else
{
_stylesheetReader.Back();
return Block.Number(FlushBuffer());
}
current = _stylesheetReader.Next;
}
}
private Block UrlStart(char current)
{
while (current.IsSpaceCharacter())
{
current = _stylesheetReader.Next;
}
switch (current)
{
case Specification.EndOfFile:
ErrorHandler(ParserError.EndOfFile, ErrorMessages.InvalidUrlEnd);
return StringBlock.Url(string.Empty, true);
case Specification.DoubleQuote:
return DoubleQuotedUrl(_stylesheetReader.Next);
case Specification.SingleQuote:
return SingleQuoteUrl(_stylesheetReader.Next);
case ')':
return StringBlock.Url(string.Empty);
default:
return UnquotedUrl(current);
}
}
private Block DoubleQuotedUrl(char current)
{
while (true)
{
if (current.IsLineBreak())
{
ErrorHandler(ParserError.UnexpectedLineBreak, ErrorMessages.InvalidUrlEnd);
return BadUrl(_stylesheetReader.Next);
}
if (Specification.EndOfFile == current)
{
return StringBlock.Url(FlushBuffer());
}
if (current == Specification.DoubleQuote)
{
return UrlEnd(_stylesheetReader.Next);
}
if (current == Specification.ReverseSolidus)
{
current = _stylesheetReader.Next;
if (current == Specification.EndOfFile)
{
_stylesheetReader.Back(2);
ErrorHandler(ParserError.EndOfFile, ErrorMessages.InvalidUrlEnd);
return StringBlock.Url(FlushBuffer(), true);
}
if (current.IsLineBreak())
{
_buffer.AppendLine();
}
else
{
_buffer.Append(ConsumeEscape(current));
}
}
else
{
_buffer.Append(current);
}
current = _stylesheetReader.Next;
}
}
private Block SingleQuoteUrl(char current)
{
while (true)
{
if (current.IsLineBreak())
{
ErrorHandler(ParserError.UnexpectedLineBreak, ErrorMessages.SingleQuotedString);
return BadUrl(_stylesheetReader.Next);
}
if (Specification.EndOfFile == current)
{
return StringBlock.Url(FlushBuffer());
}
if (current == Specification.SingleQuote)
{
return UrlEnd(_stylesheetReader.Next);
}
if (current == Specification.ReverseSolidus)
{
current = _stylesheetReader.Next;
if (current == Specification.EndOfFile)
{
_stylesheetReader.Back(2);
ErrorHandler(ParserError.EndOfFile, ErrorMessages.SingleQuotedString);
return StringBlock.Url(FlushBuffer(), true);
}
if (current.IsLineBreak())
{
_buffer.AppendLine();
}
else
{
_buffer.Append(ConsumeEscape(current));
}
}
else
{
_buffer.Append(current);
}
current = _stylesheetReader.Next;
}
}
private Block UnquotedUrl(char current)
{
while (true)
{
if (current.IsSpaceCharacter())
{
return UrlEnd(_stylesheetReader.Next);
}
if (current == Specification.ParenClose || current == Specification.EndOfFile)
{
return StringBlock.Url(FlushBuffer());
}
if (current == Specification.DoubleQuote || current == Specification.SingleQuote ||
current == Specification.ParenOpen || current.IsNonPrintable())
{
ErrorHandler(ParserError.InvalidCharacter, ErrorMessages.InvalidUrlQuote);
return BadUrl(_stylesheetReader.Next);
}
if (current == Specification.ReverseSolidus)
{
if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
else
{
ErrorHandler(ParserError.InvalidCharacter, ErrorMessages.InvalidUrlCharacter);
return BadUrl(_stylesheetReader.Next);
}
}
else
{
_buffer.Append(current);
}
current = _stylesheetReader.Next;
}
}
private Block UrlEnd(char current)
{
while (true)
{
if (current == Specification.ParenClose)
{
return StringBlock.Url(FlushBuffer());
}
if (!current.IsSpaceCharacter())
{
ErrorHandler(ParserError.InvalidCharacter, ErrorMessages.InvalidUrlCharacter);
return BadUrl(current);
}
current = _stylesheetReader.Next;
}
}
private Block BadUrl(char current)
{
while (true)
{
if (current == Specification.EndOfFile)
{
ErrorHandler(ParserError.EndOfFile, ErrorMessages.InvalidUrlEnd);
return StringBlock.Url(FlushBuffer(), true);
}
if (current == Specification.ParenClose)
{
return StringBlock.Url(FlushBuffer(), true);
}
if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
_buffer.Append(ConsumeEscape(current));
}
current = _stylesheetReader.Next;
}
}
private Block UnicodeRange(char current)
{
for (var i = 0; i < 6; i++)
{
if (!current.IsHex())
{
break;
}
_buffer.Append(current);
current = _stylesheetReader.Next;
}
if (_buffer.Length != 6)
{
for (var i = 0; i < 6 - _buffer.Length; i++)
{
if (current != Specification.QuestionMark)
{
current = _stylesheetReader.Previous;
break;
}
_buffer.Append(current);
current = _stylesheetReader.Next;
}
var range = FlushBuffer();
var start = range.Replace(Specification.QuestionMark, '0');
var end = range.Replace(Specification.QuestionMark, 'F');
return Block.Range(start, end);
}
if (current == Specification.MinusSign)
{
current = _stylesheetReader.Next;
if (current.IsHex())
{
var start = _buffer.ToString();
_buffer.Length = 0;
for (var i = 0; i < 6; i++)
{
if (!current.IsHex())
{
current = _stylesheetReader.Previous;
break;
}
_buffer.Append(current);
current = _stylesheetReader.Next;
}
var end = FlushBuffer();
return Block.Range(start, end);
}
_stylesheetReader.Back(2);
return Block.Range(FlushBuffer(), null);
}
_stylesheetReader.Back();
return Block.Range(FlushBuffer(), null);
}
private string FlushBuffer()
{
var value = _buffer.ToString();
_buffer.Length = 0;
return value;
}
private Block NumberExponential(char current)
{
current = _stylesheetReader.Next;
if (current.IsDigit())
{
_buffer.Append('e').Append(current);
return SciNotation(_stylesheetReader.Next);
}
if (current == Specification.PlusSign || current == Specification.MinusSign)
{
var op = current;
current = _stylesheetReader.Next;
if (current.IsDigit())
{
_buffer.Append('e').Append(op).Append(current);
return SciNotation(_stylesheetReader.Next);
}
_stylesheetReader.Back();
}
current = _stylesheetReader.Previous;
var number = FlushBuffer();
_buffer.Append(current);
return Dimension(_stylesheetReader.Next, number);
}
private Block NumberDash(char current)
{
current = _stylesheetReader.Next;
if (current.IsNameStart())
{
var number = FlushBuffer();
_buffer.Append(Specification.MinusSign).Append(current);
return Dimension(_stylesheetReader.Next, number);
}
if (IsValidEscape(current))
{
current = _stylesheetReader.Next;
var number = FlushBuffer();
_buffer.Append(Specification.MinusSign).Append(ConsumeEscape(current));
return Dimension(_stylesheetReader.Next, number);
}
_stylesheetReader.Back(2);
return Block.Number(FlushBuffer());
}
private string ConsumeEscape(char current)
{
if (!current.IsHex())
{
return current.ToString(CultureInfo.InvariantCulture);
}
var escape = new List<Char>();
for (var i = 0; i < 6; i++)
{
escape.Add(current);
current = _stylesheetReader.Next;
if (!current.IsHex())
{
break;
}
}
current = _stylesheetReader.Previous;
var code = int.Parse(new string(escape.ToArray()), NumberStyles.HexNumber);
return Char.ConvertFromUtf32(code);
}
private bool IsValidEscape(char current)
{
if (current != Specification.ReverseSolidus)
{
return false;
}
current = _stylesheetReader.Next;
_stylesheetReader.Back();
if (current == Specification.EndOfFile)
{
return false;
}
return !current.IsLineBreak();
}
internal bool IgnoreWhitespace
{
get { return _ignoreWhitespace; }
set { _ignoreWhitespace = value; }
}
internal bool IgnoreComments
{
get { return _ignoreComments; }
set { _ignoreComments = value; }
}
internal StylesheetReader Stream
{
get { return _stylesheetReader; }
}
internal IEnumerable<Block> Tokens
{
get
{
while (true)
{
var token = DataBlock(_stylesheetReader.Current);
if (token == null)
{
yield break;
}
_stylesheetReader.Advance();
yield return token;
}
}
}
}
}

// ReSharper disable once CheckNamespace
namespace ExCSS
{
internal static class RuleTypes
{
internal const string CharacterSet = "charset";
internal const string Keyframes = "keyframes";
internal const string Media = "media";
internal const string Page = "page";
internal const string Import = "import";
internal const string FontFace = "font-face";
internal const string Namespace = "namespace";
internal const string Supports = "supports";
internal const string Document = "document";
}
internal static class PseudoSelectorPrefix
{
internal const string NthChildOdd = "odd";
internal const string NthChildEven = "even";
internal const string NthChildN = "n";
internal const string PseudoFunctionNthchild = "nth-child";
internal const string PseudoFunctionNthlastchild = "nth-last-child";
internal const string PseudoFunctionNthOfType = "nth-of-type";
internal const string PseudoFunctionNthLastOfType = "nth-last-of-type";
internal const string PseudoRoot = "root";
internal const string PseudoFirstOfType = "first-of-type";
internal const string PseudoLastoftype = "last-of-type";
internal const string PseudoOnlychild = "only-child";
internal const string PseudoOnlyOfType = "only-of-type";
internal const string PseudoFirstchild = "first-child";
internal const string PseudoLastchild = "last-child";
internal const string PseudoEmpty = "empty";
internal const string PseudoLink = "link";
internal const string PseudoVisited = "visited";
internal const string PseudoActive = "active";
internal const string PseudoHover = "hover";
internal const string PseudoFocus = "focus";
internal const string PseudoTarget = "target";
internal const string PseudoEnabled = "enabled";
internal const string PseudoDisabled = "disabled";
internal const string PseudoChecked = "checked";
internal const string PseudoUnchecked = "unchecked";
internal const string PseudoIndeterminate = "indeterminate";
internal const string PseudoDefault = "default";
internal const string PseudoValid = "valid";
internal const string PseudoInvalid = "invalid";
internal const string PseudoRequired = "required";
internal const string PseudoInrange = "in-range";
internal const string PseudoOutofrange = "out-of-range";
internal const string PseudoOptional = "optional";
internal const string PseudoReadonly = "read-only";
internal const string PseudoReadwrite = "read-write";
internal const string PseudoFunctionDir = "dir";
internal const string PseudoFunctionNot = "not";
internal const string PseudoFunctionLang = "lang";
internal const string PseudoFunctionContains = "contains";
internal const string PseudoElementBefore = "before";
internal const string PseudoElementAfter = "after";
internal const string PseudoElementSelection = "selection";
internal const string PseudoElementFirstline = "first-line";
internal const string PseudoElementFirstletter = "first-letter";
}
internal static class ErrorMessages
{
internal const string InvalidCharacter = "Invalid character detected.";
internal const string LineBreakEof = "Unexpected line break or EOF.";
internal const string UnexpectedCommentToken = "The input element is unexpected and has been ignored.";
internal const string DoubleQuotedString = "Expected double quoted string to terminate before form feed or line feed.";
internal const string DoubleQuotedStringEof = "Expected double quoted string to terminate before end of file.";
internal const string SingleQuotedString = "Expected single quoted string to terminate before form feed or line feed.";
internal const string SingleQuotedStringEof = "Expected single quoted string to terminate before end of file.";
internal const string InvalidCharacterAfterHash = "Invalid character after #.";
internal const string InvalidIdentAfterHash = "Invalid character after #.";
internal const string InvalidUrlEnd = "Expected URL to terminate before line break or end of file.";
internal const string InvalidUrlQuote = "Expected quotation or open paren in URL.";
internal const string InvalidUrlCharacter = "Invalid character in URL.";
internal const string ExpectedCommentEnd = "Expected comment to close before end of file.";
internal const string Default = "An unexpected error occurred.";
}
public enum Combinator
{
Child,
Descendent,
AdjacentSibling,
Sibling,
Namespace
}
internal enum GrammarSegment
{
String,
Url,
UrlPrefix,
Domain,
Hash, //#
AtRule, //@
Ident,
Function,
Number,
Percentage,
Dimension,
Range,
CommentOpen,
CommentClose,
Column,
Delimiter,
IncludeMatch, //~=
DashMatch, // |=
PrefixMatch, // ^=
SuffixMatch, // $=
SubstringMatch, // *=
NegationMatch, // !=
ParenOpen,
ParenClose,
CurlyBraceOpen,
CurlyBracketClose,
SquareBraceOpen,
SquareBracketClose,
Colon,
Comma,
Semicolon,
Whitespace
}
public enum RuleType
{
Unknown = 0,
Style = 1,
Charset = 2,
Import = 3,
Media = 4,
FontFace = 5,
Page = 6,
Keyframes = 7,
Keyframe = 8,
Namespace = 10,
CounterStyle = 11,
Supports = 12,
Document = 13,
FontFeatureValues = 14,
Viewport = 15,
RegionStyle = 16
}
public enum UnitType
{
Unknown = 0,
Number = 1,
Percentage = 2,
Ems = 3,
Exs = 4,
Pixel = 5,
Centimeter = 6,
Millimeter = 7,
Inch = 8,
Point = 9,
Percent = 10,
Degree = 11,
Radian = 12,
Grad = 13,
Millisecond = 14,
Second = 15,
Hertz = 16,
KiloHertz = 17,
Dimension = 18,
String = 19,
Uri = 20,
Ident = 21,
Attribute = 22,
Counter = 23,
Rect = 24,
RGB = 25,
ViewportWidth = 26,
ViewportHeight = 28,
ViewportMin = 29,
ViewportMax = 30,
Turn = 31,
}
public enum DocumentFunction
{
Url,
UrlPrefix,
Domain,
RegExp
}
public enum DirectionMode
{
LeftToRight,
RightToLeft
}
public enum ParserError
{
EndOfFile,
UnexpectedLineBreak,
InvalidCharacter,
UnexpectedCommentToken
}
internal enum SelectorOperation
{
Data,
Attribute,
AttributeOperator,
AttributeValue,
AttributeEnd,
Class,
PseudoClass,
PseudoClassFunction,
PseudoClassFunctionEnd,
PseudoElement
}
internal enum ParsingContext
{
DataBlock,
InSelector,
InDeclaration,
AfterProperty,
BeforeValue,
InValuePool,
InValueList,
InSingleValue,
InMediaList,
InMediaValue,
BeforeImport,
BeforeCharset,
BeforeNamespacePrefix,
AfterNamespacePrefix,
BeforeFontFace,
FontfaceData,
FontfaceProperty,
AfterInstruction,
InCondition,
BeforeKeyframesName,
BeforeKeyframesData,
KeyframesData,
InKeyframeText,
BeforePageSelector,
BeforeDocumentFunction,
InDocumentFunction,
AfterDocumentFunction,
BetweenDocumentFunctions,
InUnknown,
ValueImportant,
AfterValue,
InHexValue,
InFunction
}
}
using System.Collections.Generic;
namespace ExCSS.Model.Extensions
{
static class CharacterExtensions
{
public static int FromHex(this char character)
{
return character.IsDigit() ? character - 0x30 : character - (character.IsLowercaseAscii() ? 0x57 : 0x37);
}
public static string TrimArray(this char[] array)
{
var start = 0;
var end = array.Length - 1;
while (start < array.Length && array[start].IsSpaceCharacter())
{
start++;
}
while (end > start && array[end].IsSpaceCharacter())
{
end--;
}
return new string(array, start, 1 + end - start);
}
public static string[] SplitOnCommas(this string value)
{
var list = new List<string>();
var buffer = new List<char>();
var chars = value.ToCharArray();
for (var i = 0; i <= chars.Length; i++)
{
if (i == chars.Length || chars[i] == ',')
{
if (buffer.Count <= 0)
{
continue;
}
var token = buffer.ToArray().TrimArray();
if (token.Length != 0)
{
list.Add(token);
}
buffer.Clear();
}
else
{
buffer.Add(chars[i]);
}
}
return list.ToArray();
}
public static string ToHex(this byte num)
{
var characters = new char[2];
var rem = num >> 4;
characters[0] = (char)(rem + (rem < 10 ? 48 : 55));
rem = num - 16 * rem;
characters[1] = (char)(rem + (rem < 10 ? 48 : 55));
return new string(characters);
}
public static char ToHexChar(this byte num)
{
var rem = num & 0x0F;
return (char)(rem + (rem < 10 ? 48 : 55));
}
}
}
\ No newline at end of file
using System;
using System.Text;
namespace ExCSS.Model.Extensions
{
public static class StringExtensions
{
public static string Indent(this string value, bool friendlyForamt, int indentation)
{
if (!friendlyForamt)
{
return value;
}
var tabs = new StringBuilder();
for (var i = 0; i < indentation; i++)
{
tabs.Append("\t");
}
return string.Format("{0}{1}", tabs, value);
}
public static string NewLineIndent(this string value, bool friendlyFormat, int indentation)
{
if (!friendlyFormat)
{
return value;
}
return Environment.NewLine + value.Indent(true, indentation);
}
public static string TrimFirstLine(this string value)
{
return new StringBuilder(value).TrimFirstLine().ToString();
}
public static StringBuilder TrimLastLine(this StringBuilder builder)
{
while (builder[builder.Length-1] == '\r' || builder[builder.Length-1] == '\n' || builder[builder.Length-1] == '\t')
{
builder.Remove(builder.Length - 1, 1);
}
return builder;
}
public static StringBuilder TrimFirstLine(this StringBuilder builder)
{
while (builder[0] == '\r' || builder[0] == '\n' || builder[0] == '\t')
{
builder.Remove(0, 1);
}
return builder;
}
}
}
using System;
using System.Collections.Generic;
namespace ExCSS.Model
{
internal class FunctionBuffer
{
private readonly string _function;
private readonly List<Term> _termList;
private Term _term;
internal FunctionBuffer(string function)
{
_termList = new List<Term>();
_function = function;
}
public List<Term> TermList
{
get { return _termList; }
}
public Term Term
{
get { return _term; }
set { _term = value; }
}
public void Include()
{
if (_term != null)
{
_termList.Add(_term);
}
_term = null;
}
public Term Done()
{
Include();
return BuildFunctionTerm(_function, _termList);
}
private Term BuildFunctionTerm(string name, List<Term> terms)
{
switch (name)
{
case "rgb":
{
if (terms.Count == 3)
{
if (CheckNumber(terms[0]) &&
CheckNumber(terms[1]) &&
CheckNumber(terms[2]))
{
return HtmlColor.FromRgb(
ToByte(terms[0]),
ToByte(terms[1]),
ToByte(terms[2]));
}
}
break;
}
case "rgba":
{
if (terms.Count == 4)
{
if (CheckNumber(terms[0]) &&
CheckNumber(terms[1]) &&
CheckNumber(terms[2]) &&
CheckNumber(terms[3]))
{
return HtmlColor.FromRgba(
ToByte(terms[0]),
ToByte(terms[1]),
ToByte(terms[2]),
ToSingle(terms[3]));
}
}
break;
}
case "hsl":
{
if (_termList.Count == 3)
{
if (CheckNumber(terms[0]) &&
CheckNumber(terms[1]) &&
CheckNumber(terms[2]))
{
return HtmlColor.FromHsl(
ToSingle(terms[0]),
ToSingle(terms[1]),
ToSingle(terms[2]));
}
}
break;
}
}
return new GenericFunction(name, terms);
}
private static bool CheckNumber(Term cssValue)
{
return (cssValue is PrimitiveTerm &&
((PrimitiveTerm)cssValue).PrimitiveType == UnitType.Number);
}
private static Single ToSingle(Term cssValue)
{
var value = ((PrimitiveTerm)cssValue).GetFloatValue(UnitType.Number);
return value.HasValue
? value.Value
: 0f;
}
private static byte ToByte(Single? value)
{
if (value.HasValue)
{
return (byte)Math.Min(Math.Max(value.Value, 0), 255);
}
return 0;
}
private static byte ToByte(Term cssValue)
{
return ToByte(((PrimitiveTerm)cssValue).GetFloatValue(UnitType.Number));
}
}
}
\ No newline at end of file
using System;
using System.Text;
namespace ExCSS.Model
{
internal static class HtmlEncoding
{
internal static string Extract(string content)
{
var position = 0;
content = content.ToLower();
for (var i = position; i < content.Length - 7; i++)
{
if (!content.Substring(i).StartsWith("charset"))
{
continue;
}
position = i + 7;
break;
}
if (position <= 0 || position >= content.Length)
{
return string.Empty;
}
for (var i = position; i < content.Length - 1; i++)
{
if (content[i].IsSpaceCharacter())
{
position++;
}
else
{
break;
}
}
if (content[position] != Specification.EqualSign)
{
return Extract(content.Substring(position));
}
position++;
for (var i = position; i < content.Length; i++)
{
if (content[i].IsSpaceCharacter())
{
position++;
}
else
{
break;
}
}
if (position >= content.Length)
{
return string.Empty;
}
switch (content[position])
{
case Specification.DoubleQuote:
{
content = content.Substring(position + 1);
var index = content.IndexOf(Specification.DoubleQuote);
if (index != -1)
{
return content.Substring(0, index);
}
}
break;
case Specification.SingleQuote:
{
content = content.Substring(position + 1);
var index = content.IndexOf(Specification.SingleQuote);
if (index != -1)
{
return content.Substring(0, index);
}
}
break;
default:
{
content = content.Substring(position);
var index = 0;
for (var i = 0; i < content.Length; i++)
{
if (content[i].IsSpaceCharacter())
{
break;
}
if (content[i] == ';')
{
break;
}
index++;
}
return content.Substring(0, index);
}
}
return string.Empty;
}
internal static bool IsSupported(string charset)
{
return Resolve(charset) != null;
}
internal static Encoding Resolve(string charset)
{
charset = charset.ToLower();
switch (charset)
{
case "unicode-1-1-utf-8":
case "utf-8":
case "utf8":
return Encoding.UTF8;
case "utf-16be":
return Encoding.BigEndianUnicode;
case "utf-16":
case "utf-16le":
return Encoding.Unicode;
case "dos-874":
case "iso-8859-11":
case "iso8859-11":
case "iso885911":
case "tis-620":
case "windows-874":
return Encoding.GetEncoding("windows-874");
case "cp1250":
case "windows-1250":
case "x-cp1250":
return Encoding.GetEncoding("windows-1250");
case "cp1251":
case "windows-1251":
case "x-cp1251":
return Encoding.GetEncoding("windows-1251");
case "ansi_x3.4-1968":
case "ascii":
case "cp1252":
case "cp819":
case "csisolatin1":
case "ibm819":
case "iso-8859-1":
case "iso-ir-100":
case "iso8859-1":
case "iso88591":
case "iso_8859-1":
case "iso_8859-1:1987":
case "l1":
case "latin1":
case "us-ascii":
case "windows-1252":
case "x-cp1252":
return Encoding.GetEncoding("windows-1252");
case "cp1253":
case "windows-1253":
case "x-cp1253":
return Encoding.GetEncoding("windows-1253");
case "cp1254":
case "csisolatin5":
case "iso-8859-9":
case "iso-ir-148":
case "iso8859-9":
case "iso88599":
case "iso_8859-9":
case "iso_8859-9:1989":
case "l5":
case "latin5":
case "windows-1254":
case "x-cp1254":
return Encoding.GetEncoding("windows-1254");
case "cp1255":
case "windows-1255":
case "x-cp1255":
return Encoding.GetEncoding("windows-1255");
case "cp1256":
case "windows-1256":
case "x-cp1256":
return Encoding.GetEncoding("windows-1256");
case "cp1257":
case "windows-1257":
case "x-cp1257":
return Encoding.GetEncoding("windows-1257");
case "cp1258":
case "windows-1258":
case "x-cp1258":
return Encoding.GetEncoding("windows-1258");
case "csmacintosh":
case "mac":
case "macintosh":
case "x-mac-roman":
return Encoding.GetEncoding("macintosh");
case "x-mac-cyrillic":
case "x-mac-ukrainian":
return Encoding.GetEncoding("x-mac-cyrillic");
case "866":
case "cp866":
case "csibm866":
case "ibm866":
return Encoding.GetEncoding("cp866");
case "csisolatin2":
case "iso-8859-2":
case "iso-ir-101":
case "iso8859-2":
case "iso88592":
case "iso_8859-2":
case "iso_8859-2:1987":
case "l2":
case "latin2":
return Encoding.GetEncoding("iso-8859-2");
case "csisolatin3":
case "iso-8859-3":
case "iso-ir-109":
case "iso8859-3":
case "iso88593":
case "iso_8859-3":
case "iso_8859-3:1988":
case "l3":
case "latin3":
return Encoding.GetEncoding("iso-8859-3");
case "csisolatin4":
case "iso-8859-4":
case "iso-ir-110":
case "iso8859-4":
case "iso88594":
case "iso_8859-4":
case "iso_8859-4:1988":
case "l4":
case "latin4":
return Encoding.GetEncoding("iso-8859-4");
case "csisolatincyrillic":
case "cyrillic":
case "iso-8859-5":
case "iso-ir-144":
case "iso8859-5":
case "iso88595":
case "iso_8859-5":
case "iso_8859-5:1988":
return Encoding.GetEncoding("iso-8859-5");
case "arabic":
case "asmo-708":
case "csiso88596e":
case "csiso88596i":
case "csisolatinarabic":
case "ecma-114":
case "iso-8859-6":
case "iso-8859-6-e":
case "iso-8859-6-i":
case "iso-ir-127":
case "iso8859-6":
case "iso88596":
case "iso_8859-6":
case "iso_8859-6:1987":
return Encoding.GetEncoding("iso-8859-6");
case "csisolatingreek":
case "ecma-118":
case "elot_928":
case "greek":
case "greek8":
case "iso-8859-7":
case "iso-ir-126":
case "iso8859-7":
case "iso88597":
case "iso_8859-7":
case "iso_8859-7:1987":
case "sun_eu_greek":
return Encoding.GetEncoding("iso-8859-7");
case "csiso88598e":
case "csisolatinhebrew":
case "hebrew":
case "iso-8859-8":
case "iso-8859-8-e":
case "iso-ir-138":
case "iso8859-8":
case "iso88598":
case "iso_8859-8":
case "iso_8859-8:1988":
case "visual":
return Encoding.GetEncoding("iso-8859-8");
case "csiso88598i":
case "iso-8859-8-i":
case "logical":
return Encoding.GetEncoding("iso-8859-8-i");
case "iso-8859-13":
case "iso8859-13":
case "iso885913":
return Encoding.GetEncoding("iso-8859-13");
case "csisolatin9":
case "iso-8859-15":
case "iso8859-15":
case "iso885915":
case "iso_8859-15":
case "l9":
return Encoding.GetEncoding("iso-8859-15");
case "cskoi8r":
case "koi":
case "koi8":
case "koi8-r":
case "koi8_r":
return Encoding.GetEncoding("koi8-r");
case "koi8-u":
return Encoding.GetEncoding("koi8-u");
case "chinese":
case "csgb2312":
case "csiso58gb231280":
case "gb2312":
case "gb_2312":
case "gb_2312-80":
case "gbk":
case "iso-ir-58":
case "x-gbk":
return Encoding.GetEncoding("x-cp20936");
case "hz-gb-2312":
return Encoding.GetEncoding("hz-gb-2312");
case "gb18030":
return Encoding.GetEncoding("GB18030");
case "big5":
case "big5-hkscs":
case "cn-big5":
case "csbig5":
case "x-x-big5":
return Encoding.GetEncoding("big5");
case "csiso2022jp":
case "iso-2022-jp":
return Encoding.GetEncoding("iso-2022-jp");
case "csiso2022kr":
case "iso-2022-kr":
return Encoding.GetEncoding("iso-2022-kr");
case "iso-2022-cn":
case "iso-2022-cn-ext":
return Encoding.GetEncoding("iso-2022-jp");
default:
return null;
}
}
internal static Encoding Suggest(string local)
{
if (local.Length < 2)
return Encoding.UTF8;
var firstTwo = local.Substring(0, 2).ToLower();
switch (firstTwo)
{
case "ar":
case "cy":
case "fa":
case "hr":
case "kk":
case "mk":
case "or":
case "ro":
case "sr":
case "vi":
return Encoding.UTF8;
case "be":
return Encoding.GetEncoding("iso-8859-5");
case "bg":
case "ru":
case "uk":
return Encoding.GetEncoding("windows-1251");
case "cs":
case "hu":
case "pl":
case "sl":
return Encoding.GetEncoding("iso-8859-2");
case "tr":
case "ku":
return Encoding.GetEncoding("windows-1254");
case "he":
return Encoding.GetEncoding("windows-1255");
case "lv":
return Encoding.GetEncoding("iso-8859-13");
case "ja":// Windows-31J ???? Replaced by something better anyway
return Encoding.UTF8;
case "ko":
return Encoding.GetEncoding("ks_c_5601-1987");
case "lt":
return Encoding.GetEncoding("windows-1257");
case "sk":
return Encoding.GetEncoding("windows-1250");
case "th":
return Encoding.GetEncoding("windows-874");
}
if (local.Equals("zh-CN", StringComparison.OrdinalIgnoreCase))
{
return Encoding.GetEncoding("GB18030");
}
return Encoding.GetEncoding(local.Equals("zh-TW", StringComparison.OrdinalIgnoreCase)
? "big5"
: "windows-1252");
}
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace ExCSS.Model
{
interface ISupportsRuleSets
{
List<RuleSet> RuleSets { get; }
}
}
\ No newline at end of file
namespace ExCSS.Model
{
interface ISupportsSelector
{
BaseSelector Selector { get; set; }
}
}
\ No newline at end of file
namespace ExCSS.Model
{
interface ISupportsDeclarations
{
StyleDeclaration Declarations { get; }
}
}
\ No newline at end of file
namespace ExCSS.Model
{
interface ISupportsMedia
{
MediaTypeList Media { get; }
}
}
\ No newline at end of file
using System.Collections;
using System.Collections.Generic;
using ExCSS.Model.Extensions;
// ReSharper disable once CheckNamespace
namespace ExCSS
{
public class MediaTypeList : IEnumerable<string>
{
private readonly List<string> _media;
private string _buffer;
internal MediaTypeList()
{
_buffer = string.Empty;
_media = new List<string>();
}
public string this[int index]
{
get
{
if (index < 0 || index >= _media.Count)
{
return null;
}
return _media[index];
}
set
{
_media[index] = value;
}
}
public int Count
{
get { return _media.Count; }
}
public string MediaType
{
get { return _buffer; }
set
{
_buffer = string.Empty;
_media.Clear();
if (string.IsNullOrEmpty(value))
{
return;
}
var entries = value.SplitOnCommas();
foreach (var t in entries)
{
AppendMedium(t);
}
}
}
internal MediaTypeList AppendMedium(string newMedium)
{
if (_media.Contains(newMedium))
{
return this;
}
_media.Add(newMedium);
_buffer += (string.IsNullOrEmpty(_buffer) ? string.Empty : ",") + newMedium;
return this;
}
public override string ToString()
{
return ToString(false);
}
public string ToString(bool friendlyFormat, int indentation = 0)
{
return friendlyFormat
? string.Join(", ", _media.ToArray())
: string.Join(",", _media.ToArray());
}
public IEnumerator<string> GetEnumerator()
{
return ((IEnumerable<string>) _media).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using ExCSS.Model;
// ReSharper disable once CheckNamespace
namespace ExCSS
{
public abstract class AggregateRule : RuleSet, ISupportsRuleSets
{
protected AggregateRule()
{
RuleSets = new List<RuleSet>();
}
public List<RuleSet> RuleSets { get; private set; }
}
}
using ExCSS.Model.Extensions;
// ReSharper disable once CheckNamespace
namespace ExCSS
{
public class CharacterSetRule : RuleSet
{
public CharacterSetRule()
{
RuleType = RuleType.Charset;
}
public string Encoding { get; internal set; }
public override string ToString()
{
return ToString(false);
}
public override string ToString(bool friendlyFormat, int indentation = 0)
{
return string.Format("@charset '{0}';", Encoding).NewLineIndent(friendlyFormat, indentation);
}
}
}
// ReSharper disable once CheckNamespace
namespace ExCSS
{
public abstract class ConditionalRule : AggregateRule
{
public virtual string Condition
{
get { return string.Empty; }
set { }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using ExCSS.Model;
using ExCSS.Model.Extensions;
// ReSharper disable once CheckNamespace
namespace ExCSS
{
public sealed class DocumentRule : AggregateRule
{
readonly List<KeyValuePair<DocumentFunction, string>> _conditions;
internal DocumentRule()
{
RuleType = RuleType.Document;
_conditions = new List<KeyValuePair<DocumentFunction, string>>();
}
public string ConditionText
{
get
{
var builder = new StringBuilder();
var concat = false;
foreach (var condition in _conditions)
{
if (concat)
{
builder.Append(',');
}
switch (condition.Key)
{
case DocumentFunction.Url:
builder.Append("url");
break;
case DocumentFunction.UrlPrefix:
builder.Append("url-prefix");
break;
case DocumentFunction.Domain:
builder.Append("domain");
break;
case DocumentFunction.RegExp:
builder.Append("regexp");
break;
}
builder.Append(Specification.ParenOpen);
builder.Append(Specification.DoubleQuote);
builder.Append(condition.Value);
builder.Append(Specification.DoubleQuote);
builder.Append(Specification.ParenClose);
concat = true;
}
return builder.ToString();
}
}
internal List<KeyValuePair<DocumentFunction, string>> Conditions
{
get { return _conditions; }
}
public override string ToString()
{
return ToString(false);
}
public override string ToString(bool friendlyFormat, int indentation = 0)
{
return "@document " + ConditionText + " {" +
RuleSets +
"}".NewLineIndent(friendlyFormat, indentation);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment