public static StyleSheet Parse(TextReader reader, CssContext context = null) { var sheet = new StyleSheet(context ?? new CssContext()); var rules = new List<CssRule>(); IList<Browser> browsers = null; using (var parser = new CssParser(reader)) { foreach (var node in parser.ReadNodes()) { if (node.Kind == NodeKind.Mixin) { var mixin = (MixinNode)node; sheet.Context.Mixins.Add(mixin.Name, mixin); } else if (node.Kind == NodeKind.Directive) { var directive = (CssDirective)node; if (directive.Name == "support") { var parts = directive.Value.Split(Seperators.Space); // SpaceArray... BrowserType browserType; if (Enum.TryParse(parts[0].Trim(), true, out browserType)) { if (browsers == null) { browsers = new List<Browser>(); } var browserVersion = float.Parse(parts[parts.Length - 1].Trim(' ', '+')); browsers.Add(new Browser(browserType, browserVersion)); } } } else { sheet.AddChild(node); } } if (browsers != null) { sheet.Context.SetCompatibility(browsers.ToArray()); } } return sheet; }
public void WriteRoot(StyleSheet sheet) { importCount++; if (importCount > 200) throw new Exception("Exceded importCount of 200"); var i = 0; foreach (var node in sheet.Children) { if (node.Kind == NodeKind.If) { EvaluateIf((IfBlock)node); continue; } if (node.Kind == NodeKind.Comment) { if (i != 0) writer.WriteLine(); i++; WriteComment((CssComment)node); continue; } if (node.Kind == NodeKind.Assignment) { var variable = (CssAssignment)node; scope[variable.Name] = variable.Value; continue; } var rule = node as CssRule; if (rule == null) continue; if (i != 0) writer.WriteLine(); i++; if (rule.Type == RuleType.Import) { var importRule = (ImportRule)rule; if (!importRule.Url.IsPath || resolver == null) { WriteImportRule(importRule); } else { InlineImport(importRule, sheet); } } else { WriteRule(rule); } } }
public void InlineImport(ImportRule importRule, StyleSheet sheet) { // var relativePath = importRule.Url; var absolutePath = importRule.Url.GetAbsolutePath(resolver.ScopedPath); if (absolutePath[0] == '/') { absolutePath = absolutePath.TrimStart(Seperators.ForwardSlash); } // Assume to be scss if there is no extension if (!absolutePath.Contains('.')) { absolutePath += ".scss"; } writer.WriteLine(); writer.WriteLine("/* " + absolutePath + " */"); var stream = resolver.Open(absolutePath); if (stream == null) { writer.WriteLine("/* NOT FOUND */"); return; } if (absolutePath.EndsWith(".scss")) { try { var css = StyleSheet.Parse(stream, context); WriteRoot(css); } catch (SyntaxException ex) { writer.WriteLine("body, html { background-color: red !important; }"); writer.WriteLine("body * { display: none; }"); writer.WriteLine($"/* --- Parse Error in '{absolutePath}' : {ex.Message} "); if (ex.Lines != null) { foreach (var line in ex.Lines) { writer.Write(line.Number.ToString().PadLeft(4)); // 1 writer.Write(". "); if (line.Number == ex.Location.Line) { writer.Write("* "); } writer.WriteLine(line.Text); } } writer.Write("*/"); return; } } else { // Copy the file line by line... using (var reader = new StreamReader(stream)) { string line; while ((line = reader.ReadLine()) != null) { writer.WriteLine(line); } } } }