import type * as postcss from 'postcss' ; import type { ProviderPosition } from '../completion-providers' ; export function isInNode ( position , node , includeSelector = false ) { const nodeStart = node . source ?. start ; const nodeEnd = node . source ?. end ; if ( ! node . source ) { return false ; } if ( ! nodeStart ) { return false ; } if ( nodeStart . line > position . line ) { return false ; } if ( nodeStart . line === position . line && nodeStart . column > position . character ) { return false ; } if ( ! nodeEnd ) { return ( ! isBeforeRuleset ( position , node ) || ( ! ! ( node as postcss . Container ) . nodes && ! ! ( ( node as postcss . Container ) . nodes . length > 0 ) ) ) ; } if ( nodeEnd . line < position . line ) { return false ; } if ( nodeEnd . line === position . line && nodeEnd . column < position . character ) { return false ; } if ( isBeforeRuleset ( position , node ) && ! includeSelector ) { return false ; } if ( isAfterRuleset ( position , node ) ) { return false ; } return true ; } export function isBeforeRuleset ( position , node ) { const part = node . source ! . input . css . split ( '\n' ) . slice ( node . source ! . start ! . line - 1 , node . source ! . end ? node . source ! . end . line : undefined ) ; if ( part . findIndex ( ( s ) => s . includes ( '{' ) ) + node . source ! . start ! . line > position . line ) { return true ; } if ( part [ position . line - node . source ! . start ! . line ] . indexOf ( '{' ) >= position . character ) { return true ; } return false ; } export function isAfterRuleset ( position , node ) { const part = node . source ! . input . css . split ( '\n' ) . slice ( node . source ! . start ! . line - 1 , node . source ! . end ! . line ) ; if ( part . findIndex ( ( s ) => s . includes ( '}' ) ) + node . source ! . start ! . line < position . line ) { return true ; } if ( part [ position . line - node . source ! . start ! . line ] . includes ( '}' ) && part [ position . line - node . source ! . start ! . line ] . indexOf ( '}' ) < position . character ) { return true ; } return false ; } const { hasOwnProperty } = Object . prototype ; export function isContainer ( node ) { return hasOwnProperty . call ( node , 'nodes' ) ; } export function isSelector ( node ) { return hasOwnProperty . call ( node , 'selector' ) ; } export function isVars ( node ) { return hasOwnProperty . call ( node , 'selector' ) && ( node as postcss . Rule ) . selector === ':vars' ; } export function isDeclaration ( node ) { return hasOwnProperty . call ( node , 'prop' ) ; } export function isComment ( node ) { return hasOwnProperty . call ( node , 'type' ) && ( node as postcss . Comment ) . type === 'comment' ; } export function isRoot ( node ) { return hasOwnProperty . call ( node , 'type' ) && ( node as postcss . Root ) . type === 'root' ; } export function pathFromPosition ( ast , position , res = [ ] , includeSelector = false ) { res . push ( ast ) ; if ( isContainer ( ast ) && ast . nodes ) { const childNode = ast . nodes . find ( ( node ) => { return isInNode ( position , node , includeSelector ) ; } ) ; if ( childNode ) { return pathFromPosition ( childNode , position , res , includeSelector ) ; } } return res ; } export function getAtRuleByPosition ( ast , position , atRuleName ) { let res ; ast . walkAtRules ( atRuleName , ( atRule ) => { const nodeStart = atRule . source ?. start ; const sLine = nodeStart ! . line - 1 ; const sChar = nodeStart ! . column - 1 ; const nodeEnd = atRule . source ?. end ; const eLine = nodeEnd ! . line - 1 ; const eChar = nodeEnd ! . column - 1 ; if ( ( position . line === sLine && position . character >= sChar && position . line === eLine && position . character <= eChar ) || ( position . line > sLine && position . line < eLine ) ) { res = atRule ; return false ; } return undefined ; } ) ; return res ; } export function getPositionInSrc ( src , position ) { const lines = src . split ( '\n' ) ; return ( lines . slice ( 0 , position . line ) . reduce ( ( total , line ) => line . length + total + 1 , - 1 ) + position . character ) ; }