@@ -10,6 +10,11 @@ import parser from 'postcss-values-parser';
1010export default function transformAST ( node , opts ) {
1111 node . nodes . slice ( 0 ) . forEach ( child => {
1212 if ( isColorModFunction ( child ) ) {
13+ // transform any variables within the color-mod() function
14+ if ( opts . transformVars ) {
15+ transformVariables ( child , opts ) ;
16+ }
17+
1318 // transform any color-mod() functions
1419 const color = transformColorModFunction ( child , opts ) ;
1520
@@ -27,6 +32,50 @@ export default function transformAST(node, opts) {
2732 } ) ;
2833}
2934
35+ /* Transform <var> functions
36+ /* ========================================================================== */
37+
38+ function transformVariables ( node , opts ) {
39+ node . walk (
40+ child => {
41+ if ( isVariable ( child ) ) {
42+ const [ variableName , fallbackNode ] = transformArgsByParams ( child , [
43+ // <value> , [ <fallback> ]?
44+ [ transformWord , isComma , transformNode ]
45+ ] ) ;
46+
47+ if ( variableName ) {
48+ let variableNode ;
49+
50+ opts . result . root . walkRules ( ':root' , rule => {
51+ rule . nodes . filter (
52+ rootChild => rootChild . prop === variableName
53+ ) . slice ( - 1 ) . forEach (
54+ rootChild => {
55+ const rootChildValue = rootChild . value ;
56+
57+ const rootChildAST = parser ( rootChildValue , { loose : true } ) . parse ( ) ;
58+
59+ transformVariables ( rootChildAST , opts ) ;
60+
61+ variableNode = rootChildAST . nodes [ 0 ] ;
62+ }
63+ ) ;
64+ } ) ;
65+
66+ if ( variableNode ) {
67+ child . replaceWith ( ...variableNode . nodes ) ;
68+ }
69+ } else if ( fallbackNode ) {
70+ transformVariables ( fallbackNode , opts ) ;
71+
72+ child . replaceWith ( ...fallbackNode . nodes [ 0 ] . nodes ) ;
73+ }
74+ }
75+ }
76+ ) ;
77+ }
78+
3079/* Transform <color> functions
3180/* ========================================================================== */
3281
@@ -501,6 +550,21 @@ function transformMinusPlusTimesOperator(node, opts) {
501550 }
502551}
503552
553+ /* Additional transforms
554+ /* ========================================================================== */
555+
556+ function transformWord ( node , opts ) {
557+ if ( isWord ( node ) ) {
558+ return node . value ;
559+ } else {
560+ return manageUnresolved ( node , opts , node . value , `Expected a valid word` ) ;
561+ }
562+ }
563+
564+ function transformNode ( node ) {
565+ return Object ( node ) ;
566+ }
567+
504568/* Transform helper
505569/* ========================================================================== */
506570
@@ -516,6 +580,15 @@ function transformArgsByParams(node, params) {
516580 ) ) [ 0 ] || [ ] ;
517581}
518582
583+ /* Variable validators
584+ /* ========================================================================== */
585+
586+ // return whether the node is a var function
587+ function isVariable ( node ) {
588+ // var()
589+ return Object ( node ) . type === 'func' && varMatch . test ( node . value ) ;
590+ }
591+
519592/* Adjustment validators
520593/* ========================================================================== */
521594
@@ -647,6 +720,12 @@ function isPercentage(node) {
647720 return Object ( node ) . type === 'number' && ( node . unit === '%' || node . value === '0' ) ;
648721}
649722
723+ // return whether the node is a word
724+ function isWord ( node ) {
725+ // <word>
726+ return Object ( node ) . type === 'word' ;
727+ }
728+
650729/* Matchers
651730/* ========================================================================== */
652731
@@ -667,4 +746,5 @@ const minusPlusTimesMatch = /^[*+-]$/;
667746const rgbMatch = / ^ r g b $ / i;
668747const rgbaMatch = / ^ r g b a ? $ / i;
669748const shadeTintMatch = / ^ ( s h a d e | t i n t ) $ / i;
749+ const varMatch = / ^ v a r $ / i;
670750const timesMatch = / ^ [ * ] $ / ;
0 commit comments