public void WriteBlock(CssBlock block, int level) { var prevScope = scope; writer.Write("{"); // Block start var condenced = false; var count = 0; // Write the declarations foreach (var node in block.Children) // TODO: Change to an immutable list? { if (node.Kind == NodeKind.Include) { var b2 = new CssBlock(NodeKind.Block); b2.Add(node); scope = ExpandInclude((IncludeNode)node, b2); foreach (var rule in b2.OfType<CssRule>()) { writer.WriteLine(); WriteRule(rule, level + 1); count++; } } else if (node.Kind == NodeKind.Declaration) { var declaration = (CssDeclaration)node; if (block.Children.Count == 1 && !declaration.Info.NeedsExpansion(declaration, browserSupport)) { condenced = true; writer.Write(" "); WriteDeclaration(declaration, 0); } else { if (count == 0) writer.WriteLine(); WritePatchedDeclaration(declaration, level + 1); } } else if (node.Kind == NodeKind.Rule) // Nested rule { if (count == 0) writer.WriteLine(); var childRule = (CssRule)node; WriteRule(childRule, level + 1); } else if (node.Kind == NodeKind.If) { EvaluateIf((IfBlock)node, level + 1); } if (!condenced) { writer.WriteLine(); } count++; } // Limit to declaration if (condenced) { writer.Write(" "); } else { Indent(level); } writer.Write("}"); // Block end prevScope = scope; }
public CssBlock ReadBlock(CssBlock block) { var blockStart = Read(TokenKind.BlockStart, LexicalMode.Block); // Read { ReadTrivia(); while(current.Kind != TokenKind.BlockEnd) { if (isEnd) throw new UnbalancedBlock(LexicalMode.Block, blockStart); // A list of delarations or blocks if (current.Kind == TokenKind.AtSymbol) { Read(); // Read @ var name = tokenizer.Read(); // Name switch (name.Text) { case "include" : block.Add(ReadInclude()); continue; case "if" : block.Add(ReadIfRule()); continue; } } if (current.Kind == TokenKind.Dollar) { block.Add(ReadAssignment()); continue; } var statement = ReadSpan(); switch (current.Kind) { case TokenKind.Colon : block.Add(ReadDeclarationFromName(statement)); break; // DeclarationName case TokenKind.BlockStart : block.Add(ReadRuleBlock(new CssSelector(statement))); break; case TokenKind.BlockEnd : break; // TODO: Figure out where we missed reading the semicolon TEMP case TokenKind.Semicolon : tokenizer.Read(); break; default: throw new UnexpectedTokenException(LexicalMode.Block, current); } } tokenizer.Read(); // read } block.Trailing = ReadTrivia(); return block; }