import { walk } from 'estree-walker' ; import { Position , SelectionRange } from 'vscode-languageserver' ; import { isInTag , mapSelectionRangeToParent , offsetAt , toRange } from '../../../lib/documents' ; import { SvelteDocument } from '../SvelteDocument' ; type Node = any ; type OffsetRange = { start : number ; end : number ; } ; export async function getSelectionRange ( svelteDoc , position ) { const { script , style , moduleScript } = svelteDoc ; const { ast : { html } } = await svelteDoc . getCompiled ( ) ; const transpiled = await svelteDoc . getTranspiled ( ) ; const content = transpiled . getText ( ) ; const offset = offsetAt ( transpiled . getGeneratedPosition ( position ) , content ) ; const embedded = [ script , style , moduleScript ] ; for ( const info of embedded ) { if ( isInTag ( position , info ) ) { return null ; } } let nearest = html ; let result ; walk ( html , { enter ( node , parent ) { if ( ! parent ) { return ; } if ( ! ( 'start' in node && 'end' in node ) ) { this . skip ( ) ; return ; } const { start , end } = node ; const isWithin = start <= offset && end >= offset ; if ( ! isWithin ) { this . skip ( ) ; return ; } if ( nearest === parent ) { nearest = node ; result = createSelectionRange ( node , result ) ; } } } ) ; return result ? mapSelectionRangeToParent ( transpiled , result ) : null ; function createSelectionRange ( node , parent ? ) { const range = toRange ( content , node . start , node . end ) ; return SelectionRange . create ( range , parent ) ; } }