@@ -941,10 +941,6 @@ less.Parser = function Parser(env) {
941
941
942
942
option = option && option [ 1 ] ;
943
943
944
- if ( option != "all" ) {
945
- error ( ":extend only supports the all option at the moment, please specify it after your selector, e.g. :extend(.a all)" ) ;
946
- }
947
-
948
944
if ( isRule ) {
949
945
expect ( / ^ ; / ) ;
950
946
}
@@ -3155,6 +3151,25 @@ tree.Extend = function Extend(selector, option, index) {
3155
3151
this . selector = selector ;
3156
3152
this . option = option ;
3157
3153
this . index = index ;
3154
+
3155
+ switch ( option ) {
3156
+ case "all" :
3157
+ this . deep = true ;
3158
+ this . any = true ;
3159
+ break ;
3160
+ case "deep" :
3161
+ this . deep = true ;
3162
+ this . any = false ;
3163
+ break ;
3164
+ case "any" :
3165
+ this . deep = false ;
3166
+ this . any = true ;
3167
+ break ;
3168
+ default :
3169
+ this . deep = false ;
3170
+ this . any = false ;
3171
+ break ;
3172
+ }
3158
3173
} ;
3159
3174
3160
3175
tree . Extend . prototype = {
@@ -4958,24 +4973,51 @@ tree.jsify = function (obj) {
4958
4973
for ( k = 0 ; k < allExtends . length ; k ++ ) {
4959
4974
for ( i = 0 ; i < rulesetNode . paths . length ; i ++ ) {
4960
4975
selectorPath = rulesetNode . paths [ i ] ;
4961
- var match = this . findMatch ( allExtends [ k ] , selectorPath ) ;
4962
- if ( match ) {
4963
- selector = selectorPath [ match . pathIndex ] ;
4976
+ var matches = this . findMatch ( allExtends [ k ] , selectorPath ) ;
4977
+ if ( matches . length ) {
4964
4978
allExtends [ k ] . selfSelectors . forEach ( function ( selfSelector ) {
4965
- var path = selectorPath . slice ( 0 , match . pathIndex ) ,
4966
- firstElement = new tree . Element (
4967
- match . initialCombinator ,
4968
- selfSelector . elements [ 0 ] . value ,
4969
- selfSelector . elements [ 0 ] . index
4970
- ) ;
4971
- path . push ( new tree . Selector (
4972
- selector . elements
4973
- . slice ( 0 , match . index )
4974
- . concat ( [ firstElement ] )
4975
- . concat ( selfSelector . elements . slice ( 1 ) )
4976
- . concat ( selector . elements . slice ( match . index + match . length ) )
4977
- ) ) ;
4978
- path = path . concat ( selectorPath . slice ( match . endPathIndex + 1 , selectorPath . length ) ) ;
4979
+ var currentSelectorPathIndex = 0 ,
4980
+ currentSelectorPathElementIndex = 0 ,
4981
+ path = [ ] ;
4982
+ for ( j = 0 ; j < matches . length ; j ++ ) {
4983
+ match = matches [ j ] ;
4984
+ var selector = selectorPath [ match . pathIndex ] ,
4985
+ firstElement = new tree . Element (
4986
+ match . initialCombinator ,
4987
+ selfSelector . elements [ 0 ] . value ,
4988
+ selfSelector . elements [ 0 ] . index
4989
+ ) ;
4990
+
4991
+ if ( match . pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0 ) {
4992
+ path [ path . length - 1 ] . elements = path [ path . length - 1 ] . elements . concat ( selectorPath [ currentSelectorPathIndex ] . elements . slice ( currentSelectorPathElementIndex ) ) ;
4993
+ currentSelectorPathElementIndex = 0 ;
4994
+ currentSelectorPathIndex ++ ;
4995
+ }
4996
+
4997
+ path = path . concat ( selectorPath . slice ( currentSelectorPathIndex , match . pathIndex ) ) ;
4998
+
4999
+ path . push ( new tree . Selector (
5000
+ selector . elements
5001
+ . slice ( currentSelectorPathElementIndex , match . index )
5002
+ . concat ( [ firstElement ] )
5003
+ . concat ( selfSelector . elements . slice ( 1 ) )
5004
+ ) ) ;
5005
+ currentSelectorPathIndex = match . endPathIndex ;
5006
+ currentSelectorPathElementIndex = match . endPathElementIndex ;
5007
+ if ( currentSelectorPathElementIndex >= selector . elements . length ) {
5008
+ currentSelectorPathElementIndex = 0 ;
5009
+ currentSelectorPathIndex ++ ;
5010
+ }
5011
+ }
5012
+
5013
+ if ( currentSelectorPathIndex < selectorPath . length && currentSelectorPathElementIndex > 0 ) {
5014
+ path [ path . length - 1 ] . elements = path [ path . length - 1 ] . elements . concat ( selectorPath [ currentSelectorPathIndex ] . elements . slice ( currentSelectorPathElementIndex ) ) ;
5015
+ currentSelectorPathElementIndex = 0 ;
5016
+ currentSelectorPathIndex ++ ;
5017
+ }
5018
+
5019
+ path = path . concat ( selectorPath . slice ( currentSelectorPathIndex , selectorPath . length ) ) ;
5020
+
4979
5021
selectorsToAdd . push ( path ) ;
4980
5022
} ) ;
4981
5023
}
@@ -4984,29 +5026,41 @@ tree.jsify = function (obj) {
4984
5026
rulesetNode . paths = rulesetNode . paths . concat ( selectorsToAdd ) ;
4985
5027
} ,
4986
5028
findMatch : function ( extend , selectorPath ) {
4987
- var i , j , k , l , targetElementIndex , element , hasMatch , potentialMatches = [ ] , potentialMatch , matches = [ ] ;
5029
+ var i , k , l , element , hasMatch , potentialMatches = [ ] , potentialMatch , matches = [ ] ;
4988
5030
for ( k = 0 ; k < selectorPath . length ; k ++ ) {
4989
5031
selector = selectorPath [ k ] ;
4990
5032
for ( i = 0 ; i < selector . elements . length ; i ++ ) {
4991
- potentialMatches . push ( { pathIndex : k , index : i , matched : 0 } ) ;
5033
+ if ( extend . any || ( k == 0 && i == 0 ) ) {
5034
+ potentialMatches . push ( { pathIndex : k , index : i , matched : 0 , initialCombinator : selector . elements [ i ] . combinator } ) ;
5035
+ }
4992
5036
4993
5037
for ( l = 0 ; l < potentialMatches . length ; l ++ ) {
4994
5038
potentialMatch = potentialMatches [ l ] ;
4995
- targetElementIndex = i ;
4996
- for ( j = potentialMatch . matched ; j < extend . selector . elements . length && targetElementIndex < selector . elements . length ; j ++ , targetElementIndex ++ ) {
4997
- potentialMatch . matched = j + 1 ;
4998
- if ( extend . selector . elements [ j ] . value !== selector . elements [ targetElementIndex ] . value ||
4999
- ( j > 0 && extend . selector . elements [ j ] . combinator . value !== selector . elements [ targetElementIndex ] . combinator . value ) ) {
5039
+
5040
+ var targetCombinator = selector . elements [ i ] . combinator . value ;
5041
+ if ( targetCombinator == '' && i === 0 ) {
5042
+ targetCombinator = ' ' ;
5043
+ }
5044
+ if ( extend . selector . elements [ potentialMatch . matched ] . value !== selector . elements [ i ] . value ||
5045
+ ( potentialMatch . matched > 0 && extend . selector . elements [ potentialMatch . matched ] . combinator . value !== targetCombinator ) ) {
5046
+ potentialMatch = null ;
5047
+ } else {
5048
+ potentialMatch . matched ++ ;
5049
+ }
5050
+
5051
+ if ( potentialMatch ) {
5052
+ potentialMatch . finished = potentialMatch . matched === extend . selector . elements . length ;
5053
+ if ( potentialMatch . finished &&
5054
+ ( ! extend . deep && ( i + 1 < selector . elements . length ||
5055
+ k + 1 < selectorPath . length ) ) ) {
5000
5056
potentialMatch = null ;
5001
- break ;
5002
5057
}
5003
5058
}
5004
5059
if ( potentialMatch ) {
5005
- if ( potentialMatch . matched === extend . selector . elements . length ) {
5006
- potentialMatch . initialCombinator = selector . elements [ i ] . combinator ;
5060
+ if ( potentialMatch . finished ) {
5007
5061
potentialMatch . length = extend . selector . elements . length ;
5008
5062
potentialMatch . endPathIndex = k ;
5009
- return potentialMatch ;
5063
+ potentialMatch . endPathElementIndex = i + 1 ; // index after end of match
5010
5064
potentialMatches . length = 0 ;
5011
5065
matches . push ( potentialMatch ) ;
5012
5066
break ;
@@ -5018,7 +5072,6 @@ tree.jsify = function (obj) {
5018
5072
}
5019
5073
}
5020
5074
}
5021
- return null ;
5022
5075
return matches ;
5023
5076
} ,
5024
5077
visitRulesetOut : function ( rulesetNode ) {
0 commit comments