@@ -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,27 +28,44 @@ CSSVariablesCollectorPlugin.prototype = {
2728 return this . ruleStack . length > 0 && ! this . ruleStack [ this . ruleStack . length - 1 ] . variable ;
2829 } ,
2930
30- _isInGlobalOrBaseImport ( ) {
31- return this . config . libName !== "sap.ui.core" && this . importStack . filter ( ( importNode ) => {
32- return / \/ (?: g l o b a l | b a s e ) \. l e s s $ / . test ( importNode . importedFilename ) ;
33- } ) . length > 0 ;
31+ _isVarInLibrary ( { 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 regex = new RegExp ( `(^|/)${ this . config . libPath } /themes/` ) ;
36+ const include = ! filename ||
37+ ( this . config . libPath ? regex . test ( filename ) : true ) ;
38+ return include ;
3439 } ,
3540
3641 _isRelevant ( ) {
3742 return ! this . _isInMixinOrParen ( ) && this . _isVarInRule ( ) ;
3843 } ,
3944
40- toLessVariables ( ) {
45+ toLessVariables ( varsOverride ) {
46+ const vars = { } ;
47+ Object . keys ( this . vars ) . forEach ( ( key ) => {
48+ const override = this . vars [ key ] . updateAfterEval && varsOverride [ key ] !== undefined ;
49+ /*
50+ if (override) {
51+ console.log(`Override variable "${key}" from "${this.vars[key].css}" to "${varsOverride[key]}"`);
52+ }
53+ */
54+ vars [ key ] = {
55+ css : override ? varsOverride [ key ] : this . vars [ key ] . css ,
56+ export : this . vars [ key ] . export
57+ } ;
58+ } ) ;
4159 let lessVariables = "" ;
42- Object . keys ( this . vars ) . forEach ( ( value , index ) => {
43- lessVariables += "@" + value + ": " + this . vars [ value ] . css + ";\n" ;
60+ Object . keys ( vars ) . forEach ( ( value , index ) => {
61+ lessVariables += "@" + value + ": " + vars [ value ] . css + ";\n" ;
4462 } ) ;
4563 Object . keys ( this . calcVars ) . forEach ( ( value , index ) => {
4664 lessVariables += "@" + value + ": " + this . calcVars [ value ] . css + ";\n" ;
4765 } ) ;
4866 lessVariables += "\n:root {\n" ;
49- Object . keys ( this . vars ) . forEach ( ( value , index ) => {
50- if ( this . vars [ value ] . export ) {
67+ Object . keys ( vars ) . forEach ( ( value , index ) => {
68+ if ( vars [ value ] . export ) {
5169 lessVariables += "--" + value + ": @" + value + ";\n" ;
5270 }
5371 } ) ;
@@ -89,15 +107,17 @@ CSSVariablesCollectorPlugin.prototype = {
89107
90108 visitOperation ( node , visitArgs ) {
91109 if ( this . _isRelevant ( ) ) {
110+ // console.log("visitOperation", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
92111 return new less . tree . Call ( "calc" , [ new less . tree . Expression ( [ node . operands [ 0 ] , new less . tree . Anonymous ( node . op ) , node . operands [ 1 ] ] ) ] ) ;
93112 }
94113 return node ;
95114 } ,
96115
97116 visitCall ( node , visitArgs ) {
98- // if variables are used inside rules, generate a new dynamic variable for it!
117+ // if variables are used inside rules, generate a new calculated variable for it!
99118 const isRelevantFunction = typeof less . tree . functions [ node . name ] === "function" && [ "rgba" ] . indexOf ( node . name ) === - 1 ;
100119 if ( this . _isRelevant ( ) && isRelevantFunction ) {
120+ // console.log("visitCall", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
101121 const css = this . _getCSS ( node ) ;
102122 let newName = this . config . prefix + "function_" + node . name + Object . keys ( this . vars ) . length ;
103123 // check for duplicate value in vars already
@@ -109,7 +129,7 @@ CSSVariablesCollectorPlugin.prototype = {
109129 }
110130 this . calcVars [ newName ] = {
111131 css : css ,
112- export : ! this . _isInGlobalOrBaseImport ( )
132+ export : this . _isVarInLibrary ( )
113133 } ;
114134 return new less . tree . Call ( "var" , [ new less . tree . Anonymous ( "--" + newName , node . index , node . currentFileInfo , node . mapLines ) ] ) ;
115135 }
@@ -119,6 +139,7 @@ CSSVariablesCollectorPlugin.prototype = {
119139 visitNegative ( node , visitArgs ) {
120140 // convert negative into calc function
121141 if ( this . _isRelevant ( ) ) {
142+ // console.log("visitNegative", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
122143 return new less . tree . Call ( "calc" , [ new less . tree . Expression ( [ new less . tree . Anonymous ( "-1" ) , new less . tree . Anonymous ( "*" ) , node . value ] ) ] ) ;
123144 }
124145 return node ;
@@ -133,6 +154,19 @@ CSSVariablesCollectorPlugin.prototype = {
133154 } ,
134155
135156 visitRule ( node , visitArgs ) {
157+ // check rule for being a variable declaration
158+ const isVarDeclaration = typeof node . name === "string" && node . name . startsWith ( "@" ) ;
159+ if ( ! this . _isInMixinOrParen ( ) && isVarDeclaration ) {
160+ // add the variable declaration to the list of vars
161+ const varName = node . name . substr ( 1 ) ;
162+ const isVarInLib = this . _isVarInLibrary ( {
163+ filename : node . currentFileInfo . filename
164+ } ) ;
165+ this . vars [ varName ] = {
166+ css : this . _getCSS ( node . value ) ,
167+ export : isVarInLib
168+ } ;
169+ }
136170 // store the rule context for the call variable extraction
137171 this . ruleStack . push ( node ) ;
138172 return node ;
@@ -168,29 +202,13 @@ CSSVariablesCollectorPlugin.prototype = {
168202 return node ;
169203 } ,
170204
171- visitImport ( node , visitArgs ) {
172- // store the import context
173- this . importStack . push ( node ) ;
174- return node ;
175- } ,
176-
177- visitImportOut ( node ) {
178- // remove import context
179- this . importStack . pop ( ) ;
180- return node ;
181- } ,
182-
183- visitRuleset ( node , visitArgs ) {
184- node . rules . forEach ( ( value ) => {
185- const isVarDeclaration = value instanceof less . tree . Rule && typeof value . name === "string" && value . name . startsWith ( "@" ) ;
186- if ( ! this . _isInMixinOrParen ( ) && isVarDeclaration ) {
187- // add the variable declaration to the list of vars
188- this . vars [ value . name . substr ( 1 ) ] = {
189- css : this . _getCSS ( value . value ) ,
190- export : ! this . _isInGlobalOrBaseImport ( )
191- } ;
192- }
193- } ) ;
205+ visitUrl ( node , visitArgs ) {
206+ // we mark the less variables which should be updated after eval
207+ // => strangewise less variables with "none" values are also urls
208+ // after the less variables have been evaluated
209+ if ( this . ruleStack . length > 0 && this . ruleStack [ 0 ] . variable ) {
210+ this . vars [ this . ruleStack [ 0 ] . name . substr ( 1 ) ] . updateAfterEval = true ;
211+ }
194212 return node ;
195213 }
196214
0 commit comments