예제 #1
0
        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);
            }
예제 #4
0
        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;
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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");
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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");
        }
예제 #12
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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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" }
                }
            });
        }
예제 #15
0
        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();
        }
예제 #16
0
        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()
            });
        }
예제 #17
0
 /// <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;
         }
     }
 }
예제 #18
0
        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");
        }
예제 #19
0
        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);
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }
예제 #22
0
        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");
        }
예제 #23
0
        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())));
            }
        }
예제 #24
0
        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);
        }
예제 #25
0
        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")));
            }
        }
예제 #26
0
        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));
            }
        }
예제 #27
0
        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"));
        }
예제 #28
0
        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[] { '.', '\'' })));
            }
        }
예제 #29
0
        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);
        }
예제 #30
0
        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");
        }
예제 #31
0
        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));
            }
        }
예제 #32
0
        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");
        }
예제 #33
0
        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");
        }
예제 #34
0
        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}");
        }
예제 #35
0
        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;
        }
예제 #37
0
        // 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;
        }
예제 #38
0
        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;
        }