public string SortStyleSheet(string css) { ICssParser parser = new CssParser(); StyleSheet stylesheet = parser.Parse(css.Trim(), true); CssFormatter formatter = new CssFormatter(); formatter.Options.RemoveLastSemicolon = false; StringBuilder sb = new StringBuilder(stylesheet.Text); var visitor = new CssItemCollector<RuleBlock>(true); stylesheet.Accept(visitor); foreach (RuleBlock rule in visitor.Items.Where(r => r.IsValid).Reverse()) { if (rule.Declarations.Count <= 1) continue; int start = rule.OpenCurlyBrace.AfterEnd; int length = rule.Length - 2; string text = formatter.Format(rule.Text).Trim().Trim('}', '{'); string[] declarations = text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var sorted = SortDeclarations(declarations); sb.Remove(start, length); sb.Insert(start, string.Join("", sorted)); } return sb.ToString(); }
private async static Task ParseDocument() { string fileName = GetSolutionFilePath(); if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName)) { CssParser parser = new CssParser(); StyleSheet stylesheet = parser.Parse(await FileHelpers.ReadAllTextRetry(fileName), false); if (stylesheet.IsValid) { var visitor = new CssItemCollector<AtDirective>(); stylesheet.Accept(visitor); AtDirective at = visitor.Items.SingleOrDefault(a => a.Keyword.Text == _rootDirective); if (at != null) { var visitorPalette = new CssItemCollector<AtDirective>(true); at.Accept(visitorPalette); _directives = visitorPalette.Items.Where(a => a.Keyword.Text != at.Keyword.Text).ToList(); } } InitializeWatcher(fileName); } else { _hasFile = false; } }
private static IEnumerable<ParseItem> GetItems(string filePath, string searchValue) { var cssParser = new CssParser(); StyleSheet ss = cssParser.Parse(File.ReadAllText(filePath), true); return new CssItemAggregator<ParseItem> { (ClassSelector c) => c.Text.Contains(searchValue) ? c : null, (IdSelector c) => c.Text.Contains(searchValue) ? c : null }.Crawl(ss).Where(s => s != null); }
public string Parse(string zenSyntax, ZenType type) { switch (type) { case ZenType.CSS: CssParser cssParser = new CssParser(); return cssParser.Parse(zenSyntax.Trim()); case ZenType.HTML: HtmlParser htmlParser = new HtmlParser(); return htmlParser.Parse(zenSyntax.Trim()); } return null; }
private void ProcessStylesheet(IList <InputGroup> inputGroups, SwitchParser switchParser, string outputPath, Encoding encoding) { var outputBuilder = new StringBuilder(8192); foreach (var inputGroup in inputGroups) { // create and setup parser var parser = new CssParser(); parser.Settings = switchParser.CssSettings; parser.JSSettings = switchParser.JSSettings; parser.CssError += (sender, ea) => { // if the input group is not project, then only report sev-0 errors // regardless, don't show any errors that have a severity lower (greater numeric value) // than the warning level specified. if ((inputGroup.Origin == SourceOrigin.Project || ea.Error.Severity == 0) && ea.Error.Severity <= switchParser.WarningLevel) { LogContextError(ea.Error); } }; // minify input outputBuilder.Append(parser.Parse(inputGroup.Source)); } // write output if (!Log.HasLoggedErrors) { if (!FileWriteOperation(outputPath, switchParser.Clobber, () => { using (var writer = new StreamWriter(outputPath, false, encoding)) { writer.Write(outputBuilder.ToString()); } return(true); })) { // could not write file Log.LogError(Strings.CouldNotWriteOutputFile, outputPath); } } else { Log.LogWarning(Strings.DidNotMinify, outputPath, Strings.ThereWereErrors); } }
public void SupportsShadowVendorPrefixesRule() { var source = @"@supports ( box-shadow: 0 0 2px black ) or ( -moz-box-shadow: 0 0 2px black ) or ( -webkit-box-shadow: 0 0 2px black ) or ( -o-box-shadow: 0 0 2px black ) { }"; var parser = new CssParser(source); parser.Parse(); Assert.AreEqual(1, parser.Result.Rules.Length); Assert.IsInstanceOf <CssSupportsRule>(parser.Result.Rules[0]); var supports = parser.Result.Rules[0] as CssSupportsRule; Assert.AreEqual("(box-shadow: 0 0 2px black) or (-moz-box-shadow: 0 0 2px black) or (-webkit-box-shadow: 0 0 2px black) or (-o-box-shadow: 0 0 2px black)", supports.ConditionText); Assert.IsTrue(supports.IsSupported); }
public void ParseNull() { var errors = new List <ContextError>(); var cssParser = new CssParser(); cssParser.CssError += (sender, ea) => { errors.Add(ea.Error); }; // parse it var results = cssParser.Parse(null); Assert.AreEqual(string.Empty, results); Assert.AreEqual(0, errors.Count); }
public void Can_parse_singlequoted_text_in_attributes() { StyleSheet styleSheet = null; Action action = () => styleSheet = CssParser.Parse(@" Button[Content='Some Content'] { FontWeight: Bold; }"); action.ShouldNotThrow(); styleSheet.Errors.Count.Should().Be(0); styleSheet.Rules.Count.Should().Be(1); styleSheet.Rules[0].SelectorString.Should().Be(@"Button[Content='Some Content']"); styleSheet.Rules[0].DeclarationBlock[0].Property.Should().Be(@"FontWeight"); styleSheet.Rules[0].DeclarationBlock[0].Value.Should().Be(@"Bold"); }
public Element(string tagName, Dictionary <string, string> attributes, IEnumerable <Node> children) { TagName = tagName; Attributes = attributes; foreach (var child in children) { Children.Add(child); } // Parse style attributes as CSS if (Attributes.ContainsKey("style")) { var style = Attributes["style"]; Style = CssParser.Parse(style); } }
public void Can_parse_square_brackets_in_selector() { var styleSheet = CssParser.Parse(@" .test[Text=""hallo""], .test[Text='hallo'], .test[Text=hallo] { Color: #ff00ff; }"); Assert.AreEqual(1, styleSheet.Rules[0].DeclarationBlock.Count); styleSheet.Rules[0].Selectors[0].Value.Should().Be(@".test[Text=""hallo""]"); styleSheet.Rules[1].Selectors[0].Value.Should().Be(@".test[Text='hallo']"); styleSheet.Rules[2].Selectors[0].Value.Should().Be(@".test[Text=hallo]"); Assert.AreEqual(@"#ff00ff", styleSheet.Rules[0].DeclarationBlock[0].Value); }
public void Can_parse_nested_combinator() { var styleSheet = CssParser.Parse(@" .test { > div { Opacity: 0.5; Width: 0; } }"); styleSheet.Rules.Count.Should().Be(2); styleSheet.Rules[1].SelectorString.Should().Be(@".test>div"); styleSheet.Rules[1].DeclarationBlock[0].Value.Should().Be(@"0.5"); styleSheet.Rules[1].DeclarationBlock[1].Value.Should().Be("0"); }
public void TokenImageUrlTest() { const string FileName = @"tokenimageurl.css"; var fileInfo = new FileInfo(Path.Combine(ActualDirectory, FileName)); var styleSheetNode = CssParser.Parse(fileInfo); Assert.IsNotNull(styleSheetNode); var visitor = new ImageAssemblyScanVisitor(fileInfo.FullName, null); styleSheetNode.Accept(visitor); var imageReferencesToAssemble = visitor.DefaultImageAssemblyScanOutput.ImageReferencesToAssemble; Assert.IsNotNull(imageReferencesToAssemble); Assert.AreEqual(0, imageReferencesToAssemble.Count); }
public void Rules_ordered_by_specificity() { var styleSheet = CssParser.Parse(@" .warning#some-element, #an-element, .warning { } .important { } Button { } * { } "); Assert.AreEqual(6, styleSheet.Rules.Count); Assert.AreEqual("*", styleSheet.Rules[0].Selectors[0].Value); Assert.AreEqual("0", styleSheet.Rules[0].Selectors[0].Specificity); Assert.AreEqual("Button", styleSheet.Rules[1].Selectors[0].Value); Assert.AreEqual("1", styleSheet.Rules[1].Selectors[0].Specificity); Assert.AreEqual(".warning", styleSheet.Rules[2].Selectors[0].Value); Assert.AreEqual("1,0", styleSheet.Rules[2].Selectors[0].Specificity); Assert.AreEqual(".important", styleSheet.Rules[3].Selectors[0].Value); Assert.AreEqual("1,0", styleSheet.Rules[3].Selectors[0].Specificity); Assert.AreEqual("#an-element", styleSheet.Rules[4].Selectors[0].Value); Assert.AreEqual("1,0,0", styleSheet.Rules[4].Selectors[0].Specificity); Assert.AreEqual(".warning#some-element", styleSheet.Rules[5].Selectors[0].Value); Assert.AreEqual("1,1,0", styleSheet.Rules[5].Selectors[0].Specificity); var s = new Selector { Value = ".important-button-container>Button" }; Assert.AreEqual("1,1", s.Specificity); }
public void ShouldNotOptimizeFontface() { const string FileName = @"fontface.css"; var styleSheetNode = CssParser.Parse(new FileInfo(Path.Combine(ActualDirectory, FileName))); Assert.IsNotNull(styleSheetNode); MinificationVerifier.VerifyMinification(BaseDirectory, FileName, new List <NodeVisitor> { new OptimizationVisitor { NonMergeRuleSetSelectors = new[] { "@font-face" } } }); PrettyPrintVerifier.VerifyPrettyPrint(BaseDirectory, FileName, new List <NodeVisitor> { new OptimizationVisitor { NonMergeRuleSetSelectors = new[] { "@font-face" } } }); }
private static void Warmup(MarkupExtensionParser markupExtensionParser, string defaultCssNamespace) { // warmup parser markupExtensionParser.Parse("true", Application.Current?.MainWindow ?? new FrameworkElement(), new[] { new CssNamespace("", defaultCssNamespace) }); TypeHelpers.GetPropertyAccessor(typeof(FrameworkElement), "IsLoaded"); var styleSheet = CssParser.Parse("*{Background: #DynamicResource no;}"); var f = new Button(); f.SetValue(Css.StyleSheetProperty, styleSheet); f.Content = new TextBlock(); instance.EnqueueNewElement(f, styleSheet, f); instance.ExecuteApplyStyles(); }
public void RgbCollapse() { const string FileName = @"RgbCollapse.css"; AstNode styleSheetNode = CssParser.Parse(new FileInfo(Path.Combine(ActualDirectory, FileName))); Assert.IsNotNull(styleSheetNode); styleSheetNode = styleSheetNode.Accept(new ColorOptimizationVisitor()); Assert.IsNotNull(styleSheetNode); MinificationVerifier.VerifyMinification(BaseDirectory, FileName, new List <NodeVisitor> { new ColorOptimizationVisitor() }); PrettyPrintVerifier.VerifyPrettyPrint(BaseDirectory, FileName, new List <NodeVisitor> { new ColorOptimizationVisitor() }); }
/// <summary>The try parse css files.</summary> /// <param name="directoryInfo">The directory info.</param> private static void TryParseCssFiles(DirectoryInfo directoryInfo) { foreach (var cssFile in directoryInfo.EnumerateFiles("*.css", SearchOption.AllDirectories)) { try { var styleSheetNode = CssParser.Parse(cssFile, false); Assert.IsNotNull(styleSheetNode); } catch (Exception) { // Parse again with Trace ON CssParser.Parse(cssFile); throw; } } }
public void DataTriggerValue_should_support_variables() { var content = @" $variable-value: true; .field { @Data ""{ Binding RelativeSource={RelativeSource Self}, Path=IsFocused}"" $variable-value{ Background: Green; Foreground: White; } } "; var styleSheet = CssParser.Parse(content); var first = styleSheet.Rules[0].DeclarationBlock.Triggers[0] as DataTrigger; first.Binding.Should().Be(@"{ Binding RelativeSource={RelativeSource Self}, Path=IsFocused}"); first.Value.Should().Be("true"); }
public void Test_can_parse_namespace4() { var styleSheet = CssParser.Parse(@" @namespace ""System.Windows.Controls, PresentationFramework, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35""; |Grid { |Grid.Row: 0; |Grid.Column: 1; }"); Assert.AreEqual(1, styleSheet.Namespaces.Count()); Assert.AreEqual("", styleSheet.Namespaces[0].Alias); Assert.AreEqual("System.Windows.Controls, PresentationFramework, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35", styleSheet.Namespaces[0].Namespace); Assert.AreEqual("|Grid", styleSheet.Rules[0].SelectorString); Assert.AreEqual("|Grid.Row", styleSheet.Rules[0].DeclarationBlock[0].Property); Assert.AreEqual("|Grid.Column", styleSheet.Rules[0].DeclarationBlock[1].Property); }
public void Can_handle_space_before_comma_in_selector() { var styleSheet = CssParser.Parse(@" .test , .test2 { Opacity: 0.5; Width: 0; }"); Assert.AreEqual(2, styleSheet.Rules[0].DeclarationBlock.Count); Assert.AreEqual(@"0.5", styleSheet.Rules[0].DeclarationBlock[0].Value); Assert.AreEqual("0", styleSheet.Rules[0].DeclarationBlock[1].Value); Assert.AreEqual(2, styleSheet.Rules[1].DeclarationBlock.Count); Assert.AreEqual(@"0.5", styleSheet.Rules[1].DeclarationBlock[0].Value); Assert.AreEqual("0", styleSheet.Rules[1].DeclarationBlock[1].Value); }
public void EnterActions_and_ExitActions_should_be_added_to_DataTriggers() { var content = @" Button { @Data Text.Length 10 { @Enter: { BeginStoryboard: { Storyboard: #StaticResource fadeOutAndInStoryboard; } BeginStoryboard: { Storyboard: ""#StaticResource fadeOutAndInStoryboard2""; } } BackgroundColor: Red; ForegroundColor: Green; @Exit: { BeginStoryboard: { Storyboard: #StaticResource fadeOutAndInStoryboard; } BeginStoryboard: { Storyboard: #StaticResource fadeOutAndInStoryboard2; } BeginStoryboard: { Storyboard: #StaticResource fadeOutAndInStoryboard3; } } } } "; var styleSheet = CssParser.Parse(content); var first = styleSheet.Rules[0].DeclarationBlock.Triggers[0] as DataTrigger; first.Binding.Should().Be("Text.Length"); first.Value.Should().Be("10"); first.StyleDeclarationBlock[0].Property.Should().Be("BackgroundColor"); first.StyleDeclarationBlock[0].Value.Should().Be("Red"); first.StyleDeclarationBlock[1].Property.Should().Be("ForegroundColor"); first.StyleDeclarationBlock[1].Value.Should().Be("Green"); first.EnterActions.Count.Should().Be(2); first.ExitActions.Count.Should().Be(3); }
public void Can_parse_doublequoted_text_in_attributes_with_ampersand() { StyleSheet styleSheet = null; Action action = () => styleSheet = CssParser.Parse(@" Button { &[Content=""Some Content""] { FontWeight: Bold; } }"); action.Should().NotThrow(); styleSheet.Errors.Count.Should().Be(0); styleSheet.Rules.Count.Should().Be(2); styleSheet.Rules[1].SelectorString.Should().Be(@"Button[Content=""Some Content""]"); styleSheet.Rules[1].DeclarationBlock[0].Property.Should().Be(@"FontWeight"); styleSheet.Rules[1].DeclarationBlock[0].Value.Should().Be(@"Bold"); }
public void DuplicateImageReferenceWithDifferentRulesExceptionTest() { const string FileName = @"duplicateimagereferencewithdifferentrulesexception.css"; var fileInfo = new FileInfo(Path.Combine(ActualDirectory, FileName)); var styleSheetNode = CssParser.Parse(fileInfo); Assert.IsNotNull(styleSheetNode); try { styleSheetNode.Accept(new ImageAssemblyScanVisitor(fileInfo.FullName, null)); } catch (ImageAssembleException imageAssembleException) { Assert.IsTrue(imageAssembleException.ToString().Contains(string.Format(CultureInfo.InvariantCulture, CssStrings.DuplicateImageReferenceWithDifferentRulesError, Path.Combine(ActualDirectory, "foo.gif").ToLowerInvariant()))); } }
public void Parser_loads_namespaces() { var styleSheet = CssParser.Parse(test1); Assert.AreEqual(4, styleSheet.Namespaces.Count()); Assert.AreEqual("", styleSheet.Namespaces[0].Alias); Assert.AreEqual(TestNode.GetAssemblyQualifiedNamespaceName(typeof(TestNode)), styleSheet.Namespaces[0].Namespace); Assert.AreEqual("xamlcss", styleSheet.Namespaces[1].Alias); Assert.AreEqual(TestNode.GetAssemblyQualifiedNamespaceName(typeof(CssNamespace)), styleSheet.Namespaces[1].Namespace); Assert.AreEqual("ui", styleSheet.Namespaces[2].Alias); Assert.AreEqual(TestNode.GetAssemblyQualifiedNamespaceName(typeof(TestNode)), styleSheet.Namespaces[2].Namespace); Assert.AreEqual("special", styleSheet.Namespaces[3].Alias); Assert.AreEqual(TestNode.GetAssemblyQualifiedNamespaceName(typeof(TestNode)), styleSheet.Namespaces[3].Namespace); }
public void RepeatedPropertyNameExceptionTest() { const string FileName = @"repeatedpropertynameexception.css"; var fileInfo = new FileInfo(Path.Combine(ActualDirectory, FileName)); var styleSheetNode = CssParser.Parse(fileInfo); Assert.IsNotNull(styleSheetNode); try { styleSheetNode.Accept(new ImageAssemblyScanVisitor(fileInfo.FullName, null)); } catch (ImageAssembleException imageAssembleException) { Assert.IsTrue(imageAssembleException.ToString().Contains(string.Format(CultureInfo.InvariantCulture, CssStrings.RepeatedPropertyNameError, "background-image"))); } }
public void DuplicateBackgroundFormatExceptionTest() { const string FileName = @"duplicatebackgroundformatexception.css"; var fileInfo = new FileInfo(Path.Combine(ActualDirectory, FileName)); var styleSheetNode = CssParser.Parse(fileInfo); Assert.IsNotNull(styleSheetNode); try { styleSheetNode.Accept(new ImageAssemblyScanVisitor(fileInfo.FullName, null)); } catch (ImageAssembleException imageAssembleException) { Assert.IsTrue(imageAssembleException.ToString().Contains(CssStrings.DuplicateBackgroundFormatError)); } }
public void Can_parse_mixin_with_missing_parameter_without_default_value_should_throw_exception() { var css = @" @mixin Colored($textColor, $backgroundColor:""Yellow"") { TextColor: $textColor; BackgroundColor: $backgroundColor; } .header { @include Colored(); HeightRequest: 200; } "; Assert.That(() => CssParser.Parse(css), Throws.InvalidOperationException.With.Message.Contains("$textColor")); }
public void TooManyLengthsExceptionTest() { const string FileName = @"toomanylengthsexception.css"; var fileInfo = new FileInfo(Path.Combine(ActualDirectory, FileName)); var styleSheetNode = CssParser.Parse(fileInfo); Assert.IsNotNull(styleSheetNode); try { styleSheetNode.Accept(new ImageAssemblyScanVisitor(fileInfo.FullName, null)); } catch (ImageAssembleException imageAssembleException) { Assert.IsTrue(imageAssembleException.ToString().Contains(string.Format(CultureInfo.InvariantCulture, CssStrings.TooManyLengthsError, string.Empty).TrimEnd(new[] { '.', '\'' }))); } }
public void SupportsNegatedDisplayFlexRuleWithDeclarations() { var source = @"@supports not ( display: flex ) { body { width: 100%; height: 100%; background: white; color: black; } #navigation { width: 25%; } #article { width: 75%; } }"; var parser = new CssParser(source); parser.Parse(); Assert.AreEqual(1, parser.Result.Rules.Length); Assert.IsInstanceOf <CssSupportsRule>(parser.Result.Rules[0]); var supports = parser.Result.Rules[0] as CssSupportsRule; Assert.AreEqual(3, supports.Rules.Length); Assert.AreEqual("not (display: flex)", supports.ConditionText); Assert.IsFalse(supports.IsSupported); }
public void DataTrigger_should_be_added_to_Triggers() { var content = @" Button { @Data Text.Length 10 { IsEnabled: False; ForegroundColor: Red; } } "; var styleSheet = CssParser.Parse(content); var first = styleSheet.Rules[0].DeclarationBlock.Triggers[0] as DataTrigger; first.Binding.Should().Be("Text.Length"); first.Value.Should().Be("10"); }
public void SimpleTest() { var parser = new CssParser(this.content); parser.Parse(); IEnumerable <CssClass> result = parser.Result; var cssClasses = result.ToList(); for (int i = 0; i < cssClasses.Count; i++) { var resultElement = cssClasses[i]; var expectedElement = this.checkList[i]; Assert.That(resultElement.Name, Is.EqualTo(expectedElement.Name)); Assert.That(resultElement.PascalCaseName, Is.EqualTo(expectedElement.PascalCaseName)); } }
public void Can_parse_and_use_color_variables() { var css = @" $background: #ff00ff; $foreground: #00ff00; .header { BackgroundColor: $background; TextColor: $foreground; } "; var styleSheet = CssParser.Parse(css); styleSheet.Rules.Count.Should().Be(1); styleSheet.Rules[0].SelectorString.Should().Be(".header"); styleSheet.Rules[0].DeclarationBlock[0].Value.Should().Be("#ff00ff"); styleSheet.Rules[0].DeclarationBlock[1].Value.Should().Be("#00ff00"); }
public void Can_parse_and_use_text_variables() { var css = @" $textVariable1: ""Title""; $textVariable2: ""Subtitle""; .header { Title: $textVariable1; SubTitle: $textVariable2; } "; var styleSheet = CssParser.Parse(css); styleSheet.Rules.Count.Should().Be(1); styleSheet.Rules[0].SelectorString.Should().Be(".header"); styleSheet.Rules[0].DeclarationBlock[0].Value.Should().Be("Title"); styleSheet.Rules[0].DeclarationBlock[1].Value.Should().Be("Subtitle"); }
public void Can_parse_and_use_markup_extensions_variables_with_Xaml_syntax() { var css = @" $background: ""{Binding BackgroundColor}""; $foreground: ""{Binding ForegroundColor}""; .header { BackgroundColor: $background; TextColor: $foreground; } "; var styleSheet = CssParser.Parse(css); styleSheet.Rules.Count.Should().Be(1); styleSheet.Rules[0].SelectorString.Should().Be(".header"); styleSheet.Rules[0].DeclarationBlock[0].Value.Should().Be("{Binding BackgroundColor}"); styleSheet.Rules[0].DeclarationBlock[1].Value.Should().Be("{Binding ForegroundColor}"); }
public string[] SortDeclarations(IEnumerable<string> declarations) { Dictionary<string, string> inlineCommentStorage = new Dictionary<string, string>(); List<string> filteredDeclarations = new List<string>(); // How could you do this with clever linq stuff? foreach (string attribute in declarations) { string trimmedAttribute = attribute.Trim(); Match inlineCommentRegexMatch = Regex.Match(trimmedAttribute, "/\\*.*\\*/"); if (inlineCommentRegexMatch.Success && inlineCommentRegexMatch.Index > 0) { string comment = inlineCommentRegexMatch.Value.Trim(); string value = trimmedAttribute.Remove(inlineCommentRegexMatch.Index).Trim(); inlineCommentStorage.Add(value, comment); filteredDeclarations.Add(value); } else { filteredDeclarations.Add(attribute.Trim()); } } string rule = "div {" + string.Join(Environment.NewLine, filteredDeclarations) + "}"; CssParser parser = new CssParser(); StyleSheet sheet = parser.Parse(rule, true); var comments = sheet.RuleSets[0].Block.Children.Where(c => c is CComment).Select(c => Environment.NewLine + c.Text); var decls = sheet.RuleSets[0].Block.Declarations.Select(d => d.Text); var sorted = decls.OrderBy(d => d, new DeclarationComparer()); List<string> list = new List<string>(Stringify(sorted)); list.AddRange(comments.OrderBy(c => c)); var query = from c in list join o in inlineCommentStorage on c equals o.Key into gj from sublist in gj.DefaultIfEmpty() select c + (sublist.Key == null ? string.Empty : ' ' + sublist.Value); return query.ToArray(); }
private IEnumerable<ParseItem> GetItems(string file, CssParser parser, string searchValue) { StyleSheet ss = parser.Parse(File.ReadAllText(file), true); var visitorClass = new CssItemCollector<ClassSelector>(true); ss.Accept(visitorClass); var classes = from c in visitorClass.Items where c.Text.Contains(searchValue) select c; var visitorIDs = new CssItemCollector<IdSelector>(true); ss.Accept(visitorIDs); var ids = from c in visitorIDs.Items where c.Text.Contains(searchValue) select c; List<ParseItem> list = new List<ParseItem>(); list.AddRange(classes); list.AddRange(ids); return list; }
// A very ugly hack for a very ugly bug: https://github.com/hcatlin/libsass/issues/324 // Remove this and its caller in previous method, when it is fixed in original repo // and https://github.com/andrew/node-sass/ is released with the fix. // Overwriting all positions belonging to original/source file. private IEnumerable<CssSourceMapNode> CorrectionsForScss(string cssFileContents) { // Sort collection for generated file. var sortedForGenerated = MapNodes.OrderBy(x => x.GeneratedLine) .ThenBy(x => x.GeneratedColumn) .ToList(); ParseItem item = null; Selector selector = null; SimpleSelector simple = null; StyleSheet styleSheet = null, cssStyleSheet = null; int start = 0, indexInCollection, targetDepth; string fileContents = null, simpleText = ""; var result = new List<CssSourceMapNode>(); var contentCollection = new Dictionary<string, string>(); // So we don't have to read file for each map item. var parser = new CssParser(); cssStyleSheet = parser.Parse(cssFileContents, false); foreach (var node in MapNodes) { // Cache source file contents. if (!contentCollection.ContainsKey(node.SourceFilePath)) { if (!File.Exists(node.SourceFilePath)) // Lets say someone deleted the reference file. continue; fileContents = File.ReadAllText(node.SourceFilePath); contentCollection.Add(node.SourceFilePath, fileContents); styleSheet = _parser.Parse(fileContents, false); } start = cssFileContents.NthIndexOfCharInString('\n', node.GeneratedLine); start += node.GeneratedColumn; item = cssStyleSheet.ItemAfterPosition(start); if (item == null) continue; selector = item.FindType<Selector>(); simple = item.FindType<SimpleSelector>(); if (selector == null || simple == null) continue; simpleText = simple.Text; indexInCollection = sortedForGenerated.FindIndex(e => e.Equals(node));//sortedForGenerated.IndexOf(node); targetDepth = 0; for (int i = indexInCollection; i >= 0 && node.GeneratedLine == sortedForGenerated[i].GeneratedLine; targetDepth++, --i) ; start = fileContents.NthIndexOfCharInString('\n', node.OriginalLine); start += node.OriginalColumn; item = styleSheet.ItemAfterPosition(start); while (item.TreeDepth > targetDepth) { item = item.Parent; } // selector = item.FindType<RuleSet>().Selectors.First(); RuleSet rule; ScssRuleBlock scssRuleBlock = item as ScssRuleBlock; if (scssRuleBlock == null) rule = item as RuleSet; else rule = scssRuleBlock.RuleSets.First(); // Because even on the same TreeDepth, there may be mulitple ruleblocks // and the selector names may include & or other symbols which are diff // fromt he generated counterpart, here is the guess work item = rule.Children.FirstOrDefault(r => r is Selector && r.Text.Trim() == simpleText) as Selector; selector = item == null ? null : item as Selector; if (selector == null) { // One more try; dive deep and sniff then skip. var items = rule.Children.Where(r => r is RuleBlock) .SelectMany(r => (r as RuleBlock).Children .Where(s => s is RuleSet) .Select(s => (s as RuleSet).Selectors.FirstOrDefault(sel => sel.Text.Trim() == simpleText))); selector = items.Any() ? items.First() : null; if (selector == null) continue; } node.OriginalLine = fileContents.Substring(0, selector.Start).Count(s => s == '\n'); node.OriginalColumn = fileContents.GetLineColumn(selector.Start, node.OriginalLine); result.Add(node); } return result; }
private IEnumerable<CssSourceMapNode> ProcessGeneratedMaps(string fileContents) { ParseItem item = null; Selector selector = null; StyleSheet styleSheet = null; SimpleSelector simple = null; int start; var parser = new CssParser(); var result = new List<CssSourceMapNode>(); styleSheet = parser.Parse(fileContents, false); foreach (var node in MapNodes) { start = fileContents.NthIndexOfCharInString('\n', node.GeneratedLine); start += node.GeneratedColumn; item = styleSheet.ItemAfterPosition(start); if (item == null) continue; selector = item.FindType<Selector>(); if (selector == null) continue; var depth = node.OriginalSelector.TreeDepth / 2; if (depth < selector.SimpleSelectors.Count) { simple = selector.SimpleSelectors.First(); if (simple == null) simple = item.Parent != null ? item.Parent.FindType<SimpleSelector>() : null; if (simple == null) continue; var selectorText = new StringBuilder(); for (int i = 0; i < node.OriginalSelector.SimpleSelectors.Count; i++) { selectorText.Append(simple.Text).Append(" "); if (simple.NextSibling == null) continue; simple = simple.NextSibling as SimpleSelector; } selector = parser.Parse(selectorText.ToString(), false).RuleSets.First().Selectors.First() as Selector; if (selector == null) continue; } node.GeneratedSelector = selector; result.Add(node); } return result; }