@@ -57,8 +57,16 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
57
57
// Map of variable names to a list of declarations
58
58
let map = { } ;
59
59
60
+
60
61
// Add the js defined variables `opts.variables` to the map
61
- Object . keys ( opts . variables ) . forEach ( function ( prevVariableMap , variableKey ) {
62
+ // ---------------------------------------------------------
63
+ // ---------------------------------------------------------
64
+ const rootNode = postcss . rule ( { selector : ':root' } ) ;
65
+ if ( opts . variables && Object . keys ( opts . variables ) . length > 0 && opts . preserve && opts . preserveInjectedVariables ) {
66
+ css . prepend ( rootNode ) ;
67
+ }
68
+
69
+ Object . keys ( opts . variables ) . forEach ( function ( variableKey ) {
62
70
const variableEntry = opts . variables [ variableKey ] ;
63
71
// Automatically prefix any variable with `--` (CSS custom property syntax) if it doesn't have it already
64
72
const variableName = variableKey . slice ( 0 , 2 ) === '--' ? variableKey : '--' + variableKey ;
@@ -70,14 +78,19 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
70
78
name : variableName ,
71
79
value : variableValue ,
72
80
isImportant,
73
- selectorBranches : [ ':root' ]
81
+ selectorBranches : generateSelectorBranchesFromPostcssNode ( rootNode )
74
82
} ) ;
83
+
84
+ if ( opts . preserve && opts . preserveInjectedVariables ) {
85
+ const variableDecl = postcss . decl ( { prop : variableName , value : variableValue } ) ;
86
+ rootNode . append ( variableDecl ) ;
87
+ }
75
88
} ) ;
76
89
77
90
78
91
79
92
80
- // Collect all of the variables defined
93
+ // Collect all of the variables defined `--foo: #f00;`
81
94
// ---------------------------------------------------------
82
95
// ---------------------------------------------------------
83
96
eachCssVariableDeclaration ( css , function ( variableDecl ) {
@@ -105,8 +118,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
105
118
// .foo { --color: #f00; color: var(--color); }
106
119
// .foo:hover { --color: #0f0; };
107
120
// After:
108
- // .foo { color: #f00; }
109
- // .foo:hover { color: #0f0; }
121
+ // .foo { -- color: #f00; color: var(--color) ; }
122
+ // .foo:hover { -- color: #0f0; color: var(--color) ; }
110
123
// --------------------------------
111
124
css . walkDecls ( function ( usageDecl ) {
112
125
// Avoid duplicating the usage decl on itself
@@ -120,8 +133,10 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
120
133
return usageSelectorBranches . some ( ( usageSelectorBranch ) => {
121
134
// In this case, we look whether the usage is under the scope of the definition
122
135
const isUnderScope = isSelectorBranchUnderScope ( usageSelectorBranch , variableSelectorBranch ) ;
136
+ //const isUnderScope = isSelectorBranchUnderScope(variableSelectorBranch, usageSelectorBranch, { ignoreConditionals: true });
123
137
124
138
debug ( `Should expand usage? isUnderScope=${ isUnderScope } ` , usageSelectorBranch . selector . toString ( ) , '|' , variableSelectorBranch . selector . toString ( ) )
139
+ //debug(`Should expand usage? isUnderScope=${isUnderScope}`, variableSelectorBranch.selector.toString(), '|', usageSelectorBranch.selector.toString())
125
140
126
141
if ( isUnderScope ) {
127
142
usageDecl . value . replace ( new RegExp ( RE_VAR_FUNC . source , 'g' ) , ( match , matchedVariableName ) => {
@@ -137,7 +152,6 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
137
152
} ) ;
138
153
139
154
140
-
141
155
// Remove the variable declaration because they are pretty much useless after we resolve them
142
156
if ( ! opts . preserve ) {
143
157
variableDecl . remove ( ) ;
@@ -146,6 +160,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
146
160
else if ( opts . preserve === 'computed' ) {
147
161
// TODO: put computed value here
148
162
}
163
+ // Otherwise just leave them alone
164
+ // else {}
149
165
150
166
// Clean up the rule that declared them if it doesn't have anything left after we potentially remove the variable decl
151
167
if ( variableDeclParentRule . nodes . length <= 0 ) {
@@ -160,15 +176,25 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
160
176
debug ( '---------------------------------' ) ;
161
177
162
178
163
- // Resolve variables everywhere
179
+
180
+
181
+ // Resolve variable values
182
+ // ---------------------------------------------------------
183
+ // ---------------------------------------------------------
184
+ // TODO
185
+
186
+
187
+
188
+
189
+ // Resolve variable usage everywhere `var(--foo)`
164
190
// ---------------------------------------------------------
165
191
// ---------------------------------------------------------
166
192
css . walkDecls ( function ( decl ) {
167
193
// Avoid any variable decls, `--foo: var(--bar);`, that may have been preserved
168
194
if ( ! RE_VAR_PROP . test ( decl . prop ) ) {
169
195
const selectorBranches = generateSelectorBranchesFromPostcssNode ( decl . parent ) ;
170
196
171
- decl . value = decl . value . replace ( new RegExp ( RE_VAR_FUNC . source , 'g' ) , ( match , variableName , fallback ) => {
197
+ const newDeclValue = decl . value . replace ( new RegExp ( RE_VAR_FUNC . source , 'g' ) , ( match , variableName , fallback ) => {
172
198
debug ( 'usage' , variableName ) ;
173
199
const variableEntries = map [ variableName ] || [ ] ;
174
200
@@ -204,11 +230,30 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
204
230
result . warn ( [ 'variable ' + variableName + ' is undefined and used without a fallback' , { node : decl } ] ) ;
205
231
}
206
232
233
+ // We use 'undefined' value as a string to avoid making other plugins down the line unhappy, see #22
207
234
return resultantValue || 'undefined' ;
208
235
} ) ;
236
+
237
+
238
+ if ( newDeclValue !== decl . value ) {
239
+ let potentialClone = decl ;
240
+ if ( opts . preserve === true ) {
241
+ potentialClone = decl . cloneBefore ( ) ;
242
+ }
243
+
244
+ // We `cloneBefore` and put the value on the clone so that
245
+ // `walkDecl` doesn't try to iterate on the new decl
246
+ potentialClone . value = newDeclValue ;
247
+ }
248
+
209
249
}
210
250
} ) ;
211
251
212
252
253
+
254
+ debug ( 'postcss-css-variables completed -' ) ;
255
+ debug ( css . toString ( ) ) ;
256
+ debug ( '---------------------------------' ) ;
257
+
213
258
} ;
214
259
} ) ;
0 commit comments