From 277d8c3957bfc15bc94242d33e92aa98a89468d6 Mon Sep 17 00:00:00 2001 From: Sascha Peilicke Date: Thu, 23 Jan 2014 19:03:22 +0100 Subject: [PATCH] Fix '&' multiplication Let'S do it by example: .ident_a, .ident_b { & + & + & { color: red; } } We have to generate all permutations of the parent identifier list and the amount of ampersand child identifiers. In the above case, the exploded identifier list has ident_count**ampersand_count entries (8). As a bonus, we get the same identifier sort order as lessc does. Conflicts: lesscpy/plib/identifier.py --- lesscpy/lessc/utility.py | 13 + lesscpy/plib/identifier.py | 66 +++-- lesscpy/test/bootstrap3/css/theme.css | 10 +- lesscpy/test/bootstrap3/css/theme.min.css | 2 +- lesscpy/test/css/nesting.css | 338 +++++++++++++--------- lesscpy/test/css/nesting.min.css | 10 +- lesscpy/test/less/nesting.less | 22 +- lesscpy/test/testidentifier.py | 9 +- 8 files changed, 287 insertions(+), 183 deletions(-) diff --git a/lesscpy/lessc/utility.py b/lesscpy/lessc/utility.py index 4bdd088..3649353 100644 --- a/lesscpy/lessc/utility.py +++ b/lesscpy/lessc/utility.py @@ -11,6 +11,7 @@ from __future__ import print_function import collections +import itertools import math import re import sys @@ -276,3 +277,15 @@ def convergent_round(value, ndigits=0): nearest_even = integral_part + 0.5 return math.ceil(nearest_even) return round(value, ndigits) + + +def permutations_with_replacement(iterable, r=None): + """Return successive r length permutations of elements in the iterable. + + Similar to itertools.permutation but withouth repeated values filtering. + """ + pool = tuple(iterable) + n = len(pool) + r = n if r is None else r + for indices in itertools.product(range(n), repeat=r): + yield list(pool[i] for i in indices) diff --git a/lesscpy/plib/identifier.py b/lesscpy/plib/identifier.py index 3851480..68c55c7 100644 --- a/lesscpy/plib/identifier.py +++ b/lesscpy/plib/identifier.py @@ -96,36 +96,46 @@ def root(self, scope, names): if parent: parent = parent[-1] if parent.parsed: - return [self._pscn(part, n) - if part and part[0] not in self._subp - else n - for part in parent.parsed - for n in names] + parsed_names = [] + for name in names: + ampersand_count = name.count('&') + if ampersand_count: + filtered_parts = [] + for part in parent.parsed: + if part and part[0] not in self._subp: + filtered_parts.append(part) + permutations = list(utility.permutations_with_replacement(filtered_parts, ampersand_count)) + for permutation in permutations: + parsed = [] + for name_part in name: + if name_part == "&": + parent_part = permutation.pop(0) + if parsed and parsed[-1].endswith(']'): + parsed.extend(' ') + if parent_part[-1] == ' ': + parent_part.pop() + parsed.extend(parent_part) + else: + parsed.append(name_part) + parsed_names.append(parsed) + else: + # NOTE(saschpe): Maybe this code can be expressed with permutations too? + for part in parent.parsed: + if part and part[0] not in self._subp: + parsed = [] + if name[0] == "@media": + parsed.extend(name) + else: + parsed.extend(part) + if part[-1] != ' ': + parsed.append(' ') + parsed.extend(name) + parsed_names.append(parsed) + else: + parsed_names.append(name) + return parsed_names return names - def _pscn(self, parent, name): - """ - """ - parsed = [] - if any((n for n in name if n == '&')): - for n in name: - if n == '&': - if parsed[-1].endswith(']'): - parsed.extend(' ') - if parent[-1] == ' ': - parent.pop() - parsed.extend(parent) - else: - parsed.append(n) - elif name[0] == "@media": - parsed.extend(name) - else: - parsed.extend(parent) - if parent[-1] != ' ': - parsed.append(' ') - parsed.extend(name) - return parsed - def raw(self, clean=False): """Raw identifier. args: diff --git a/lesscpy/test/bootstrap3/css/theme.css b/lesscpy/test/bootstrap3/css/theme.css index 778b208..43250db 100644 --- a/lesscpy/test/bootstrap3/css/theme.css +++ b/lesscpy/test/bootstrap3/css/theme.css @@ -9,16 +9,16 @@ box-shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075); } .btn-default:active, -.btn-default.active, .btn-primary:active, -.btn-primary.active, .btn-success:active, -.btn-success.active, .btn-info:active, -.btn-info.active, .btn-warning:active, -.btn-warning.active, .btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, .btn-danger.active { -webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.125); box-shadow: inset 0 3px 5px rgba(0,0,0,.125); diff --git a/lesscpy/test/bootstrap3/css/theme.min.css b/lesscpy/test/bootstrap3/css/theme.min.css index 1af03e2..7a16850 100644 --- a/lesscpy/test/bootstrap3/css/theme.min.css +++ b/lesscpy/test/bootstrap3/css/theme.min.css @@ -1,5 +1,5 @@ .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);} -.btn-default:active,.btn-default.active,.btn-primary:active,.btn-primary.active,.btn-success:active,.btn-success.active,.btn-info:active,.btn-info.active,.btn-warning:active,.btn-warning.active,.btn-danger:active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125);} +.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125);} .btn:active,.btn.active{background-image:none;} .btn-default{background-image:-webkit-gradient(linear,left 0%,left 100%,from(#ffffff),to(#e0e0e0 ));background-image:-webkit-linear-gradient(top,#ffffff 0%,#e0e0e0 100%);background-image:-moz-linear-gradient(top,#ffffff 0%,#e0e0e0 100%);background-image:linear-gradient(to bottom,#ffffff 0%,#e0e0e0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff ', endColorstr='#ffe0e0e0 ', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #ffffff;border-color:#cccccc;} .btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px;} diff --git a/lesscpy/test/css/nesting.css b/lesscpy/test/css/nesting.css index 483a6be..155f3f5 100644 --- a/lesscpy/test/css/nesting.css +++ b/lesscpy/test/css/nesting.css @@ -14,10 +14,10 @@ color: purple; } h1 a:hover, -h1 p:hover, h2 a:hover, -h2 p:hover, h3 a:hover, +h1 p:hover, +h2 p:hover, h3 p:hover { color: red; } @@ -72,10 +72,10 @@ p a span { color: #110000; } #first > .one > #second .two > #deux #fourth .seven, -#first > .one > #second .two > #deux #fourth .eight > #nine, #first > .one > #second .two > #deux #five .seven, -#first > .one > #second .two > #deux #five .eight > #nine, #first > .one > #second .two > #deux #six .seven, +#first > .one > #second .two > #deux #fourth .eight > #nine, +#first > .one > #second .two > #deux #five .eight > #nine, #first > .one > #second .two > #deux #six .eight > #nine { border: 1px solid black; } @@ -85,164 +85,220 @@ p a span { color: red; } h1 a .one:hover, -h1 a .one:focus, -h1 a .two:hover, -h1 a .two:focus, -h1 a .three:hover, -h1 a .three:focus, -h1 a .four:hover, -h1 a .four:focus, +h2 a .one:hover, +h3 a .one:hover, +h4 a .one:hover, +h5 a .one:hover, h1 p .one:hover, -h1 p .one:focus, -h1 p .two:hover, -h1 p .two:focus, -h1 p .three:hover, -h1 p .three:focus, -h1 p .four:hover, -h1 p .four:focus, +h2 p .one:hover, +h3 p .one:hover, +h4 p .one:hover, +h5 p .one:hover, h1 div .one:hover, -h1 div .one:focus, -h1 div .two:hover, -h1 div .two:focus, -h1 div .three:hover, -h1 div .three:focus, -h1 div .four:hover, -h1 div .four:focus, +h2 div .one:hover, +h3 div .one:hover, +h4 div .one:hover, +h5 div .one:hover, h1 span .one:hover, -h1 span .one:focus, -h1 span .two:hover, -h1 span .two:focus, -h1 span .three:hover, -h1 span .three:focus, -h1 span .four:hover, -h1 span .four:focus, -h2 a .one:hover, -h2 a .one:focus, +h2 span .one:hover, +h3 span .one:hover, +h4 span .one:hover, +h5 span .one:hover, +h1 a .two:hover, h2 a .two:hover, -h2 a .two:focus, -h2 a .three:hover, -h2 a .three:focus, -h2 a .four:hover, -h2 a .four:focus, -h2 p .one:hover, -h2 p .one:focus, +h3 a .two:hover, +h4 a .two:hover, +h5 a .two:hover, +h1 p .two:hover, h2 p .two:hover, -h2 p .two:focus, -h2 p .three:hover, -h2 p .three:focus, -h2 p .four:hover, -h2 p .four:focus, -h2 div .one:hover, -h2 div .one:focus, +h3 p .two:hover, +h4 p .two:hover, +h5 p .two:hover, +h1 div .two:hover, h2 div .two:hover, -h2 div .two:focus, -h2 div .three:hover, -h2 div .three:focus, -h2 div .four:hover, -h2 div .four:focus, -h2 span .one:hover, -h2 span .one:focus, +h3 div .two:hover, +h4 div .two:hover, +h5 div .two:hover, +h1 span .two:hover, h2 span .two:hover, -h2 span .two:focus, -h2 span .three:hover, -h2 span .three:focus, -h2 span .four:hover, -h2 span .four:focus, -h3 a .one:hover, -h3 a .one:focus, -h3 a .two:hover, -h3 a .two:focus, +h3 span .two:hover, +h4 span .two:hover, +h5 span .two:hover, +h1 a .three:hover, +h2 a .three:hover, h3 a .three:hover, -h3 a .three:focus, -h3 a .four:hover, -h3 a .four:focus, -h3 p .one:hover, -h3 p .one:focus, -h3 p .two:hover, -h3 p .two:focus, +h4 a .three:hover, +h5 a .three:hover, +h1 p .three:hover, +h2 p .three:hover, h3 p .three:hover, -h3 p .three:focus, -h3 p .four:hover, -h3 p .four:focus, -h3 div .one:hover, -h3 div .one:focus, -h3 div .two:hover, -h3 div .two:focus, +h4 p .three:hover, +h5 p .three:hover, +h1 div .three:hover, +h2 div .three:hover, h3 div .three:hover, -h3 div .three:focus, -h3 div .four:hover, -h3 div .four:focus, -h3 span .one:hover, -h3 span .one:focus, -h3 span .two:hover, -h3 span .two:focus, +h4 div .three:hover, +h5 div .three:hover, +h1 span .three:hover, +h2 span .three:hover, h3 span .three:hover, -h3 span .three:focus, -h3 span .four:hover, -h3 span .four:focus, -h4 a .one:hover, -h4 a .one:focus, -h4 a .two:hover, -h4 a .two:focus, -h4 a .three:hover, -h4 a .three:focus, +h4 span .three:hover, +h5 span .three:hover, +h1 a .four:hover, +h2 a .four:hover, +h3 a .four:hover, h4 a .four:hover, -h4 a .four:focus, -h4 p .one:hover, -h4 p .one:focus, -h4 p .two:hover, -h4 p .two:focus, -h4 p .three:hover, -h4 p .three:focus, +h5 a .four:hover, +h1 p .four:hover, +h2 p .four:hover, +h3 p .four:hover, h4 p .four:hover, -h4 p .four:focus, -h4 div .one:hover, -h4 div .one:focus, -h4 div .two:hover, -h4 div .two:focus, -h4 div .three:hover, -h4 div .three:focus, +h5 p .four:hover, +h1 div .four:hover, +h2 div .four:hover, +h3 div .four:hover, h4 div .four:hover, -h4 div .four:focus, -h4 span .one:hover, -h4 span .one:focus, -h4 span .two:hover, -h4 span .two:focus, -h4 span .three:hover, -h4 span .three:focus, +h5 div .four:hover, +h1 span .four:hover, +h2 span .four:hover, +h3 span .four:hover, h4 span .four:hover, -h4 span .four:focus, -h5 a .one:hover, +h5 span .four:hover, +h1 a .one:focus, +h2 a .one:focus, +h3 a .one:focus, +h4 a .one:focus, h5 a .one:focus, -h5 a .two:hover, -h5 a .two:focus, -h5 a .three:hover, -h5 a .three:focus, -h5 a .four:hover, -h5 a .four:focus, -h5 p .one:hover, +h1 p .one:focus, +h2 p .one:focus, +h3 p .one:focus, +h4 p .one:focus, h5 p .one:focus, -h5 p .two:hover, -h5 p .two:focus, -h5 p .three:hover, -h5 p .three:focus, -h5 p .four:hover, -h5 p .four:focus, -h5 div .one:hover, +h1 div .one:focus, +h2 div .one:focus, +h3 div .one:focus, +h4 div .one:focus, h5 div .one:focus, -h5 div .two:hover, -h5 div .two:focus, -h5 div .three:hover, -h5 div .three:focus, -h5 div .four:hover, -h5 div .four:focus, -h5 span .one:hover, +h1 span .one:focus, +h2 span .one:focus, +h3 span .one:focus, +h4 span .one:focus, h5 span .one:focus, -h5 span .two:hover, +h1 a .two:focus, +h2 a .two:focus, +h3 a .two:focus, +h4 a .two:focus, +h5 a .two:focus, +h1 p .two:focus, +h2 p .two:focus, +h3 p .two:focus, +h4 p .two:focus, +h5 p .two:focus, +h1 div .two:focus, +h2 div .two:focus, +h3 div .two:focus, +h4 div .two:focus, +h5 div .two:focus, +h1 span .two:focus, +h2 span .two:focus, +h3 span .two:focus, +h4 span .two:focus, h5 span .two:focus, -h5 span .three:hover, +h1 a .three:focus, +h2 a .three:focus, +h3 a .three:focus, +h4 a .three:focus, +h5 a .three:focus, +h1 p .three:focus, +h2 p .three:focus, +h3 p .three:focus, +h4 p .three:focus, +h5 p .three:focus, +h1 div .three:focus, +h2 div .three:focus, +h3 div .three:focus, +h4 div .three:focus, +h5 div .three:focus, +h1 span .three:focus, +h2 span .three:focus, +h3 span .three:focus, +h4 span .three:focus, h5 span .three:focus, -h5 span .four:hover, +h1 a .four:focus, +h2 a .four:focus, +h3 a .four:focus, +h4 a .four:focus, +h5 a .four:focus, +h1 p .four:focus, +h2 p .four:focus, +h3 p .four:focus, +h4 p .four:focus, +h5 p .four:focus, +h1 div .four:focus, +h2 div .four:focus, +h3 div .four:focus, +h4 div .four:focus, +h5 div .four:focus, +h1 span .four:focus, +h2 span .four:focus, +h3 span .four:focus, +h4 span .four:focus, h5 span .four:focus { display: block; } +.child + .child, +.child + .sibling, +.sibling + .child, +.sibling + .sibling { + color: red; +} +.child + .child + .child, +.child + .child + .sibling, +.child + .sibling + .child, +.child + .sibling + .sibling, +.sibling + .child + .child, +.sibling + .child + .sibling, +.sibling + .sibling + .child, +.sibling + .sibling + .sibling { + color: red; +} +.child + .child + .child, +.child + .child + .sibling, +.child + .child + .foo, +.child + .sibling + .child, +.child + .sibling + .sibling, +.child + .sibling + .foo, +.child + .foo + .child, +.child + .foo + .sibling, +.child + .foo + .foo, +.sibling + .child + .child, +.sibling + .child + .sibling, +.sibling + .child + .foo, +.sibling + .sibling + .child, +.sibling + .sibling + .sibling, +.sibling + .sibling + .foo, +.sibling + .foo + .child, +.sibling + .foo + .sibling, +.sibling + .foo + .foo, +.foo + .child + .child, +.foo + .child + .sibling, +.foo + .child + .foo, +.foo + .sibling + .child, +.foo + .sibling + .sibling, +.foo + .sibling + .foo, +.foo + .foo + .child, +.foo + .foo + .sibling, +.foo + .foo + .foo { + color: red; +} +.child + .child, +.child + .sibling, +.child + .foo, +.sibling + .child, +.sibling + .sibling, +.sibling + .foo, +.foo + .child, +.foo + .sibling, +.foo + .foo { + color: red; +} diff --git a/lesscpy/test/css/nesting.min.css b/lesscpy/test/css/nesting.min.css index 95af030..e6112e0 100644 --- a/lesscpy/test/css/nesting.min.css +++ b/lesscpy/test/css/nesting.min.css @@ -3,7 +3,7 @@ .div .nest.deep{color:yellow;} .div .nest.deep .deeper{color:angry;} .div .nest.deep .deeper .deepest{color:purple;} -h1 a:hover,h1 p:hover,h2 a:hover,h2 p:hover,h3 a:hover,h3 p:hover{color:red;} +h1 a:hover,h2 a:hover,h3 a:hover,h1 p:hover,h2 p:hover,h3 p:hover{color:red;} a{color:red;} a:hover{color:blue;} div a{color:green;} @@ -19,6 +19,10 @@ p a span{color:yellow;} #first>.one>#second .two>#deux #third:focus #fifth>#sixth .seventh #eighth+.sibling_selector{color:angry;} #first>.one>#second .two>#deux #third~p.general_sibling_selector{color:unused;} #first>.one>#second .two>#deux #fourth,#first>.one>#second .two>#deux #five,#first>.one>#second .two>#deux #six{color:#110000;} -#first>.one>#second .two>#deux #fourth .seven,#first>.one>#second .two>#deux #fourth .eight>#nine,#first>.one>#second .two>#deux #five .seven,#first>.one>#second .two>#deux #five .eight>#nine,#first>.one>#second .two>#deux #six .seven,#first>.one>#second .two>#deux #six .eight>#nine{border:1px solid black;} +#first>.one>#second .two>#deux #fourth .seven,#first>.one>#second .two>#deux #five .seven,#first>.one>#second .two>#deux #six .seven,#first>.one>#second .two>#deux #fourth .eight>#nine,#first>.one>#second .two>#deux #five .eight>#nine,#first>.one>#second .two>#deux #six .eight>#nine{border:1px solid black;} #first>.one>#second .two>#deux #fourth #ten,#first>.one>#second .two>#deux #five #ten,#first>.one>#second .two>#deux #six #ten{color:red;} -h1 a .one:hover,h1 a .one:focus,h1 a .two:hover,h1 a .two:focus,h1 a .three:hover,h1 a .three:focus,h1 a .four:hover,h1 a .four:focus,h1 p .one:hover,h1 p .one:focus,h1 p .two:hover,h1 p .two:focus,h1 p .three:hover,h1 p .three:focus,h1 p .four:hover,h1 p .four:focus,h1 div .one:hover,h1 div .one:focus,h1 div .two:hover,h1 div .two:focus,h1 div .three:hover,h1 div .three:focus,h1 div .four:hover,h1 div .four:focus,h1 span .one:hover,h1 span .one:focus,h1 span .two:hover,h1 span .two:focus,h1 span .three:hover,h1 span .three:focus,h1 span .four:hover,h1 span .four:focus,h2 a .one:hover,h2 a .one:focus,h2 a .two:hover,h2 a .two:focus,h2 a .three:hover,h2 a .three:focus,h2 a .four:hover,h2 a .four:focus,h2 p .one:hover,h2 p .one:focus,h2 p .two:hover,h2 p .two:focus,h2 p .three:hover,h2 p .three:focus,h2 p .four:hover,h2 p .four:focus,h2 div .one:hover,h2 div .one:focus,h2 div .two:hover,h2 div .two:focus,h2 div .three:hover,h2 div .three:focus,h2 div .four:hover,h2 div .four:focus,h2 span .one:hover,h2 span .one:focus,h2 span .two:hover,h2 span .two:focus,h2 span .three:hover,h2 span .three:focus,h2 span .four:hover,h2 span .four:focus,h3 a .one:hover,h3 a .one:focus,h3 a .two:hover,h3 a .two:focus,h3 a .three:hover,h3 a .three:focus,h3 a .four:hover,h3 a .four:focus,h3 p .one:hover,h3 p .one:focus,h3 p .two:hover,h3 p .two:focus,h3 p .three:hover,h3 p .three:focus,h3 p .four:hover,h3 p .four:focus,h3 div .one:hover,h3 div .one:focus,h3 div .two:hover,h3 div .two:focus,h3 div .three:hover,h3 div .three:focus,h3 div .four:hover,h3 div .four:focus,h3 span .one:hover,h3 span .one:focus,h3 span .two:hover,h3 span .two:focus,h3 span .three:hover,h3 span .three:focus,h3 span .four:hover,h3 span .four:focus,h4 a .one:hover,h4 a .one:focus,h4 a .two:hover,h4 a .two:focus,h4 a .three:hover,h4 a .three:focus,h4 a .four:hover,h4 a .four:focus,h4 p .one:hover,h4 p .one:focus,h4 p .two:hover,h4 p .two:focus,h4 p .three:hover,h4 p .three:focus,h4 p .four:hover,h4 p .four:focus,h4 div .one:hover,h4 div .one:focus,h4 div .two:hover,h4 div .two:focus,h4 div .three:hover,h4 div .three:focus,h4 div .four:hover,h4 div .four:focus,h4 span .one:hover,h4 span .one:focus,h4 span .two:hover,h4 span .two:focus,h4 span .three:hover,h4 span .three:focus,h4 span .four:hover,h4 span .four:focus,h5 a .one:hover,h5 a .one:focus,h5 a .two:hover,h5 a .two:focus,h5 a .three:hover,h5 a .three:focus,h5 a .four:hover,h5 a .four:focus,h5 p .one:hover,h5 p .one:focus,h5 p .two:hover,h5 p .two:focus,h5 p .three:hover,h5 p .three:focus,h5 p .four:hover,h5 p .four:focus,h5 div .one:hover,h5 div .one:focus,h5 div .two:hover,h5 div .two:focus,h5 div .three:hover,h5 div .three:focus,h5 div .four:hover,h5 div .four:focus,h5 span .one:hover,h5 span .one:focus,h5 span .two:hover,h5 span .two:focus,h5 span .three:hover,h5 span .three:focus,h5 span .four:hover,h5 span .four:focus{display:block;} +h1 a .one:hover,h2 a .one:hover,h3 a .one:hover,h4 a .one:hover,h5 a .one:hover,h1 p .one:hover,h2 p .one:hover,h3 p .one:hover,h4 p .one:hover,h5 p .one:hover,h1 div .one:hover,h2 div .one:hover,h3 div .one:hover,h4 div .one:hover,h5 div .one:hover,h1 span .one:hover,h2 span .one:hover,h3 span .one:hover,h4 span .one:hover,h5 span .one:hover,h1 a .two:hover,h2 a .two:hover,h3 a .two:hover,h4 a .two:hover,h5 a .two:hover,h1 p .two:hover,h2 p .two:hover,h3 p .two:hover,h4 p .two:hover,h5 p .two:hover,h1 div .two:hover,h2 div .two:hover,h3 div .two:hover,h4 div .two:hover,h5 div .two:hover,h1 span .two:hover,h2 span .two:hover,h3 span .two:hover,h4 span .two:hover,h5 span .two:hover,h1 a .three:hover,h2 a .three:hover,h3 a .three:hover,h4 a .three:hover,h5 a .three:hover,h1 p .three:hover,h2 p .three:hover,h3 p .three:hover,h4 p .three:hover,h5 p .three:hover,h1 div .three:hover,h2 div .three:hover,h3 div .three:hover,h4 div .three:hover,h5 div .three:hover,h1 span .three:hover,h2 span .three:hover,h3 span .three:hover,h4 span .three:hover,h5 span .three:hover,h1 a .four:hover,h2 a .four:hover,h3 a .four:hover,h4 a .four:hover,h5 a .four:hover,h1 p .four:hover,h2 p .four:hover,h3 p .four:hover,h4 p .four:hover,h5 p .four:hover,h1 div .four:hover,h2 div .four:hover,h3 div .four:hover,h4 div .four:hover,h5 div .four:hover,h1 span .four:hover,h2 span .four:hover,h3 span .four:hover,h4 span .four:hover,h5 span .four:hover,h1 a .one:focus,h2 a .one:focus,h3 a .one:focus,h4 a .one:focus,h5 a .one:focus,h1 p .one:focus,h2 p .one:focus,h3 p .one:focus,h4 p .one:focus,h5 p .one:focus,h1 div .one:focus,h2 div .one:focus,h3 div .one:focus,h4 div .one:focus,h5 div .one:focus,h1 span .one:focus,h2 span .one:focus,h3 span .one:focus,h4 span .one:focus,h5 span .one:focus,h1 a .two:focus,h2 a .two:focus,h3 a .two:focus,h4 a .two:focus,h5 a .two:focus,h1 p .two:focus,h2 p .two:focus,h3 p .two:focus,h4 p .two:focus,h5 p .two:focus,h1 div .two:focus,h2 div .two:focus,h3 div .two:focus,h4 div .two:focus,h5 div .two:focus,h1 span .two:focus,h2 span .two:focus,h3 span .two:focus,h4 span .two:focus,h5 span .two:focus,h1 a .three:focus,h2 a .three:focus,h3 a .three:focus,h4 a .three:focus,h5 a .three:focus,h1 p .three:focus,h2 p .three:focus,h3 p .three:focus,h4 p .three:focus,h5 p .three:focus,h1 div .three:focus,h2 div .three:focus,h3 div .three:focus,h4 div .three:focus,h5 div .three:focus,h1 span .three:focus,h2 span .three:focus,h3 span .three:focus,h4 span .three:focus,h5 span .three:focus,h1 a .four:focus,h2 a .four:focus,h3 a .four:focus,h4 a .four:focus,h5 a .four:focus,h1 p .four:focus,h2 p .four:focus,h3 p .four:focus,h4 p .four:focus,h5 p .four:focus,h1 div .four:focus,h2 div .four:focus,h3 div .four:focus,h4 div .four:focus,h5 div .four:focus,h1 span .four:focus,h2 span .four:focus,h3 span .four:focus,h4 span .four:focus,h5 span .four:focus{display:block;} +.child+.child,.child+.sibling,.sibling+.child,.sibling+.sibling{color:red;} +.child+.child+.child,.child+.child+.sibling,.child+.sibling+.child,.child+.sibling+.sibling,.sibling+.child+.child,.sibling+.child+.sibling,.sibling+.sibling+.child,.sibling+.sibling+.sibling{color:red;} +.child+.child+.child,.child+.child+.sibling,.child+.child+.foo,.child+.sibling+.child,.child+.sibling+.sibling,.child+.sibling+.foo,.child+.foo+.child,.child+.foo+.sibling,.child+.foo+.foo,.sibling+.child+.child,.sibling+.child+.sibling,.sibling+.child+.foo,.sibling+.sibling+.child,.sibling+.sibling+.sibling,.sibling+.sibling+.foo,.sibling+.foo+.child,.sibling+.foo+.sibling,.sibling+.foo+.foo,.foo+.child+.child,.foo+.child+.sibling,.foo+.child+.foo,.foo+.sibling+.child,.foo+.sibling+.sibling,.foo+.sibling+.foo,.foo+.foo+.child,.foo+.foo+.sibling,.foo+.foo+.foo{color:red;} +.child+.child,.child+.sibling,.child+.foo,.sibling+.child,.sibling+.sibling,.sibling+.foo,.foo+.child,.foo+.sibling,.foo+.foo{color:red;} diff --git a/lesscpy/test/less/nesting.less b/lesscpy/test/less/nesting.less index bf115f5..d154da1 100644 --- a/lesscpy/test/less/nesting.less +++ b/lesscpy/test/less/nesting.less @@ -98,4 +98,24 @@ h1, h2, h3, h4, h5 { } } } -} \ No newline at end of file +} +.child, .sibling { + & + & { + color: red; + } +} +.child, .sibling { + & + & + & { + color: red; + } +} +.child, .sibling, .foo { + & + & + & { + color: red; + } +} +.child, .sibling, .foo { + & + & { + color: red; + } +} diff --git a/lesscpy/test/testidentifier.py b/lesscpy/test/testidentifier.py index 4c435cb..753fbe2 100644 --- a/lesscpy/test/testidentifier.py +++ b/lesscpy/test/testidentifier.py @@ -79,12 +79,13 @@ def test_groups(self): sc.current = Identifier(['.c', ',', '.d'], 0).parse(sc) id = Identifier(['.deep'], 0) self.assertEqual(id.parse(sc).fmt(fl), '.a .next .c .deep,\n' - '.a .next .d .deep,\n' '.b .next .c .deep,\n' + '.a .next .d .deep,\n' '.b .next .d .deep') - self.assertEqual(id.raw(), '.a% %.next% %.c% %.deep%.a%' - ' %.next% %.d% %.deep%.b% %.next%' - ' %.c% %.deep%.b% %.next% %.d% %.deep') + self.assertEqual(id.raw(), '.a% %.next% %.c% %.deep%' + '.b% %.next% %.c% %.deep%' + '.a% %.next% %.d% %.deep%' + '.b% %.next% %.d% %.deep') def test_media(self): fl = {'ws': ' ', 'nl': '\n'}