1+ import { normalizePath } from "vite" ;
2+ import { gen , parse , t , trav } from "./babel" ;
3+ import type { types as Babel } from "@babel/core"
4+ import type { ParseResult } from "@babel/parser"
5+
6+
7+ const transform = ( ast : ParseResult < Babel . File > , file : string ) => {
8+ let didTransform = false ;
9+ trav ( ast , {
10+ JSXOpeningElement ( path , ) {
11+ const loc = path . node . loc ;
12+ if ( ! loc ) return ;
13+ const line = loc . start . line ;
14+ const column = loc . start . column ;
15+
16+ // Inject data-source as a string: "<file>:<line>:<column>"
17+ path . node . attributes . push (
18+ t . jsxAttribute (
19+ t . jsxIdentifier ( 'data-source' ) ,
20+ t . stringLiteral ( `${ file } :${ line } :${ column } ` )
21+ )
22+ ) ;
23+
24+ didTransform = true ;
25+ }
26+ } )
27+
28+ return didTransform
29+ }
30+
31+
32+ export function addSourceToJsx ( code : string , id : string ) {
33+ const [ filePath ] = id . split ( "?" )
34+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
35+ const location = filePath ?. replace ( normalizePath ( process . cwd ( ) ) , '' ) !
36+
37+ try {
38+ const ast = parse ( code , { sourceType : "module" , plugins : [ "jsx" , "typescript" ] } ) ;
39+ const didTransform = transform ( ast , location )
40+ if ( ! didTransform ) {
41+ return { code }
42+ }
43+ return gen ( ast , { sourceMaps : true , filename : id , sourceFileName : filePath } )
44+ } catch ( e ) {
45+
46+ return { code }
47+ }
48+ }
0 commit comments