@@ -2,6 +2,7 @@ const postcss = require('postcss');
22
33const THEME_VAR_PREFIX = 'theme-var' ;
44const VAR_REGEX = / v a r \( ( - - .+ ?) \) / ;
5+ const VAR_NAME_REGEX = / v a r \( ( - - .+ ?) \) / ;
56
67module . exports . extractThemeRulesPlugin = postcss . plugin ( 'postcss-extract-theme-rules' , ( options = { } ) => {
78 const prefix = options . prefix || THEME_VAR_PREFIX ;
@@ -25,6 +26,36 @@ module.exports.extractThemeRulesPlugin = postcss.plugin('postcss-extract-theme-r
2526 } ;
2627} ) ;
2728
29+ const flattenValue = ( variables , name , recursiveSeenMap = { } ) => {
30+ let value = variables [ name ] ;
31+
32+ // Check for circular dependency
33+ if ( recursiveSeenMap . hasOwnProperty ( name ) ) {
34+ throw new Error ( `Found circular dependency in CSS theme variables for '${ name } '` ) ;
35+ } else {
36+ recursiveSeenMap [ name ] = true ;
37+ }
38+
39+ // Replace recursive variables in left-to-right order
40+ while ( value && value . indexOf ( 'var(--' ) > - 1 ) {
41+ const varName = VAR_NAME_REGEX . exec ( value ) [ 1 ] ;
42+ const varValue = flattenValue ( variables , varName , recursiveSeenMap ) ;
43+
44+ // Overwrite value to prevent duplicate work
45+ variables [ name ] = value = value . replace ( VAR_REGEX , varValue ) ;
46+ }
47+
48+ return value ;
49+ } ;
50+
51+ const flattenRecursiveValues = ( variables ) => {
52+ for ( const key in variables ) {
53+ flattenValue ( variables , key ) ;
54+ }
55+
56+ return variables ;
57+ } ;
58+
2859module . exports . extractVariablesPlugin = postcss . plugin ( 'postcss-extract-variables' , ( ) => {
2960 return ( root , results ) => {
3061 let vars = { } ;
@@ -39,51 +70,30 @@ module.exports.extractVariablesPlugin = postcss.plugin('postcss-extract-variable
3970 } ) ;
4071 } ) ;
4172
42- results . variables = vars ;
73+ results . variables = flattenRecursiveValues ( vars ) ;
4374 } ;
4475} ) ;
4576
46- const getVariableValue = ( variables , name , recursiveSeenMap = { } ) => {
47- if ( ! variables . hasOwnProperty ( name ) ) {
48- return [ `Missing value for variable '${ name } '` ] ;
49- }
50-
51- // Circular dependency check
52- if ( recursiveSeenMap . hasOwnProperty ( name ) ) {
53- return [ `Found circular dependency in CSS theme variables for '${ name } '` ] ;
54- }
55-
56- let value = variables [ name ] ;
57-
58- // value is a variable, recursively lookup value
59- if ( value . indexOf ( 'var(--' ) === 0 ) {
60- value = VAR_REGEX . exec ( value ) [ 1 ] ;
61- recursiveSeenMap [ name ] = true ;
62-
63- return getVariableValue ( variables , value , recursiveSeenMap ) ;
64- }
65-
66- return [ null , value ] ;
67- } ;
68-
6977module . exports . replaceThemeVars = postcss . plugin ( 'postcss-replace-theme-vars' , ( options = { } ) => {
70- const regex = new RegExp ( THEME_VAR_PREFIX + '\\((.+?)\\)' ) ;
7178 const variables = options . variables ;
7279
80+ const varNameRegex = new RegExp ( THEME_VAR_PREFIX + '\\((.+?)\\)' ) ;
81+ const varRegex = new RegExp ( THEME_VAR_PREFIX + '\\(.+?\\)' ) ;
82+
7383 return ( root ) => {
7484 root . walkDecls ( decl => {
75- const match = regex . exec ( decl . value ) ;
76- if ( ! match ) return ;
77-
78- const varName = match [ 1 ] ;
79- const [ err , value ] = getVariableValue ( variables , varName ) ;
80-
81- if ( err ) {
82- console . error ( err ) ;
83- return ;
85+ // Replace all theme vars in decl value
86+ let match ;
87+ while ( match = varNameRegex . exec ( decl . value ) ) {
88+ const varName = match [ 1 ] ;
89+ const varValue = variables [ varName ] ;
90+
91+ if ( varValue ) {
92+ decl . value = decl . value . replace ( varRegex , varValue ) ;
93+ } else {
94+ console . error ( `Missing theming variable '${ varName } '` ) ;
95+ }
8496 }
85-
86- decl . value = value ;
8797 } ) ;
8898 } ;
8999} ) ;
0 commit comments