@@ -8,20 +8,25 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
88 const importMap = new Map < string , Set < string > > ( )
99
1010 // Handle re-exports
11- const reExportRegex = / e x p o r t \s * (?: \* | \{ [ ^ } ] * \} ) \s * f r o m \s * [ ' " ] [ ^ ' " ] + [ ' " ] / g
12- const reExports = fileContent . match ( reExportRegex ) || [ ]
13- declarations += `${ reExports . join ( '\n' ) } \n`
11+ const reExportRegex = / e x p o r t \s * (?: \* | \{ [ ^ } ] * \} ) \s * f r o m \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
12+ let reExportMatch
13+
14+ while ( ( reExportMatch = reExportRegex . exec ( fileContent ) ) !== null ) {
15+ declarations += `${ reExportMatch [ 0 ] } \n`
16+ }
1417
1518 // Capture all imports
1619 const importRegex = / i m p o r t \s + (?: ( t y p e ) \s + ) ? (?: ( \{ [ ^ } ] + \} ) | ( \w + ) ) (?: \s * , \s * (?: ( \{ [ ^ } ] + \} ) | ( \w + ) ) ) ? \s + f r o m \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
17- const imports = Array . from ( fileContent . matchAll ( importRegex ) )
18-
19- imports . forEach ( ( [ , isTypeImport , namedImports1 , defaultImport1 , namedImports2 , defaultImport2 , from ] ) => {
20+ let importMatch
21+ // eslint-disable-next-line no-cond-assign
22+ while ( ( importMatch = importRegex . exec ( fileContent ) ) !== null ) {
23+ // eslint-disable-next-line unused-imports/no-unused-vars
24+ const [ , isTypeImport , namedImports1 , defaultImport1 , namedImports2 , defaultImport2 , from ] = importMatch
2025 if ( ! importMap . has ( from ) ) {
2126 importMap . set ( from , new Set ( ) )
2227 }
2328
24- const processImports = ( imports : string | undefined , _isType : boolean ) => {
29+ const processImports = ( imports : string | undefined ) => {
2530 if ( imports ) {
2631 const types = imports . replace ( / [ { } ] / g, '' ) . split ( ',' ) . map ( ( t ) => {
2732 const [ name , alias ] = t . split ( ' as ' ) . map ( s => s . trim ( ) )
@@ -33,70 +38,47 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
3338 }
3439 }
3540
36- processImports ( namedImports1 , ! ! isTypeImport )
37- processImports ( namedImports2 , ! ! isTypeImport )
41+ processImports ( namedImports1 )
42+ processImports ( namedImports2 )
43+
3844 if ( defaultImport1 )
3945 importMap . get ( from ) ! . add ( defaultImport1 )
4046 if ( defaultImport2 )
4147 importMap . get ( from ) ! . add ( defaultImport2 )
42- } )
48+ }
4349
4450 // Handle exports with comments
45- const exportLines = fileContent . split ( '\n' )
46- let i = 0
47- while ( i < exportLines . length ) {
48- let comment = ''
49- let exportStatement = ''
50-
51- // Collect comment
52- if ( exportLines [ i ] . trim ( ) . startsWith ( '/**' ) ) {
53- while ( i < exportLines . length && ! exportLines [ i ] . includes ( '*/' ) ) {
54- comment += `${ exportLines [ i ] } \n`
55- i ++
51+ const exportRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( e x p o r t \s + (?: a s y n c \s + ) ? (?: f u n c t i o n | c o n s t | l e t | v a r | c l a s s | i n t e r f a c e | t y p e ) \s + \w [ \s \S ] * ?) (? = \n \s * (?: \/ \* \* | e x p o r t | $ ) ) / g
52+ let match
53+ // eslint-disable-next-line no-cond-assign
54+ while ( ( match = exportRegex . exec ( fileContent ) ) !== null ) {
55+ const [ , comment , exportStatement ] = match
56+ const formattedComment = comment ? formatComment ( comment . trim ( ) ) : ''
57+ let formattedExport = exportStatement . trim ( )
58+
59+ if ( formattedExport . startsWith ( 'export function' ) || formattedExport . startsWith ( 'export async function' ) ) {
60+ formattedExport = formattedExport . replace ( / ^ e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n / , 'export declare function' )
61+ const functionSignature = formattedExport . match ( / ^ .* ?\) / )
62+ if ( functionSignature ) {
63+ let params = functionSignature [ 0 ] . slice ( functionSignature [ 0 ] . indexOf ( '(' ) + 1 , - 1 )
64+ params = params . replace ( / \s * = [ ^ , ) ] + / g, '' ) // Remove default values
65+ const returnType = formattedExport . match ( / \) : \s * ( [ ^ { ] + ) / )
66+ formattedExport = `export declare function ${ formattedExport . split ( 'function' ) [ 1 ] . split ( '(' ) [ 0 ] . trim ( ) } (${ params } )${ returnType ? `: ${ returnType [ 1 ] . trim ( ) } ` : '' } ;`
5667 }
57- comment += `${ exportLines [ i ] } \n`
58- i ++
5968 }
60-
61- // Collect export statement
62- if ( i < exportLines . length && exportLines [ i ] . trim ( ) . startsWith ( 'export' ) ) {
63- exportStatement = exportLines [ i ]
64- i ++
65- while ( i < exportLines . length && ! exportLines [ i ] . trim ( ) . startsWith ( 'export' ) && ! exportLines [ i ] . trim ( ) . startsWith ( '/**' ) ) {
66- exportStatement += `\n${ exportLines [ i ] } `
67- i ++
68- }
69+ else if ( formattedExport . startsWith ( 'export const' ) || formattedExport . startsWith ( 'export let' ) || formattedExport . startsWith ( 'export var' ) ) {
70+ formattedExport = formattedExport . replace ( / ^ e x p o r t \s + ( c o n s t | l e t | v a r ) / , 'export declare $1' )
71+ formattedExport = `${ formattedExport . split ( '=' ) [ 0 ] . trim ( ) } ;`
6972 }
7073
71- if ( exportStatement ) {
72- const formattedComment = comment ? formatComment ( comment . trim ( ) ) : ''
73- let formattedExport = exportStatement . trim ( )
74-
75- if ( formattedExport . startsWith ( 'export function' ) || formattedExport . startsWith ( 'export async function' ) ) {
76- formattedExport = formattedExport . replace ( / ^ e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n / , 'export declare function' )
77- const functionSignature = formattedExport . match ( / ^ .* ?\) / )
78- if ( functionSignature ) {
79- let params = functionSignature [ 0 ] . slice ( functionSignature [ 0 ] . indexOf ( '(' ) + 1 , - 1 )
80- params = params . replace ( / \s * = [ ^ , ) ] + / g, '' ) // Remove default values
81- const returnType = formattedExport . match ( / \) : \s * ( [ ^ { ] + ) / )
82- formattedExport = `export declare function ${ formattedExport . split ( 'function' ) [ 1 ] . split ( '(' ) [ 0 ] . trim ( ) } (${ params } )${ returnType ? `: ${ returnType [ 1 ] . trim ( ) } ` : '' } ;`
83- }
84- }
85- else if ( formattedExport . startsWith ( 'export const' ) || formattedExport . startsWith ( 'export let' ) || formattedExport . startsWith ( 'export var' ) ) {
86- formattedExport = formattedExport . replace ( / ^ e x p o r t \s + ( c o n s t | l e t | v a r ) / , 'export declare $1' )
87- formattedExport = `${ formattedExport . split ( '=' ) [ 0 ] . trim ( ) } ;`
88- }
89-
90- declarations += `${ formattedComment } \n${ formattedExport } \n\n`
91-
92- // Add types used in the export to usedTypes
93- const typeRegex = / \b ( [ A - Z ] \w + ) (?: < [ ^ > ] * > ) ? / g
94- const types = Array . from ( formattedExport . matchAll ( typeRegex ) )
95- types . forEach ( ( [ , type ] ) => usedTypes . add ( type ) )
96- }
74+ declarations += `${ formattedComment } \n${ formattedExport } \n\n`
9775
98- if ( ! exportStatement && ! comment ) {
99- i ++
76+ // Add types used in the export to usedTypes
77+ const typeRegex = / \b ( [ A - Z ] \w + ) (?: < [ ^ > ] * > ) ? / g
78+ let typeMatch
79+ // eslint-disable-next-line no-cond-assign
80+ while ( ( typeMatch = typeRegex . exec ( formattedExport ) ) !== null ) {
81+ usedTypes . add ( typeMatch [ 1 ] )
10082 }
10183 }
10284
0 commit comments