@@ -33,6 +33,30 @@ function eachCssVariableDeclaration(css, cb) {
33
33
} ) ;
34
34
}
35
35
36
+ function cloneParentAncestry ( node ) {
37
+ const clone = node . clone ( ) ;
38
+ clone . removeAll ( ) ;
39
+
40
+ if ( node . parent && node . parent . type !== 'root' ) {
41
+ const parentClone = node . parent . clone ( ) ;
42
+ parentClone . removeAll ( ) ;
43
+ parentClone . append ( clone ) ;
44
+
45
+ return cloneParentAncestry ( parentClone ) ;
46
+ }
47
+
48
+ return clone ;
49
+ }
50
+
51
+ function insertNodeIntoAncestry ( ancestry , insertNode ) {
52
+ let deepestNode = ancestry ;
53
+ while ( ! deepestNode . nodes || deepestNode . nodes . length > 0 ) {
54
+ deepestNode = deepestNode . nodes [ 0 ] ;
55
+ }
56
+
57
+ deepestNode . append ( insertNode ) ;
58
+ }
59
+
36
60
37
61
var defaults = {
38
62
// Allows you to preserve custom properties & var() usage in output.
@@ -123,7 +147,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
123
147
// --------------------------------
124
148
css . walkDecls ( function ( usageDecl ) {
125
149
// Avoid duplicating the usage decl on itself
126
- if ( variableDeclParentRule === usageDecl . parent ) {
150
+ // And make sure this decl has `var()` usage
151
+ if ( variableDeclParentRule === usageDecl . parent || ! RE_VAR_FUNC . test ( usageDecl . value ) ) {
127
152
return ;
128
153
}
129
154
@@ -133,10 +158,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
133
158
return usageSelectorBranches . some ( ( usageSelectorBranch ) => {
134
159
// In this case, we look whether the usage is under the scope of the definition
135
160
const isUnderScope = isSelectorBranchUnderScope ( usageSelectorBranch , variableSelectorBranch ) ;
136
- //const isUnderScope = isSelectorBranchUnderScope(variableSelectorBranch, usageSelectorBranch, { ignoreConditionals: true });
137
161
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())
162
+ debug ( `Should unroll decl? isUnderScope=${ isUnderScope } ` , usageSelectorBranch . selector . toString ( ) , '|' , variableSelectorBranch . selector . toString ( ) )
140
163
141
164
if ( isUnderScope ) {
142
165
usageDecl . value . replace ( new RegExp ( RE_VAR_FUNC . source , 'g' ) , ( match , matchedVariableName ) => {
@@ -145,6 +168,36 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
145
168
}
146
169
} ) ;
147
170
}
171
+ else {
172
+ // If there is a conditional like a atrule/media-query, then we should check whether
173
+ // the variable can apply and put our usage within that same context
174
+ // Before:
175
+ // :root { --color: #f00; }
176
+ // @media (max-width: 1000px) { :root { --color: #0f0; } }
177
+ // .box { color: var(--color); }
178
+ // After:
179
+ // .box { color: #f00; }
180
+ // @media (max-width: 1000px) {.box { color: #0f0; } }
181
+ const hasAtRule = ( variableSelectorBranch . conditionals || [ ] ) . some ( ( conditional ) => {
182
+ return conditional . type === 'atrule' ;
183
+ } )
184
+ if ( hasAtRule ) {
185
+ const doesVariableApplyToUsage = isSelectorBranchUnderScope ( variableSelectorBranch , usageSelectorBranch , { ignoreConditionals : true } ) ;
186
+ debug ( `Should expand usage? doesVariableApplyToUsage=${ doesVariableApplyToUsage } ` , variableSelectorBranch . selector . toString ( ) , '|' , usageSelectorBranch . selector . toString ( ) )
187
+
188
+ // Create a new usage clone with only the usage decl
189
+ const newUsageRule = usageDecl . parent . clone ( ) ;
190
+ newUsageRule . removeAll ( ) ;
191
+ newUsageRule . append ( usageDecl . clone ( ) ) ;
192
+
193
+ const variableAncestry = cloneParentAncestry ( variableDecl . parent . parent ) ;
194
+ insertNodeIntoAncestry ( variableAncestry , newUsageRule ) ;
195
+
196
+ usageDecl . parent . cloneBefore ( ) ;
197
+ usageDecl . parent . replaceWith ( variableAncestry ) ;
198
+ }
199
+ }
200
+
148
201
149
202
return isUnderScope ;
150
203
} ) ;
@@ -164,8 +217,11 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
164
217
// else {}
165
218
166
219
// Clean up the rule that declared them if it doesn't have anything left after we potentially remove the variable decl
167
- if ( variableDeclParentRule . nodes . length <= 0 ) {
168
- variableDeclParentRule . remove ( ) ;
220
+ let currentNodeToCheckEmpty = variableDeclParentRule ;
221
+ while ( currentNodeToCheckEmpty . nodes . length === 0 ) {
222
+ const nodeToRemove = currentNodeToCheckEmpty ;
223
+ currentNodeToCheckEmpty = nodeToRemove . parent ;
224
+ nodeToRemove . remove ( ) ;
169
225
}
170
226
} ) ;
171
227
0 commit comments