Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add Sass like extend #509

Closed
wants to merge 3 commits into from
@hokaccha

Sass extend is here.
http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend

More simple syntax, use +.

.foo {
  width: 100px;
}
.bar {
  +.foo;
}

converted this.

.foo, bar {
  width: 100px;
}

See also test code.

@cloudhead
Owner

Nice work, I'll have a look!

@madevelopers

and the output is also grouped. nice.

@cloudhead

The ; here should be a ,.

@aziz

I really like to see this one get merged into LESS. It's obviously missing this feature and will help us generate lighter and leaner css files by reusing instead of repeating.

a big :+1:

@jmgunn87

Yeah, I like this as well. Is this going to be merged or what?

@davidhund

I also would love to know if/when this is going to be implemented.

@rowanmanning

It'd be awesome to get something like this into LESS. Any plans to merge?

@icholy

+1

@kadamwhite

Another +1 to this, it'd be a huge help!

@albohlabs

Nice one. +1

@sturobson

+1 can we get this merged into LESS please. It'll help loads, really.

@Chrisui

+1 I feel this is the one major piece of functionality LESS is missing.

(Also: more +1's from another issue: #759)

@icholy icholy referenced this pull request
Closed

Selector Inheritance #759

@json-uk

Has there been any movement on this? Why hasn't the developer pulled this in? All the comparisons between SASS and LESS point to this as one of the killer features. Cloudhead your community desparatwly wants this feature!!!!

@Chrisui

Any chance of taking a look @cloudhead ?

@json-uk

Can someone with prove ledges please add this and release it? This pull request is months old. The LESS community will be very grateful!

@lukeapage
Owner

we will get round to considering this, but I think bugs are higher priority.

@kadamwhite

I can't disagree with the importance of bug fixes, @agatronic, but I'd also second @dtigraphics that time and time again I hear people recommend Sass over LESS because LESS lacks this feature... It's a useful bit of functionality that would really improve the experience of using the tool, IMO, and we'd love to see this prioritized as soon as new features are under discussion.

In the meantime, what can we as a community do to test/support this request? There's a lot of us on this thread by now, if there is anything we can do to speed up the inclusion of this feature we would love to help!

@leopic

If you want this REALLY bad you could just fork the repo and make your own build in the mean time ;)

@icholy

@leopic and then have to go back and fix all your code when a slightly modified version of this feature gets merged.

@leopic

Well you can't have your cake and eat it too, IMHO the whole idea of exposing your source code is that people don't have to wait 8 months before trying out a new feature gets merged, as long as you can make a build you can run your own flavor of your favorite tool =)

@icholy

@leopic that's true when you're hacking at personal projects. But maintaining a patch like this in production quickly turns into a huge pita.

@json-uk
@jmgunn87

Well let's fork and get on with it. Who's first?

@lukeapage
Owner

before you do that please read bug #867 and move this conversation there. we are doing our best!

@superfunkminister

so can this happen now? would be SO AWESOME

@kadamwhite

@agatronic - Thanks for all the work you and the others are doing to maintain this project. Please let us know if we can do anything to vet out this PR... While it is a new feature/increased scope, I have semi-regularly heard people express the lack of extend as the sole reason they are choosing SCSS over LESS and I'd love to be involved in the conversation about how we might address that issue.

@lukeapage
Owner

this one is just waiting for someone to pick it up, evaluate etc. we have had alot of interest and @cloudhead seemed to be interested in it, so I could have a go at merging soon.

@DesignByOnyx

Just wanted to make a request for a different syntax. The "+" sign is a next sibling selector that is easy to confuse with the syntax proposed here. Here is an example of real world code, which could be really confusing when breezing over code.

.shared {
    color: red;
    font-size: 12px;
}

h3 {
    +.shared;
    font-size: 20px;

    + .shared {
        font-size: 18px;
    }
}

I do like the "+" syntax for extending... would it be wise to do something like a double plus "++":

h3 {
    font-size: 20px;
    ++.shared;
}
@jonschlinkert

I completely agree that the + symbol alone is not a good idea for the reasons stated by @DesignByOnyx. I think the ++ is a good idea, it's still clean, and it's very obvious compared to a single +.

@Soviut

Will this syntax work inline in a selector?

h3 ++ .shared {
   font-size: 20px;
}

The space after the ++ could potentially be optional, but I think it might actually fit better into the CSS syntax as an homage to ancestor syntax.

@SomMeri SomMeri referenced this pull request in SomMeri/less4j
Closed

Extending Mixins #31

@DesignByOnyx

@Soviut - I am not sure what your syntax is supposed to imply. The double plus syntax is not really a selector but a LESS version of SASS' @extend operation. The example you give implies that ++ is a selector of some sorts. Let me show LESS code, followed by the compiled CSS:

// LESS
.shared {
    font-size: 12px;
    color: red;
}

h3 {
    ++ .shared;

    font-size: 16px;

    + .shared {
        color: blue;
    }
}

Would produce the following CSS:

.shared,
h3 {
    font-size: 12px;
    color: red;
}

h3 {
    font-size: 16px;
}

h3 + .shared {
    color: blue;
}

I also want to take this opportunity to say that something like ++ would be easier for the parsing engine to catch. I am up for any syntax which is not just a simple + sign or any other standard CSS selector.

@Soviut

Thanks for the explanation. I understood what it was supposed to be used for before, but I was wondering if it could work in the selector syntax.

Regardless, I'm in favour of ++

@lukeapage
Owner

what about using the & parent selector in the context of calling a mixin .. e.g.

.shared {
    font-size: 12px;
    color: red;
}

h3 {
    &,.shared;
    font-size: 16px;
}

h2 {
    &.shared;
    font-size: 10px;
}

becomes

h3, .shared {
    font-size: 12px;
    color: red;
}
h3 {
    font-size: 16px;
}
h2.shared {
    font-size: 12px;
    color: red;
}
h2 {
    font-size: 10px;
}

hrmm.. maybe ++ is better just trying to think what is obvious looking and natural.

@dmcass

Honestly I kind of prefer the explicit @extend instead. Maybe that's just me, but +, ++, and & all seem like they could exist as mistakes within a LESS file...something that could end up being difficult to hunt down. If we do end up using some kind of symbol for it, I'd prefer to use something unique that neither CSS or LESS currently has implemented, and I'd still recommend aliasing @extend.

@DesignByOnyx

I think I agree with @dmcass the most here. LESS already comes with functions to darken(), lighten(), fade(), etc. It seems most proper to have an extend( @selector ) function. I don't agree with the leading @ sign, as that's syntax for SASS... but nonetheless - my vote is for a function.

@jestho

A function might be a bit inconsistent with how LESS operates today, as functions is only in use within properties. I also think one shouldn't need to use more characters than necessary. + is already a native CSS operator, and @ is used for variables in LESS. How about =, % or $?

.foo {
    $.bar;
    border-width: 2px;
}

.foo {
    =.bar;
    border-width: 2px;  
}

.foo {
    %.bar;
    border-width: 2px;  
}
@jonschlinkert

@dmcass and @DesignByOnyx in my code, I haven't found a character or symbol yet which couldn't exist as a mistake... ;)

Kidding aside, I see your point. I also see @jestho's point regarding @DesignByOnyx's suggestion, but regardless of whether or not functions have been used this way in LESS before, this seems like as good of a use case as any to start doing it.

I think we're getting somewhere with this discussion, and I think the function and syntax suggested by @DesignByOnyx make it pretty clear what is being declared - accept that I don't feel very strongly about whether or not the function is preceded by a symbol.

In a perfect world, less.js would have a wip branch so that action can be taken to implement what seems like the best way to solve a problem like this, then we can actually test these scenarios without cause to complain when things blow up. Then the conversation will shift to experience instead of rhetoric (and please don't take that as a jab, or suggestion that I'm not happy with how things are going, quite the contrary... just speaking in ideals...)

@lukeapage
Owner

I'm happy to put ++ or + syntax on a branch. I think a function is clunky.

How about I go with ++ on an experimental branch?

@jonschlinkert

@agatronic I think that's a good decision. In this case, because of the "weight" that the community has placed on this particular feature, an experimental branch seems justified. For now, the separation of concerns will also allow the focus of the main branch to remain on "fixing" instead of features.

We should regard ++ as arbitrary for now, and that implementing the function on a wip-extends or experimental-extends branch allows us to throw darts at 1) is a function the right way to go? 2) what is best syntax? 3) best lexicon? and to accelerate progress towards a solution that works.

And thank you, any movement on this is a big encouragement!

@lukeapage
Owner

I put it into our 1.4.0 branch and changed the syntax into ++

If anyone disagrees / finds a bug / has another suggestion then we can discuss further... it may or may not make it into 1.4.0 but if it doesn't I'll re-open another pull request with the changes in.

@lukeapage lukeapage closed this
@jonschlinkert

nice, thanks!

@dpashkevich

First of all, a big +1 on the feature itself, it makes sense and should help opmimize CSS in big projects.

Just want to add that more explicit SASS-like phrasing:

.mypanel {
  @extend .widget
  ...
}
.expander {
  @include .clearfix
  ...
}

is just easier to remember and read than this:

.mypanel {
  ++.widget
  ...
}
.expander {
  .clearfix
  ...
}

You clearly see what's going on in the first example, it's nearly impossible to get it wrong. I'm not advocating monkeying the SASS implementation though, just pointing out that the suggested syntax looks a bit cryptic, and the more features like this are added, the more cryptic it gets (see @jestho's comment - what if all these existed?). And I agree with the point made by @dmcass that + and ++ is potentially more error-prone.

I can see where @Soviut's suggestion is coming from. The h3 ++ .shared {...} syntax where you define inheritance in the selector string and not inside its body reminds me of the inheritance syntax in classic OOP languages like Java or C++, e.g. class CRectangle: public CPolygon { ... }. I think I like it, that way the "base class" definition never gets lost among other rules inside selector's body. And since there is always only one class we can extend (otherwise there are mixins), this syntax doesn't add much weight to the selector. But of course if it complicates the parser too much as @DesignByOnyx notes, it's probably not worth implementing but still an interesting approach imho.

@lukeapage
Owner

I'm tempted by the selector syntax as it seems to fit better... though what about .a, .b ++ .c ... are you extending .a and .b or just .b? Or should that format be invalid?

@Soviut
@dpashkevich

@agatronic good point made, I didn't think of it.

But let's look at why we write multiple selectors like .a, .b, .c? We do it to avoid code repetition, e.g. give the same style to different elements without copying and pasting definitions. With preprocessors, we have stuff like extending and mixins. The whole point of extending another class (and by class I actually mean any selector) is to reuse its styles but also to add your own definitions that will differ from the base class, e.g.

.a ++ .c {
  // own styles added on top of styles inherited from .c...
}
.b ++ .c {
  // own styles added on top of styles inherited from .c...
  // That are not the same as in .a !
  // otherwise why did I create .b anyway?
}

So telling LESS make .a and .b extend .c and also apply these same extra styles to them doesn't make much sense to me, regardless of which syntax to use for extending, e.g.

.a, .b ++ .c { // .a and .b both extend .c
  // now write _the same_ styles for .a and .b ?! what's the point?
}

// OR

.a, .b {
  ++.c;  // .a and .b both extend .c
  // now write _the same_ styles for .a and .b ?! what's the point?
}

If .a and .b appear to share some of the styles then you should just make one of them extend another (i.e. .a extends .b extends .c).

Another possible interpretation of .a, .b ++ .c is that only .b extends .c but the syntax is still confusing and I think should be prohibited.


P.S. I overlooked the fact that in SASS (and I believe also in the submitted LESS implementation) you can actually do multiple extends. In this regard the "inline" syntax doesn't work well so we should probably go with the originally suggested syntax, e.g.

.seriousError {
  ++.error;
  ++.attention;
  border-width: 3px;
}
@cloudhead
Owner

how about something like

.seriousError {
  < .error;
  < .attention;
}
@matthew-dean

If this makes it into LESS, this has to really be run through the paces. There's a lot of opportunities to lead to confusion here. Questions like: does extending a class / selector extend every mention of it everywhere, in any combination of other classes? How often will this break the cascading inheritance model? And I think this syntax could be potentially confusing:

.myClass {
  ++.topClass;
  + .sibling;
}
@matthew-dean

@cloudhead This > might make more sense, as a kind of reference pointer to the root class.

.seriousError {
  > .error;
  >.attention;  // (With or without space)
}

UPDATE: Wait, ha, never mind, > is already a CSS character.

@cloudhead
Owner

But > means something already.

< is used in some languages, ex ruby to specify inheritance: Cat < Animal

@matthew-dean

Yes, I caught that directly after. Okay, since there's some inheritance of Ruby concepts, and not specifically a reserved character, < could work. Hmm....

@lukeapage
Owner

@matthewdl regarding how it works, the general idea has been to "do what sass does" because thats what people find really useful over there and I think that is quite well understood. If you look at the examples in the test cases for some time you'll see the idea of how it works is already quite thought out (and answering your questions above I think). More complex cases as in #1014 do need to be looked at though.

"Questions like: does extending a class / selector extend every mention of it everywhere, in any combination of other classes?"

yes

"How often will this break the cascading inheritance model? "

Not sure what you mean? What will it break?

"And I think this syntax could be potentially confusing"

the second part of the example is not currently valid less so it would syntax error. what do you mean?

I like @cloudhead's suggestion for <.

But yes.. I am here to try to sort this issue out. I'm for it because its a hotly asked for request seems like it adds value and is already implemented. I'll let one of the active supporters of it answer your questions.

@matthew-dean

Yep, it seems like the consensus is to put it in. I just want to raise questions so that a) we fully understand what the goals are and what devs want to accomplish, b) that we don't automatically assume that just because SASS solved something a certain way doesn't mean it's the only or best way to do so.

In the case of inheritance, I just mean that when things are grouped, the order of properties / selectors change, which can lead to unexpected output, whereas the current additive model of LESS, while more verbose in output, preserves declaration (cascading) order. No doubt SASS comes up against the same shortcomings, and probably in many cases, devs might make the case that the value outweighs the added complexity.

Which part was not valid LESS?

@jonschlinkert

@matthewdl well said, this conversation is exactly what I was hoping would happen once an experimental branch was put up.

I put this gist up to summarize proposals to date (please comment on the gist if I missed or mischaracterized something): https://gist.github.com/3989438

Here is my proposal:

E:extend(selector) {...}

So rather than using combinators as previously suggested, this syntax leverages a concept that already exists in CSS for targeting elements, attributes, selectors, classes, ids, etc. We already do:

.foo:nth-child(3) {...}

and the :not(selector) even allows you to target a comma separated list of elements.

.foo:not(.bar, .baz) {...}

Some examples:

.alert:extend(.alert-important, .alert-danger) {
    background: red;
}

or

.alert {
    background: red;
    &:extend(.alert-important, .alert-danger);
}

or

.alert:extend(.alert-important, .alert-danger) {
    background: red;
    .alert-header:extend(.modal-header) {...}
}
@SomMeri
Owner

I may be wrong, bug googling "less extend" will probably find less documentation while googling "less ++" will probably find a lot of random sites. Plus, if it is named extend I can safely guess what it does without googling it or remembering special symbols table.

@DesignByOnyx
@matthew-dean

@jonschlinkert Your proposed syntax is pretty close to what I was envisioning in my head. It feels more elegant, and like mixin guards for LESS which mimic media query syntax, it feels more like an extension of CSS, and therefore, more LESS-like than other symbols.

Plus, by making :extend in the declaration, it more accurately describes that this class definition will be merged with other selectors (and which ones). Having the extend declaration arbitrarily placed somewhere within the list of properties doesn't feel right for an extending behavior. This is on par with, say, the ":not" psuedo-class, and some of the jQuery pseudo-class extensions which mimic CSS.

Very nice work. This syntax, in itself, makes me like the whole concept of extend even more, because it's much more clearly defined.

+1 to @jonschlinkert's syntax

@Soviut
@Soviut
@lukeapage
Owner

@Soviut - when you reply in emails, click off the quote - then we get cleaner comments :)

@jonschlinkert nice. I like the idea we can use it for both stand alone and as part of the selector. some questions

  1. same as before .a, .b:extend(.c) ... does the extend cover both selectors .a and .b or should it be disallowed?
  2. is there any difference between .b :extend(.c) and .b:extend(.c) ?

If I get some time I'll look at implementing this and also figuring out how to fix #1104.. does every agree with #1104 btw? I haven't had time to figure it out.

I would love it If anyone else would prefer to do the coding, as I have plenty of other less coding to do.

@dpashkevich

I like @jonschlinkert suggestion too. I wouldn't want the inheritance definition get lost among property definitions. It can still be surrounded by other pseudo-class definitions, though, but then I would probably put them on separate lines like so:

.alert
    :extend(.alert-important, .alert-danger) 
    :first-child
    :hover
    {
    background: red;
    ...
}

Of course the example is rather esoteric and in LESS I should use the & combinator nested inside the main selector instead but this syntax should still be valid, right?

One concern that I have is about pseudo-elements. The following line:

.alert::before:extend(.shiny-tip) {}

Is supposed to mean that the ::before pseudo-element extends .shiny-tip but the syntax is a bit confusing in this case.

P.S. With the Shadow DOM spec we will see way more pseudo-elements coming!

@lukeapage
Owner
@Soviut

True, the :extend syntax, while CSS in spirit, deviates significantly from the SASS style @extend in terms of implementation.

@lukeapage
Owner
@jonschlinkert

@agatronic the point you bring up is valid for straight CSS as well, meaning that it seems confusing. It wouldn't surprise me if a lot of front-end folks didn't know that the spec currently allows for chaining pseudo-selectors at all.

My view (conjecture?) is that if you use pseudo-selectors regularly in your CSS, then you should have very little learning curve here. As for whether or not chaining should be allowed, it seems that it would be difficult to implement without it, at least eventually. Just consider hover and active as prime examples. I think if we view the problem from 20,000 feet, we shouldn't allow the syntax to determine the objective.

It makes the most sense to consider the following as a typical use-case, and a reason to allow chaining:

E:hover:extend(...) {}

We make regular use of these pseudo-selectors:

E:hover {}
E:active {}
E:before {}
E:after {}

So my suggestion is to think if it in that context, rather than thinking of more complicated and less-often used use cases like:

p:first-child:first-letter:first-line:after:hover {}

Which, btw, is valid. But would anyone use it? I guess, yeah, sure if I had to... but it's not a probably not a good use case lol.

That being said, I'm aware that you have to weigh this against other considerations, so it's ultimately up to you whether or not chaining will be introduced in the first iteration of the :extend feature.

My vote is that :extend is still powerful without chaining, but even more useful with it. So do whatever is pragmatic for now..

@lukeapage
Owner
@matthew-dean
Owner

To jump in, no, I don't think :extend should be allowed in the middle of the selector. Like jQuery's extensions, it still belongs at the end. It should apply to the entire selector as a string match.

To extend a block like above:

E:hover:extend(...), E:active:extend(...) {
  property: value;
}

// equivalent to:

E:hover, E:active {
  &:extend(...) {
    property: value;
  }
}

This allows you to separate and use LESS in coherent blocks, extending only the properties you want to base classes, while having some properties only be local one-off values, or controlling output order.

E:hover, E:active {
  &:extend(...) {
    property: value;
  }
  non-merged-property: value;
}

In other words, this syntax I think would be simpler to understand and also a bit more powerful than SASS.

@lukeapage
Owner
@jonschlinkert

I've had some time to test :extend in 1_4_0 (using the default test files as well as Bootstrap's Less), and so far it works as expected. Lot's more testing to do, but I'm also looking forward to seeing feedback from others. Thanks for the hard work on this!

@Synchro
Owner

It would be much appreciated if you could contribute some examples and edge cases to add to the tests.

@jonschlinkert

@Synchro no problem, I'd be happy to. I'll try to put something together this week.

@lukeapage
Owner
@jonschlinkert

I think only the first example should be valid. &:extend conforms to a known pattern in Less

@Soviut

I agree. It should follow the correct selector logic if it's going to be treated as a pseudo-selector. The first example reads as "extend .b with .a" while the second example reads as "extend the decendents of .b".

@Soviut

Documentation-wise, I think the .b:extends(.a) syntax should be pushed more prominently though.

@matthew-dean

@Soviut +1 to that, too.

@jonschlinkert

@agatronic and forgot to mention, no problem on the tests either way. I did run the tests included in 1_4_0, everything checks out. If you want me to throw more together as 1_4_0 progresses just say the word

@lukeapage
Owner

this is the bug I would appreciate comments on

#1014

@jonschlinkert

@agatronic will do, I'm putting something together since there is some thought involved here. I'll update as soon as I have something to share.

@feichang

+1 for extend

@vitrig

why not to just steal @extend syntax from SASS?

@lukeapage
Owner
@DesignByOnyx

I have finally gotten around to testing this and wanted to post my initial findings. I have been using the alpha version less-1.4.0-alpha.js on the client-side only (no command line yet - not that it should be any different really).

So far, everything works as I would expect except for two major drawbacks which can be explained with one example. Take the following code which is located in one of my root LESS files:

.container { margin: 0 auto; }
.container.positioned { position: absolute }

@media screen and (min-width: 30rem) {
    .container.positioned { left: 50%; }
}
@media screen and (min-width: 30rem) and (max-width: 48rem) {
    .container { width: 30rem; }
    .container.positioned { margin-left: -15rem; }
}
@media screen and (min-width: 48rem) and (max-width: 60rem) {
    .container { width: 48rem; }
    .container.positioned { margin-left: -24rem; }
}
@media screen and (min-width: 60rem) {
    .container { width: 60rem; }
    .container.positioned { margin-left: -30rem; }
}

Issue 1 - styles defined within media queries do not get extended. Anything trying to extend the .container class only gets the margin: 0 auto styles.

.some-element:extend(.container);

Issue 2 - compound selectors do not get extended. However, the first participant DOES get extended. For example, the following incorrectly extends the .container styles but not the intended .container.positioned styles.

.some-element:extend(.container.positioned);

I wish I could provide a solution. Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 5, 2011
  1. @hokaccha

    Add Sass like extend

    hokaccha authored
Commits on Dec 13, 2011
  1. @hokaccha
Commits on Dec 16, 2011
  1. @hokaccha
This page is out of date. Refresh to see the latest.
View
2  lib/less/index.js
@@ -78,7 +78,7 @@ var less = {
'selector', 'quoted', 'expression', 'rule',
'call', 'url', 'alpha', 'import',
'mixin', 'comment', 'anonymous', 'value',
- 'javascript', 'assignment'
+ 'javascript', 'assignment', 'extend'
].forEach(function (n) {
require('./tree/' + n);
});
View
20 lib/less/parser.js
@@ -435,7 +435,8 @@ less.Parser = function Parser(env) {
var node, root = [];
while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) ||
- $(this.mixin.call) || $(this.comment) || $(this.directive))
+ $(this.mixin.call) || $(this.comment) || $(this.directive) ||
+ $(this.extend))
|| $(/^[\s\n]+/)) {
node && root.push(node);
}
@@ -673,6 +674,23 @@ less.Parser = function Parser(env) {
},
//
+ // extend
+ //
+ extend: function() {
+ var elements = [], e, c, args, index = i, s = input.charAt(i);
+
+ if (s !== '+') { return }
+
+ while (e = $(/^\+[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) {
+ elements.push(new(tree.Element)(c, e.slice(1), i));
+ }
+
+ if (elements.length > 0 && ($(';') || peek('}'))) {
+ return new(tree.Extend)(elements, index);
+ }
+ },
+
+ //
// Mixins
//
mixin: {
View
56 lib/less/tree/extend.js
@@ -0,0 +1,56 @@
+(function (tree) {
+
+tree.Extend = function Extend(elements, index) {
+ this.selector = new(tree.Selector)(elements);
+ this.index = index;
+};
+
+tree.Extend.prototype.eval = function Extend_eval(env) {
+ var selfSelectors = findSelfSelectors(env.selectors),
+ targetValue = this.selector.elements[0].value;
+
+ env.frames.forEach(function(frame) {
+ frame.rulesets().forEach(function(rule) {
+ rule.selectors.forEach(function(selector) {
+ selector.elements.forEach(function(element, idx) {
+ if (element.value === targetValue) {
+ selfSelectors.forEach(function(_selector) {
+ _selector.elements[0] = new tree.Element(
+ element.combinator,
+ _selector.elements[0].value,
+ _selector.elements[0].index
+ );
+ rule.selectors.push(new tree.Selector(
+ selector.elements
+ .slice(0, idx)
+ .concat(_selector.elements)
+ .concat(selector.elements.slice(idx + 1))
+ ));
+ });
+ }
+ });
+ });
+ });
+ });
+ return this;
+};
+
+function findSelfSelectors(selectors) {
+ var ret = [];
+
+ (function loop(elem, i) {
+ if (selectors[i] && selectors[i].length) {
+ selectors[i].forEach(function(s) {
+ loop(s.elements.concat(elem), i + 1);
+ });
+ }
+ else {
+ ret.push({ elements: elem });
+ }
+ })([], 0);
+
+ return ret;
+}
+
+
+})(require('../tree'));
View
7 lib/less/tree/ruleset.js
@@ -14,6 +14,12 @@ tree.Ruleset.prototype = {
// push the current ruleset to the frames stack
env.frames.unshift(ruleset);
+ // currrent selectors
+ if (!env.selectors) {
+ env.selectors = [];
+ }
+ env.selectors.unshift(this.selectors);
+
// Evaluate imports
if (ruleset.root) {
for (var i = 0; i < ruleset.rules.length; i++) {
@@ -51,6 +57,7 @@ tree.Ruleset.prototype = {
// Pop the stack
env.frames.shift();
+ env.selectors.shift();
return ruleset;
},
View
15 test/css/extend-clearfix.css
@@ -0,0 +1,15 @@
+.clearfix, .foo, .bar {
+ *zoom: 1;
+}
+.clearfix:after, .foo:after, .bar:after {
+ content: '';
+ display: block;
+ clear: both;
+ height: 0;
+}
+.foo {
+ color: red;
+}
+.bar {
+ color: blue;
+}
View
15 test/css/extend-nest.css
@@ -0,0 +1,15 @@
+.sidebar, .sidebar2, .type1 .sidebar3 {
+ width: 300px;
+ background: red;
+}
+.sidebar .box, .sidebar2 .box, .type1 .sidebar3 .box {
+ background: #FFF;
+ border: 1px solid #000;
+ margin: 10px 0;
+}
+.sidebar2 {
+ background: blue;
+}
+.type1 .sidebar3 {
+ background: green;
+}
View
30 test/css/extend.css
@@ -0,0 +1,30 @@
+.error, .badError {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion, .badError.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error, .intrusion .badError {
+ display: none;
+}
+.badError {
+ border-width: 3px;
+}
+.foo .bar,
+.foo .baz,
+.ext1 .ext2 .bar,
+.ext1 .ext2 .baz,
+.ext3 .bar,
+.ext4 .bar,
+.ext3 .baz,
+.ext4 .baz {
+ display: none;
+}
+div.ext5,
+.ext6 > .ext5,
+div.ext7,
+.ext6 > .ext7 {
+ width: 100px;
+}
View
19 test/less/extend-clearfix.less
@@ -0,0 +1,19 @@
+.clearfix {
+ *zoom: 1;
+ &:after {
+ content: '';
+ display: block;
+ clear: both;
+ height: 0;
+ }
+}
+
+.foo {
+ +.clearfix;
+ color: red;
+}
+
+.bar {
+ +.clearfix;
+ color: blue;
+}
View
22 test/less/extend-nest.less
@@ -0,0 +1,22 @@
+.sidebar {
+ width: 300px;
+ background: red;
+
+ .box {
+ background: #FFF;
+ border: 1px solid #000;
+ margin: 10px 0;
+ }
+}
+
+.sidebar2 {
+ +.sidebar;
+ background: blue;
+}
+
+.type1 {
+ .sidebar3 {
+ +.sidebar;
+ background: green;
+ }
+}
View
35 test/less/extend.less
@@ -0,0 +1,35 @@
+.error {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error {
+ display: none;
+}
+.badError {
+ +.error;
+ border-width: 3px;
+}
+
+.foo .bar, .foo .baz {
+ display: none;
+}
+
+.ext1 .ext2 {
+ +.foo;
+}
+
+.ext3, .ext4 {
+ +.foo;
+}
+
+div.ext5, .ext6 > .ext5 {
+ width: 100px;
+}
+
+.ext7 {
+ +.ext5;
+}
Something went wrong with that request. Please try again.