public CssNode(CssNodeType type, CssNode parent, string text) { Type = type; Parent = parent; TextBuilder = new StringBuilder(text); }
internal static CssNode GetAst(string cssDocument) { var doc = new CssNode(CssNodeType.Document, null, ""); var currentNode = doc; var tokens = Tokenize(cssDocument).ToList(); for (var i = 0; i < tokens.Count;) { var t = tokens[i++]; CssNode n; switch (t.Type) { case CssTokenType.At: if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.NamespaceDeclaration, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.Identifier: if (currentNode.Type == CssNodeType.NamespaceDeclaration) { n = new CssNode(CssNodeType.NamespaceKeyword, currentNode, "@" + t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceKeyword) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.NamespaceAlias, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Selectors) { n = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(n); var fragment = new CssNode(CssNodeType.SelectorFragment, n, t.Text); n.Children.Add(fragment); currentNode = fragment; } else if (currentNode.Type == CssNodeType.Selector) { n = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclarationBlock) { n = new CssNode(CssNodeType.StyleDeclaration, currentNode, ""); currentNode.Children.Add(n); currentNode = n; n = new CssNode(CssNodeType.Key, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Value) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.DoubleQuotes: if (currentNode.Type == CssNodeType.NamespaceKeyword) { currentNode = currentNode.Parent; currentNode.Children.Add(new CssNode(CssNodeType.NamespaceAlias, currentNode, "")); n = new CssNode(CssNodeType.NamespaceValue, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceAlias) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.NamespaceValue, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { n = new CssNode(CssNodeType.Value, currentNode.Parent, ""); currentNode.Children.Add(n); currentNode = n; } if (currentNode.Type == CssNodeType.Value) { n = new CssNode(CssNodeType.DoubleQuoteText, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.DoubleQuoteText) { currentNode = currentNode.Parent; } break; case CssTokenType.SingleQuotes: if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { n = new CssNode(CssNodeType.Value, currentNode.Parent, ""); currentNode.Children.Add(n); currentNode = n; } if (currentNode.Type == CssNodeType.Value) { n = new CssNode(CssNodeType.SingleQuoteText, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.SingleQuoteText) { currentNode = currentNode.Parent; } break; case CssTokenType.Colon: if (currentNode.Type == CssNodeType.Key) { currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Value) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.Semicolon: if (currentNode.Type == CssNodeType.Value) { currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } currentNode = currentNode.Parent; break; case CssTokenType.Dot: if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.NamespaceAlias) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Selectors) { var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; currentNode.Children.Add(new CssNode(CssNodeType.SelectorFragment, currentNode, "." + tokens[i++].Text)); } else if (currentNode.Type == CssNodeType.Selector) { var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, "."); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Key) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.Hash: if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.Selectors) { var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.Selector) { var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, "."); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.AngleBraketClose: if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode.Children.Add(new CssNode(CssNodeType.SelectorFragment, currentNode, ">")); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.ParenthesisOpen: case CssTokenType.ParenthesisClose: if (currentNode.Type == CssNodeType.Value) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.Comma: if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Value) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.Pipe: if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.Key) { currentNode.Text.Append(t.Text); } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } break; case CssTokenType.BraceOpen: currentNode.Text = new StringBuilder(currentNode.Text.ToString().Trim()); if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } else { if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selectors) { currentNode = currentNode.Parent; } n = new CssNode(CssNodeType.StyleDeclarationBlock, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } break; case CssTokenType.BraceClose: if (currentNode.Type == CssNodeType.Value) { currentNode.Text.Append(t.Text); currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.DoubleQuoteText || currentNode.Type == CssNodeType.SingleQuoteText) { currentNode.Text.Append(t.Text); } else { currentNode = currentNode.Parent.Parent; } break; case CssTokenType.Whitespace: currentNode.Text.Append(t.Text); break; } } return(doc); }
private static List <string> GetSelectorStringsFromSelectorsCssNode(CssNode selectors) { return(selectors.Children .Select(x => string.Join(" ", x.Children /* selector-fragment */.Select(y => y.Text))) .ToList()); }
internal static CssNode GetAst(string cssDocument) { var doc = new CssNode(CssNodeType.Document, null, ""); var currentNode = doc; var tokens = Tokenizer.Tokenize(cssDocument).ToList(); for (var i = 0; i < tokens.Count; i++) { var t = tokens[i]; CssNode n; switch (t.Type) { case CssTokenType.At: if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.NamespaceDeclaration, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Value || currentNode.Type == CssNodeType.VariableValue) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.Dollar: if (currentNode.Type == CssNodeType.Document || currentNode.Type == CssNodeType.StyleDeclarationBlock) { n = new CssNode(CssNodeType.VariableDeclaration, currentNode, ""); currentNode.Children.Add(n); currentNode = n; n = new CssNode(CssNodeType.VariableName, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Value) { n = new CssNode(CssNodeType.VariableReference, currentNode, "$"); currentNode.Children.Add(n); currentNode = n; } break; case CssTokenType.Identifier: if (currentNode.Type == CssNodeType.VariableName) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.VariableValue) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.VariableReference) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.NamespaceDeclaration) { n = new CssNode(CssNodeType.NamespaceKeyword, currentNode, "@" + t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceKeyword) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.NamespaceAlias, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Selectors) { n = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(n); var fragment = new CssNode(CssNodeType.SelectorFragment, n, t.Text); n.Children.Add(fragment); currentNode = fragment; } else if (currentNode.Type == CssNodeType.Selector) { n = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclarationBlock) { n = new CssNode(CssNodeType.StyleDeclaration, currentNode, ""); currentNode.Children.Add(n); currentNode = n; n = new CssNode(CssNodeType.Key, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } break; case CssTokenType.DoubleQuotes: if (currentNode.Type == CssNodeType.NamespaceKeyword) { currentNode = currentNode.Parent; currentNode.Children.Add(new CssNode(CssNodeType.NamespaceAlias, currentNode, "")); n = new CssNode(CssNodeType.NamespaceValue, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceAlias) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.NamespaceValue, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { n = new CssNode(CssNodeType.Value, currentNode.Parent, ""); currentNode.Children.Add(n); currentNode = n; } if (currentNode.Type == CssNodeType.Value) { n = new CssNode(CssNodeType.DoubleQuoteText, currentNode, ""); currentNode.Children.Add(n); currentNode = n; i++; do { if (tokens[i].Type == CssTokenType.Backslash) { i++; currentNode.TextBuilder.Append(tokens[i].Text); } else if (tokens[i].Type == CssTokenType.DoubleQuotes) { currentNode = currentNode.Parent; break; } else { currentNode.TextBuilder.Append(tokens[i].Text); } i++; } while (i < tokens.Count); } else if (currentNode.Type == CssNodeType.VariableValue) { i++; do { if (tokens[i].Type == CssTokenType.Backslash) { i++; currentNode.TextBuilder.Append(tokens[i].Text); } else if (tokens[i].Type == CssTokenType.DoubleQuotes) { currentNode = currentNode.Parent; break; } else { currentNode.TextBuilder.Append(tokens[i].Text); } i++; } while (i < tokens.Count); } else if (currentNode.Type == CssNodeType.DoubleQuoteText) { currentNode = currentNode.Parent; } break; case CssTokenType.SingleQuotes: if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { n = new CssNode(CssNodeType.Value, currentNode.Parent, ""); currentNode.Children.Add(n); currentNode = n; } if (currentNode.Type == CssNodeType.Value) { n = new CssNode(CssNodeType.SingleQuoteText, currentNode, ""); currentNode.Children.Add(n); currentNode = n; i++; do { if (tokens[i].Type == CssTokenType.Backslash) { i++; currentNode.TextBuilder.Append(tokens[i].Text); } else if (tokens[i].Type == CssTokenType.SingleQuotes) { currentNode = currentNode.Parent; break; } else { currentNode.TextBuilder.Append(tokens[i].Text); } i++; } while (i < tokens.Count); } else if (currentNode.Type == CssNodeType.SingleQuoteText) { currentNode = currentNode.Parent; } break; case CssTokenType.Colon: if (currentNode.Type == CssNodeType.VariableName) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.VariableValue, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Key) { var nextToken = FirstTokenTypeOf(tokens, i, new[] { CssTokenType.Semicolon, CssTokenType.DoubleQuotes, CssTokenType.BraceOpen }); // normal value if (nextToken == CssTokenType.Semicolon || nextToken == CssTokenType.DoubleQuotes) { currentNode = currentNode.Parent; n = new CssNode(CssNodeType.Value, currentNode, ""); currentNode.Children.Add(n); currentNode = n; i++; while (t.Type == CssTokenType.Whitespace) { i++; t = tokens[i]; } } else // selector { currentNode.TextBuilder.Append(t.Text); } } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.Semicolon: if (currentNode.Type == CssNodeType.VariableReference) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Value) { currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode = currentNode.Parent; } else if (currentNode.Type == CssNodeType.VariableValue) { currentNode = currentNode.Parent; } currentNode = currentNode.Parent; break; case CssTokenType.Dot: if (currentNode.Type == CssNodeType.Document || currentNode.Type == CssNodeType.StyleDeclarationBlock) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.NamespaceAlias) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Selectors) { var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); var selectorFragment = new CssNode(CssNodeType.SelectorFragment, selector, tokens[i].Text); selector.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.Selector) { var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, "."); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Key) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.Hash: if (currentNode.Type == CssNodeType.Document) { n = new CssNode(CssNodeType.StyleRule, currentNode, ""); var selectors = new CssNode(CssNodeType.Selectors, n, ""); n.Children.Add(selectors); currentNode.Children.Add(n); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.Selectors) { var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, t.Text); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.Selector) { var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, "."); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.VariableValue) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.AngleBraketClose: if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode.Children.Add(new CssNode(CssNodeType.SelectorFragment, currentNode, ">")); } break; case CssTokenType.ParenthesisOpen: case CssTokenType.ParenthesisClose: if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Key) // selector { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.Comma: if (currentNode.Type == CssNodeType.Key) { var keyValue = currentNode.Text; var styleDeclaration = currentNode.Parent; styleDeclaration.Children.Remove(currentNode); var subRule = styleDeclaration; subRule.Type = CssNodeType.StyleRule; var selectors = new CssNode(CssNodeType.Selectors, subRule, ""); subRule.Children.Add(selectors); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, keyValue); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.NamespaceValue) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.Pipe: if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode.TextBuilder.Append(t.Text); } else if (currentNode.Type == CssNodeType.Key) { currentNode.TextBuilder.Append(t.Text); } break; case CssTokenType.BraceOpen: if (currentNode.Type == CssNodeType.Key) { var keyValue = currentNode.Text; var styleDeclaration = currentNode.Parent; styleDeclaration.Children.Remove(currentNode); var subRule = styleDeclaration; subRule.Type = CssNodeType.StyleRule; var selectors = new CssNode(CssNodeType.Selectors, subRule, ""); subRule.Children.Add(selectors); currentNode = selectors; var selector = new CssNode(CssNodeType.Selector, currentNode, ""); currentNode.Children.Add(selector); currentNode = selector; var selectorFragment = new CssNode(CssNodeType.SelectorFragment, currentNode, keyValue); currentNode.Children.Add(selectorFragment); currentNode = selectorFragment; } currentNode.TextBuilder = new StringBuilder(currentNode.TextBuilder.ToString().Trim()); if (currentNode.Type == CssNodeType.StyleDeclaration) { n = new CssNode(CssNodeType.Value, currentNode, t.Text); currentNode.Children.Add(n); currentNode = n; } else if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); } else { if (currentNode.Type == CssNodeType.SelectorFragment) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selector) { currentNode = currentNode.Parent; } if (currentNode.Type == CssNodeType.Selectors) { currentNode = currentNode.Parent; } n = new CssNode(CssNodeType.StyleDeclarationBlock, currentNode, ""); currentNode.Children.Add(n); currentNode = n; } break; case CssTokenType.BraceClose: if (currentNode.Type == CssNodeType.Value) { currentNode.TextBuilder.Append(t.Text); currentNode = currentNode.Parent; } else { currentNode = currentNode.Parent.Parent; } break; case CssTokenType.Whitespace: currentNode.TextBuilder.Append(t.Text); break; } } return(doc); }