@@ -11,12 +11,13 @@ const CSSVariablesCollectorPlugin = module.exports = function(config) {
1111 this . ruleStack = [ ] ;
1212 this . mixinStack = [ ] ;
1313 this . parenStack = [ ] ;
14- this . importStack = [ ] ;
1514} ;
1615
1716CSSVariablesCollectorPlugin . prototype = {
1817
18+ // needed to keep the less variable references intact to use this info for the CSS variables references
1919 isPreEvalVisitor : true ,
20+
2021 isReplacing : true ,
2122
2223 _isInMixinOrParen ( ) {
@@ -27,28 +28,41 @@ CSSVariablesCollectorPlugin.prototype = {
2728 return this . ruleStack . length > 0 && ! this . ruleStack [ this . ruleStack . length - 1 ] . variable ;
2829 } ,
2930
30- _isVarInLibrary ( ) {
31- // the last less file defines the location of the css variable and this must
32- // be in the path of the current library, otherwise it is an external variable
33- const regexp = new RegExp ( `^/resources/${ this . config . libPath } /themes/` ) ;
34- return this . importStack . length > 0 ? regexp . test ( this . importStack [ this . importStack . length - 1 ] . importedFilename ) : true ;
31+ _isVarInLibrary ( { varName, filename} ) {
32+ // for libraries we check that the file is within the libraries theme path
33+ // in all other cases with no filename (indicates calculated variables)
34+ // or in case of variables in standalone less files we just include them!
35+ const include = ! filename ||
36+ ( this . config . libPath ? filename . startsWith ( `/resources/${ this . config . libPath } /themes/` ) : true ) ;
37+ return include ;
3538 } ,
3639
3740 _isRelevant ( ) {
3841 return ! this . _isInMixinOrParen ( ) && this . _isVarInRule ( ) ;
3942 } ,
4043
41- toLessVariables ( ) {
44+ toLessVariables ( varsOverride ) {
45+ const vars = { } ;
46+ Object . keys ( this . vars ) . forEach ( ( key ) => {
47+ const override = this . vars [ key ] . updateAfterEval && varsOverride [ key ] !== undefined ;
48+ if ( override ) {
49+ console . log ( `Override variable "${ key } " from "${ this . vars [ key ] . css } " to "${ varsOverride [ key ] . css } "` ) ;
50+ }
51+ vars [ key ] = {
52+ css : override ? varsOverride [ key ] . css : this . vars [ key ] . css ,
53+ export : this . vars [ key ] . export
54+ } ;
55+ } ) ;
4256 let lessVariables = "" ;
43- Object . keys ( this . vars ) . forEach ( ( value , index ) => {
44- lessVariables += "@" + value + ": " + this . vars [ value ] . css + ";\n" ;
57+ Object . keys ( vars ) . forEach ( ( value , index ) => {
58+ lessVariables += "@" + value + ": " + vars [ value ] . css + ";\n" ;
4559 } ) ;
4660 Object . keys ( this . calcVars ) . forEach ( ( value , index ) => {
4761 lessVariables += "@" + value + ": " + this . calcVars [ value ] . css + ";\n" ;
4862 } ) ;
4963 lessVariables += "\n:root {\n" ;
50- Object . keys ( this . vars ) . forEach ( ( value , index ) => {
51- if ( this . vars [ value ] . export ) {
64+ Object . keys ( vars ) . forEach ( ( value , index ) => {
65+ if ( vars [ value ] . export ) {
5266 lessVariables += "--" + value + ": @" + value + ";\n" ;
5367 }
5468 } ) ;
@@ -96,7 +110,7 @@ CSSVariablesCollectorPlugin.prototype = {
96110 } ,
97111
98112 visitCall ( node , visitArgs ) {
99- // if variables are used inside rules, generate a new dynamic variable for it!
113+ // if variables are used inside rules, generate a new calculated variable for it!
100114 const isRelevantFunction = typeof less . tree . functions [ node . name ] === "function" && [ "rgba" ] . indexOf ( node . name ) === - 1 ;
101115 if ( this . _isRelevant ( ) && isRelevantFunction ) {
102116 const css = this . _getCSS ( node ) ;
@@ -110,7 +124,9 @@ CSSVariablesCollectorPlugin.prototype = {
110124 }
111125 this . calcVars [ newName ] = {
112126 css : css ,
113- export : this . _isVarInLibrary ( )
127+ export : this . _isVarInLibrary ( {
128+ varName : newName
129+ } )
114130 } ;
115131 return new less . tree . Call ( "var" , [ new less . tree . Anonymous ( "--" + newName , node . index , node . currentFileInfo , node . mapLines ) ] ) ;
116132 }
@@ -169,30 +185,32 @@ CSSVariablesCollectorPlugin.prototype = {
169185 return node ;
170186 } ,
171187
172- visitImport ( node , visitArgs ) {
173- // store the import context
174- this . importStack . push ( node ) ;
175- return node ;
176- } ,
177-
178- visitImportOut ( node ) {
179- // remove import context
180- this . importStack . pop ( ) ;
181- return node ;
182- } ,
183-
184188 visitRuleset ( node , visitArgs ) {
185189 node . rules . forEach ( ( value ) => {
186190 const isVarDeclaration = value instanceof less . tree . Rule && typeof value . name === "string" && value . name . startsWith ( "@" ) ;
187191 if ( ! this . _isInMixinOrParen ( ) && isVarDeclaration ) {
188192 // add the variable declaration to the list of vars
189- this . vars [ value . name . substr ( 1 ) ] = {
193+ const varName = value . name . substr ( 1 ) ;
194+ this . vars [ varName ] = {
190195 css : this . _getCSS ( value . value ) ,
191- export : this . _isVarInLibrary ( )
196+ export : this . _isVarInLibrary ( {
197+ varName,
198+ filename : value . currentFileInfo . filename
199+ } )
192200 } ;
193201 }
194202 } ) ;
195203 return node ;
204+ } ,
205+
206+ visitUrl ( node , visitArgs ) {
207+ // we mark the less variables which should be updated after eval
208+ // => strangewise less variables with "none" values are also urls
209+ // after the less variables have been evaluated
210+ if ( this . ruleStack . length > 0 && this . ruleStack [ 0 ] . variable ) {
211+ this . vars [ this . ruleStack [ 0 ] . name . substr ( 1 ) ] . updateAfterEval = true ;
212+ }
213+ return node ;
196214 }
197215
198216} ;
0 commit comments