@@ -8,20 +8,25 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
8
8
const importMap = new Map < string , Set < string > > ( )
9
9
10
10
// 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
+ }
14
17
15
18
// Capture all imports
16
19
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
20
25
if ( ! importMap . has ( from ) ) {
21
26
importMap . set ( from , new Set ( ) )
22
27
}
23
28
24
- const processImports = ( imports : string | undefined , _isType : boolean ) => {
29
+ const processImports = ( imports : string | undefined ) => {
25
30
if ( imports ) {
26
31
const types = imports . replace ( / [ { } ] / g, '' ) . split ( ',' ) . map ( ( t ) => {
27
32
const [ name , alias ] = t . split ( ' as ' ) . map ( s => s . trim ( ) )
@@ -33,70 +38,47 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
33
38
}
34
39
}
35
40
36
- processImports ( namedImports1 , ! ! isTypeImport )
37
- processImports ( namedImports2 , ! ! isTypeImport )
41
+ processImports ( namedImports1 )
42
+ processImports ( namedImports2 )
43
+
38
44
if ( defaultImport1 )
39
45
importMap . get ( from ) ! . add ( defaultImport1 )
40
46
if ( defaultImport2 )
41
47
importMap . get ( from ) ! . add ( defaultImport2 )
42
- } )
48
+ }
43
49
44
50
// 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 ( ) } ` : '' } ;`
56
67
}
57
- comment += `${ exportLines [ i ] } \n`
58
- i ++
59
68
}
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 ( ) } ;`
69
72
}
70
73
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`
97
75
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 ] )
100
82
}
101
83
}
102
84
0 commit comments