import { AtRule , Declaration , Root } from "postcss" ; import postcssValueParser , { WordNode } from "postcss-value-parser" ; import { kaizenVariableUsedNextToOperatorMessage , negatedKaizenVariableMessage , tokenNotInterpolatedInCalcMessage , } from "../messages" ; import { isOperator } from "../util/patterns" ; import { Options , RuleDefinition } from "../types" ; import { isVariable , parseVariable , stringifyVariable , } from "../util/variableUtils" ; import { walkDeclsWithKaizenTokens , walkWithParent } from "../util/walkers" ; const noInvalidEquations = ( postcssNode , parsedValue , options ) => { const parsed = parsedValue ; let amended ; let lastTwoWordNodesNextToEachOther = [ ] ; walkWithParent ( parsed , ( node , parent ) => { if ( node . type === "function" || node . type === "div" ) { lastTwoWordNodesNextToEachOther = [ ] ; return ; } const isWithinCalcFunction = parent ?. value === "calc" ; if ( node . type === "word" ) { const parsedVariable = parseVariable ( node ) ; if ( parsedVariable ?. negated && parsedVariable ?. kaizenToken && parsedVariable ?. kaizenToken . cssVariable ) { if ( options . language === "scss" && options . fix && ! isVariable ( postcssNode ) ) { const fixedVariable = `${ isWithinCalcFunction ? "" : "calc" }(-1 * ${ stringifyVariable ( { ... parsedVariable , interpolated : true , negated : false , } ) })` ; node . value = fixedVariable ; amended = postcssValueParser . stringify ( parsed . nodes ) ; } else { options . reporter ( { message : negatedKaizenVariableMessage , node : postcssNode , autofixAvailable : ! isVariable ( postcssNode ) && options . language === "scss" , } ) ; } return false ; } lastTwoWordNodesNextToEachOther . unshift ( node ) ; if ( lastTwoWordNodesNextToEachOther . length === 3 ) { lastTwoWordNodesNextToEachOther . pop ( ) ; } if ( lastTwoWordNodesNextToEachOther . length === 2 ) { const parsedVariable0 = parseVariable ( lastTwoWordNodesNextToEachOther [ 0 ] ) ; const parsedVariable1 = parseVariable ( lastTwoWordNodesNextToEachOther [ 1 ] ) ; if ( ( isOperator ( lastTwoWordNodesNextToEachOther [ 0 ] . value ) && parsedVariable1 ?. kaizenToken && parsedVariable1 ?. kaizenToken ?. cssVariable ) || ( isOperator ( lastTwoWordNodesNextToEachOther [ 1 ] . value ) && parsedVariable0 ?. kaizenToken && parsedVariable0 ?. kaizenToken ?. cssVariable ) ) { const variableInEquation = parsedVariable0 || parsedVariable1 ; if ( isWithinCalcFunction ) { if ( variableInEquation ?. interpolated ) { return false ; } if ( options . language === "scss" && options . fix && ! isVariable ( postcssNode ) ) { if ( variableInEquation ?. kaizenToken ) { variableInEquation . node . value = stringifyVariable ( { ... variableInEquation , interpolated : true , } ) ; } amended = postcssValueParser . stringify ( parsed . nodes ) ; } else { options . reporter ( { message : tokenNotInterpolatedInCalcMessage , node : postcssNode , autofixAvailable : ! isVariable ( postcssNode ) , } ) ; } } else { options . reporter ( { message : kaizenVariableUsedNextToOperatorMessage , node : postcssNode , autofixAvailable : false , } ) ; } return false ; } } } } ) ; if ( options . fix && amended && ! isVariable ( postcssNode ) ) { postcssNode . replaceWith ( postcssNode . clone ( { value : amended , } ) ) ; } } ; export const noInvalidUseOfVarTokensInEquations = { name : "no-invalid-use-of-var-tokens-in-equations" , ruleFunction : ( stylesheetNode , options ) => { walkDeclsWithKaizenTokens ( stylesheetNode , ( { postcssNode , parsedValue } ) => { noInvalidEquations ( postcssNode , parsedValue , options ) ; } ) ; } , } ; /**
 * Check if a declaration contains an equation that we cannot support with CSS Variables.
 * This is exported so other rules can avoid transforming tokens to CSS Variables versions when they are used in unsupported functions.
 **/ export const containsEquationThatDoesntWorkWithCSSVariables = ( postcssNode , parsedValue , options ) => { let reported = 0 ; noInvalidEquations ( postcssNode . clone ( ) , parsedValue , { ... options , fix : true , reporter : ( ) => { reported ++ ; } , } ) ; return reported > 0 ; } ;