@@ -57,8 +57,16 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
5757 // Map of variable names to a list of declarations
5858 let map = { } ;
5959
60+
6061 // 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 ) {
6270 const variableEntry = opts . variables [ variableKey ] ;
6371 // Automatically prefix any variable with `--` (CSS custom property syntax) if it doesn't have it already
6472 const variableName = variableKey . slice ( 0 , 2 ) === '--' ? variableKey : '--' + variableKey ;
@@ -70,14 +78,19 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
7078 name : variableName ,
7179 value : variableValue ,
7280 isImportant,
73- selectorBranches : [ ':root' ]
81+ selectorBranches : generateSelectorBranchesFromPostcssNode ( rootNode )
7482 } ) ;
83+
84+ if ( opts . preserve && opts . preserveInjectedVariables ) {
85+ const variableDecl = postcss . decl ( { prop : variableName , value : variableValue } ) ;
86+ rootNode . append ( variableDecl ) ;
87+ }
7588 } ) ;
7689
7790
7891
7992
80- // Collect all of the variables defined
93+ // Collect all of the variables defined `--foo: #f00;`
8194 // ---------------------------------------------------------
8295 // ---------------------------------------------------------
8396 eachCssVariableDeclaration ( css , function ( variableDecl ) {
@@ -105,8 +118,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
105118 // .foo { --color: #f00; color: var(--color); }
106119 // .foo:hover { --color: #0f0; };
107120 // 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) ; }
110123 // --------------------------------
111124 css . walkDecls ( function ( usageDecl ) {
112125 // Avoid duplicating the usage decl on itself
@@ -120,8 +133,10 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
120133 return usageSelectorBranches . some ( ( usageSelectorBranch ) => {
121134 // In this case, we look whether the usage is under the scope of the definition
122135 const isUnderScope = isSelectorBranchUnderScope ( usageSelectorBranch , variableSelectorBranch ) ;
136+ //const isUnderScope = isSelectorBranchUnderScope(variableSelectorBranch, usageSelectorBranch, { ignoreConditionals: true });
123137
124138 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())
125140
126141 if ( isUnderScope ) {
127142 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) {
137152 } ) ;
138153
139154
140-
141155 // Remove the variable declaration because they are pretty much useless after we resolve them
142156 if ( ! opts . preserve ) {
143157 variableDecl . remove ( ) ;
@@ -146,6 +160,8 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
146160 else if ( opts . preserve === 'computed' ) {
147161 // TODO: put computed value here
148162 }
163+ // Otherwise just leave them alone
164+ // else {}
149165
150166 // Clean up the rule that declared them if it doesn't have anything left after we potentially remove the variable decl
151167 if ( variableDeclParentRule . nodes . length <= 0 ) {
@@ -160,15 +176,25 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
160176 debug ( '---------------------------------' ) ;
161177
162178
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)`
164190 // ---------------------------------------------------------
165191 // ---------------------------------------------------------
166192 css . walkDecls ( function ( decl ) {
167193 // Avoid any variable decls, `--foo: var(--bar);`, that may have been preserved
168194 if ( ! RE_VAR_PROP . test ( decl . prop ) ) {
169195 const selectorBranches = generateSelectorBranchesFromPostcssNode ( decl . parent ) ;
170196
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 ) => {
172198 debug ( 'usage' , variableName ) ;
173199 const variableEntries = map [ variableName ] || [ ] ;
174200
@@ -204,11 +230,30 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
204230 result . warn ( [ 'variable ' + variableName + ' is undefined and used without a fallback' , { node : decl } ] ) ;
205231 }
206232
233+ // We use 'undefined' value as a string to avoid making other plugins down the line unhappy, see #22
207234 return resultantValue || 'undefined' ;
208235 } ) ;
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+
209249 }
210250 } ) ;
211251
212252
253+
254+ debug ( 'postcss-css-variables completed -' ) ;
255+ debug ( css . toString ( ) ) ;
256+ debug ( '---------------------------------' ) ;
257+
213258 } ;
214259} ) ;
0 commit comments