@@ -11,12 +11,13 @@ const CSSVariablesCollectorPlugin = module.exports = function(config) {
11
11
this . ruleStack = [ ] ;
12
12
this . mixinStack = [ ] ;
13
13
this . parenStack = [ ] ;
14
- this . importStack = [ ] ;
15
14
} ;
16
15
17
16
CSSVariablesCollectorPlugin . prototype = {
18
17
18
+ // needed to keep the less variable references intact to use this info for the CSS variables references
19
19
isPreEvalVisitor : true ,
20
+
20
21
isReplacing : true ,
21
22
22
23
_isInMixinOrParen ( ) {
@@ -27,27 +28,44 @@ CSSVariablesCollectorPlugin.prototype = {
27
28
return this . ruleStack . length > 0 && ! this . ruleStack [ this . ruleStack . length - 1 ] . variable ;
28
29
} ,
29
30
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 ;
34
39
} ,
35
40
36
41
_isRelevant ( ) {
37
42
return ! this . _isInMixinOrParen ( ) && this . _isVarInRule ( ) ;
38
43
} ,
39
44
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
+ } ) ;
41
59
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" ;
44
62
} ) ;
45
63
Object . keys ( this . calcVars ) . forEach ( ( value , index ) => {
46
64
lessVariables += "@" + value + ": " + this . calcVars [ value ] . css + ";\n" ;
47
65
} ) ;
48
66
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 ) {
51
69
lessVariables += "--" + value + ": @" + value + ";\n" ;
52
70
}
53
71
} ) ;
@@ -89,15 +107,17 @@ CSSVariablesCollectorPlugin.prototype = {
89
107
90
108
visitOperation ( node , visitArgs ) {
91
109
if ( this . _isRelevant ( ) ) {
110
+ // console.log("visitOperation", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
92
111
return new less . tree . Call ( "calc" , [ new less . tree . Expression ( [ node . operands [ 0 ] , new less . tree . Anonymous ( node . op ) , node . operands [ 1 ] ] ) ] ) ;
93
112
}
94
113
return node ;
95
114
} ,
96
115
97
116
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!
99
118
const isRelevantFunction = typeof less . tree . functions [ node . name ] === "function" && [ "rgba" ] . indexOf ( node . name ) === - 1 ;
100
119
if ( this . _isRelevant ( ) && isRelevantFunction ) {
120
+ // console.log("visitCall", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
101
121
const css = this . _getCSS ( node ) ;
102
122
let newName = this . config . prefix + "function_" + node . name + Object . keys ( this . vars ) . length ;
103
123
// check for duplicate value in vars already
@@ -109,7 +129,7 @@ CSSVariablesCollectorPlugin.prototype = {
109
129
}
110
130
this . calcVars [ newName ] = {
111
131
css : css ,
112
- export : ! this . _isInGlobalOrBaseImport ( )
132
+ export : this . _isVarInLibrary ( )
113
133
} ;
114
134
return new less . tree . Call ( "var" , [ new less . tree . Anonymous ( "--" + newName , node . index , node . currentFileInfo , node . mapLines ) ] ) ;
115
135
}
@@ -119,6 +139,7 @@ CSSVariablesCollectorPlugin.prototype = {
119
139
visitNegative ( node , visitArgs ) {
120
140
// convert negative into calc function
121
141
if ( this . _isRelevant ( ) ) {
142
+ // console.log("visitNegative", this.ruleStack[this.ruleStack.length - 1], this._getCSS(node));
122
143
return new less . tree . Call ( "calc" , [ new less . tree . Expression ( [ new less . tree . Anonymous ( "-1" ) , new less . tree . Anonymous ( "*" ) , node . value ] ) ] ) ;
123
144
}
124
145
return node ;
@@ -133,6 +154,19 @@ CSSVariablesCollectorPlugin.prototype = {
133
154
} ,
134
155
135
156
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
+ }
136
170
// store the rule context for the call variable extraction
137
171
this . ruleStack . push ( node ) ;
138
172
return node ;
@@ -168,29 +202,13 @@ CSSVariablesCollectorPlugin.prototype = {
168
202
return node ;
169
203
} ,
170
204
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
+ }
194
212
return node ;
195
213
}
196
214
0 commit comments