Beispiel #1
0
        public void TestMixinExpansion()
        {
            var lessFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(LessContentTypeDefinition.LessContentType));
            var lessCode    = @"a {
                                .myMixin(@p) {
                                    b, code {
                                    }
                                }
                            }";

            var lessDoc    = lessFactory.CreateParser().Parse(lessCode, false);
            var lessBlocks = new CssItemAggregator <RuleSet>(true)
            {
                (RuleSet rs) => rs
            }.Crawl(lessDoc).ToList();

            // Remove all but the deepest blocks
            while (0 < lessBlocks.RemoveAll(c => lessBlocks.Any(c.IsParentOf)))
            {
                ;
            }

            var literalExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal)).ToList();

            literalExpansions.Should().Equal(new[] { "a .myMixin(@p) b", "a .myMixin(@p) code" });

            var skipExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Skip)).ToList();

            skipExpansions.Should().BeEmpty();

            var nestedExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.NestedOnly)).ToList();

            nestedExpansions.Should().Equal(new[] { "«mixin .myMixin» b", "«mixin .myMixin» code" });
        }
Beispiel #2
0
        public void TestMixinExpansion()
        {
            var scssFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(ScssContentTypeDefinition.ScssContentType));
            var scssCode    = @"a {
                                @mixin myMixin($p) {
                                        b, code {
                                            width: $p+10+px;
                                        }
                                    }
                                    @include myMixin(1)
                                }
                            ";

            var scssDoc    = scssFactory.CreateParser().Parse(scssCode, false);
            var scssBlocks = new CssItemAggregator <RuleSet>(true)
            {
                (RuleSet rs) => rs
            }.Crawl(scssDoc).ToList();

            // Remove all but the deepest blocks
            while (0 < scssBlocks.RemoveAll(c => scssBlocks.Any(c.IsParentOf)))
            {
                ;
            }

            var literalExpansions = scssBlocks.SelectMany(rs => ScssDocument.GetSelectorNames(rs, ScssMixinAction.Literal)).ToList();

            literalExpansions.Should().Equal(new[] { "a b", "a code" });

            var skipExpansions = scssBlocks.SelectMany(rs => ScssDocument.GetSelectorNames(rs, ScssMixinAction.Skip)).ToList();

            skipExpansions.Should().BeEmpty();
        }
Beispiel #3
0
        private static IEnumerable<ParseItem> GetColors(CssTree tree, SnapshotSpan span)
        {
            ParseItem complexItem = tree.StyleSheet.ItemFromRange(span.Start, span.Length);
            if (complexItem == null || (!(complexItem is AtDirective) && !(complexItem is RuleBlock) && !(complexItem is CssVariableDeclaration) && !(complexItem is FunctionArgument)))
                return Enumerable.Empty<ParseItem>();

            var colorCrawler = new CssItemAggregator<ParseItem>(filter: e => e.AfterEnd > span.Start && e.Start < span.End)
            {
                (HexColorValue h) => h,
                (FunctionColor c) => c,
                (TokenItem i) => (i.PreviousSibling == null || (i.PreviousSibling.Text != "@" && i.PreviousSibling.Text != "$"))    // Ignore variable names that happen to be colors
                               && i.TokenType == CssTokenType.Identifier
                               && (i.FindType<Declaration>() != null || i.FindType<CssExpression>() != null)                       // Ignore classnames that happen to be colors
                               && Color.FromName(i.Text).IsNamedColor
                               ? i : null
            };

            return colorCrawler.Crawl(complexItem).Where(o => o != null);
        }
        public void Reparse(string text)
        {
            lock (ParseSync)
            {
                if (string.Equals(text, _lastParsedText, StringComparison.Ordinal))
                {
                    return;
                }

                var parser      = CreateParser();
                var parseResult = parser.Parse(text, false);

                Rules = new CssItemAggregator <IStylingRule>(true)
                {
                    (RuleSet rs) => CssRule.From(_file, text, rs, this)
                }
                .Crawl(parseResult)
                .Where(x => x != null)
                .ToList();

                _lastParsedText = text;
            }
        }
        public void Reparse(string text)
        {
            lock (ParseSync)
            {
                if (string.Equals(text, _lastParsedText, StringComparison.Ordinal))
                {
                    return;
                }

                var parser = CreateParser();
                var parseResult = parser.Parse(text, false);

                Rules = new CssItemAggregator<IStylingRule>(true) { (RuleSet rs) => CssRule.From(_file, text, rs, this) }
                    .Crawl(parseResult)
                    .Where(x => x != null)
                    .ToList();

                _lastParsedText = text;
            }
        }
        public void TestMixinExpansion()
        {
            var lessFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(LessContentTypeDefinition.LessContentType));
            var lessCode = @"a {
                                .myMixin(@p) {
                                    b, code {
                                    }
                                }
                            }";

            var lessDoc = lessFactory.CreateParser().Parse(lessCode, false);
            var lessBlocks = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(lessDoc).ToList();
            // Remove all but the deepest blocks
            while (0 < lessBlocks.RemoveAll(c => lessBlocks.Any(c.IsParentOf)))
                ;

            var literalExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal)).ToList();
            literalExpansions.Should().Equal(new[] { "a .myMixin(@p) b", "a .myMixin(@p) code" });

            var skipExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Skip)).ToList();
            skipExpansions.Should().BeEmpty();

            var nestedExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.NestedOnly)).ToList();
            nestedExpansions.Should().Equal(new[] { "«mixin .myMixin» b", "«mixin .myMixin» code" });
        }
        public async Task SelectorExpansionTest()
        {
            #region LESS sources
            var testSources = new[]{
@"
@media all {
    a {
        @media all {
            @media all {
                b {
                    color: goldenrod;
                    em {
                        color: goldenrod;
                    }
                }
            }
        }
    }
}
",
@"  // Taken from http://blog.slaks.net/2013-09-29/less-css-secrets-of-the-ampersand/
a {
    color: blue;
    &:hover {
        color: green;
    }
}
form a {
    color: purple;
    body.QuietMode & {
        color: black;
    }
}
.quoted-source {
    background: #fcc;
    blockquote& {
        background: #fdc;
    }
}
.btn.btn-primary.btn-lg[disabled] {
    & + & + & {
        margin-left: 10px;
    }
}
p, blockquote, ul, li {
    border-top: 1px solid gray;
    & + & {
        border-top: 0;
    }
}
",
@"  // Taken from https://github.com/less/less.js/blob/master/test/less/selectors.less
h1, h2, h3 {
  a, p {
    &:hover {
      color: red;
    }
  }
}

#all { color: blue; }
#the { color: blue; }
#same { color: blue; }

ul, li, div, q, blockquote, textarea {
  margin: 0;
}

td {
  margin: 0;
  padding: 0;
}

td, input {
  line-height: 1em;
}

a {
  color: red;

  &:hover { color: blue; }

  div & { color: green; }

  p & span { color: yellow; }
}

.foo {
  .bar, .baz {
    & .qux {
      display: block;
    }
    .qux & {
      display: inline;
    }
    .qux& {
      display: inline-block;
    }
    .qux & .biz {
      display: none;
    }
  }
}

.b {
 &.c {
  .a& {
   color: red;
  }
 }
}

.b {
 .c & {
  &.a {
   color: red;
  }
 }
}

.p {
  .foo &.bar {
    color: red;
  }
}

.p {
  .foo&.bar {
    color: red;
  }
}

.foo {
  .foo + & {
    background: amber;
  }
  & + & {
    background: amber;
  }
}

.foo, .bar {
  & + & {
    background: amber;
  }
}

.foo, .bar {
  a, b {
    & > & {
      background: amber;
    }
  }
}

.other ::fnord { color: red }
.other::fnord { color: red }
.other {
  ::bnord {color: red }
  &::bnord {color: red }
}
",
            @"// Taken from https://github.com/less/less.js/blob/master/test/less/rulesets.less
#first > .one {
  > #second .two > #deux {
    width: 50%;
    #third {
      &:focus {
        color: black;
        #fifth {
          > #sixth {
            .seventh #eighth {
              + #ninth {
                color: purple;
              }
            }
          }
        }
      }
      height: 100%;
    }
    #fourth, #five, #six {
      color: #110000;
      .seven, .eight > #nine {
        border: 1px solid black;
      }
      #ten {
        color: red;
      }
    }
  }
  font-size: 2em;
}
"};
            #endregion

            var lessFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(LessContentTypeDefinition.LessContentType));
            foreach (var lessCode in testSources)
            {
                var cssCode = await new LessCompiler().CompileSourceAsync(lessCode, ".less");
                var lessDoc = lessFactory.CreateParser().Parse(lessCode, false);
                var cssDoc = new CssParser().Parse(cssCode, false);

                var cssSelectors = new CssItemAggregator<string>(false) { (Selector s) => CssExtensions.SelectorText(s) }.Crawl(cssDoc);

                var lessSelectors = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(lessDoc)
                                                .Where(rs => rs.Block.Declarations.Any())   // Skip selectors that don't have any rules; these won't end up in the CSS
                                                .SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal))
                                                .ToList();

                lessSelectors.Should().Equal(cssSelectors);
            }
        }
        public void TestMixinExpansion()
        {
            var lessCode = @"
a {
    .myMixin(@p) {
        b, code {
        }
    }
}";

            var lessDoc = new LessParser().Parse(lessCode, false);
            var lessBlocks = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(lessDoc).ToList();
            // Remove all but the deepest blocks
            while (0 < lessBlocks.RemoveAll(c => lessBlocks.Any(c.IsParentOf)))
                ;

            var literalExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal)).ToList();
            CollectionAssert.AreEqual(new[] { "a .myMixin(@p) b", "a .myMixin(@p) code" }, literalExpansions);

            var skipExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Skip)).ToList();
            CollectionAssert.AreEqual(new string[0], skipExpansions);

            var nestedExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.NestedOnly)).ToList();
            CollectionAssert.AreEqual(new[] { "«mixin .myMixin» b", "«mixin .myMixin» code" }, nestedExpansions);
        }
Beispiel #9
0
        public async Task SelectorExpansionTest()
        {
            #region LESS sources
            var testSources = new[] {
                @"
@media all {
    a {
        @media all {
            @media all {
                b {
                    color: goldenrod;
                    em {
                        color: goldenrod;
                    }
                }
            }
        }
    }
}
",
                @"  // Taken from http://blog.slaks.net/2013-09-29/less-css-secrets-of-the-ampersand/
a {
    color: blue;
    &:hover {
        color: green;
    }
}
form a {
    color: purple;
    body.QuietMode & {
        color: black;
    }
}
.quoted-source {
    background: #fcc;
    blockquote& {
        background: #fdc;
    }
}
.btn.btn-primary.btn-lg[disabled] {
    & + & + & {
        margin-left: 10px;
    }
}
p, blockquote, ul, li {
    border-top: 1px solid gray;
    & + & {
        border-top: 0;
    }
}
",
                @"  // Taken from https://github.com/less/less.js/blob/master/test/less/selectors.less
h1, h2, h3 {
  a, p {
    &:hover {
      color: red;
    }
  }
}

#all { color: blue; }
#the { color: blue; }
#same { color: blue; }

ul, li, div, q, blockquote, textarea {
  margin: 0;
}

td {
  margin: 0;
  padding: 0;
}

td, input {
  line-height: 1em;
}

a {
  color: red;

  &:hover { color: blue; }

  div & { color: green; }

  p & span { color: yellow; }
}

.foo {
  .bar, .baz {
    & .qux {
      display: block;
    }
    .qux & {
      display: inline;
    }
    .qux& {
      display: inline-block;
    }
    .qux & .biz {
      display: none;
    }
  }
}

.b {
 &.c {
  .a& {
   color: red;
  }
 }
}

.b {
 .c & {
  &.a {
   color: red;
  }
 }
}

.p {
  .foo &.bar {
    color: red;
  }
}

.p {
  .foo&.bar {
    color: red;
  }
}

.foo {
  .foo + & {
    background: amber;
  }
  & + & {
    background: amber;
  }
}

.foo, .bar {
  & + & {
    background: amber;
  }
}

.foo, .bar {
  a, b {
    & > & {
      background: amber;
    }
  }
}

.other ::fnord { color: red }
.other::fnord { color: red }
.other {
  ::bnord {color: red }
  &::bnord {color: red }
}
",
                @"// Taken from https://github.com/less/less.js/blob/master/test/less/rulesets.less
#first > .one {
  > #second .two > #deux {
    width: 50%;
    #third {
      &:focus {
        color: black;
        #fifth {
          > #sixth {
            .seventh #eighth {
              + #ninth {
                color: purple;
              }
            }
          }
        }
      }
      height: 100%;
    }
    #fourth, #five, #six {
      color: #110000;
      .seven, .eight > #nine {
        border: 1px solid black;
      }
      #ten {
        color: red;
      }
    }
  }
  font-size: 2em;
}
"
            };
            #endregion

            var lessFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(LessContentTypeDefinition.LessContentType));
            foreach (var lessCode in testSources)
            {
                var cssCode = await new LessCompiler().CompileSourceAsync(lessCode, ".less");
                var lessDoc = lessFactory.CreateParser().Parse(lessCode, false);
                var cssDoc  = new CssParser().Parse(cssCode, false);

                var cssSelectors = new CssItemAggregator <string>(false)
                {
                    (Selector s) => CssExtensions.SelectorText(s)
                }.Crawl(cssDoc);

                var lessSelectors = new CssItemAggregator <RuleSet>(true)
                {
                    (RuleSet rs) => rs
                }.Crawl(lessDoc)
                .Where(rs => rs.Block.Declarations.Any())                                   // Skip selectors that don't have any rules; these won't end up in the CSS
                .SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal))
                .ToList();

                lessSelectors.Should().Equal(cssSelectors);
            }
        }
        public void TestMixinExpansion()
        {
            var scssFactory = CssParserLocator.FindComponent(ContentTypeManager.GetContentType(ScssContentTypeDefinition.ScssContentType));
            var scssCode = @"a {
                                @mixin myMixin($p) {
                                        b, code {
                                            width: $p+10+px;
                                        }
                                    }
                                    @include myMixin(1)
                                }
                            ";

            var scssDoc = scssFactory.CreateParser().Parse(scssCode, false);
            var scssBlocks = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(scssDoc).ToList();
            // Remove all but the deepest blocks
            while (0 < scssBlocks.RemoveAll(c => scssBlocks.Any(c.IsParentOf)))
                ;

            var literalExpansions = scssBlocks.SelectMany(rs => ScssDocument.GetSelectorNames(rs, ScssMixinAction.Literal)).ToList();
            literalExpansions.Should().Equal(new[] { "a b", "a code" });

            var skipExpansions = scssBlocks.SelectMany(rs => ScssDocument.GetSelectorNames(rs, ScssMixinAction.Skip)).ToList();
            skipExpansions.Should().BeEmpty();
        }