@@ -15,12 +15,30 @@ function isEmpty(obj: any): boolean {
1515
1616type BabelParser = Pick < typeof defaultBabelParser , 'parse' | 'parseExpression' >
1717
18+ function pluginName ( p : ParserPlugin ) : string {
19+ return typeof p === 'string' ? p : p [ 0 ]
20+ }
21+
22+ function pluginOpts ( p : ParserPlugin ) : any {
23+ return typeof p === 'string' ? { } : p [ 1 ]
24+ }
25+
26+ function arePluginsEqual ( a : ParserPlugin , b : ParserPlugin ) : boolean {
27+ return (
28+ pluginName ( a ) === pluginName ( b ) &&
29+ t . shallowEqual ( pluginOpts ( a ) , pluginOpts ( b ) )
30+ )
31+ }
32+
1833function mergePlugins (
1934 a : ParserPlugin [ ] | undefined ,
2035 b : ParserPlugin [ ] | undefined
2136) : ParserPlugin [ ] | undefined {
2237 if ( ! b ) return a
2338 if ( ! a ) return b
39+
40+ if ( b . every ( ( bp ) => a . find ( ( ap ) => arePluginsEqual ( ap , bp ) ) ) ) return a
41+
2442 // eslint-disable-next-line @typescript-eslint/no-explicit-any
2543 const map : Map < string , any > = new Map (
2644 // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -39,6 +57,16 @@ function mergePlugins(
3957 ) as any
4058}
4159
60+ function removePlugins (
61+ a : ParserPlugin [ ] | undefined ,
62+ b : string [ ]
63+ ) : ParserPlugin [ ] | undefined {
64+ if ( ! b . some ( ( plugin ) => a ?. some ( ( p ) => pluginName ( p ) === plugin ) ) ) {
65+ return a
66+ }
67+ return a ?. filter ( ( p ) => ! b . includes ( pluginName ( p ) ) )
68+ }
69+
4270export class Parser {
4371 readonly babelParser : BabelParser
4472 readonly parserOpts : ParserOptions
@@ -67,50 +95,83 @@ export class Parser {
6795 plugins : mergePlugins ( this . parserOpts . plugins , parserOpts . plugins ) ,
6896 } )
6997 }
98+
99+ mergePlugins ( ...plugins : ParserPlugin [ ] ) : Parser {
100+ const merged = mergePlugins ( this . parserOpts . plugins , plugins )
101+ return merged === this . parserOpts . plugins
102+ ? this
103+ : new Parser ( this . babelParser , {
104+ ...this . parserOpts ,
105+ plugins : merged ,
106+ } )
107+ }
108+
109+ removePlugins ( ...plugins : string [ ] ) : Parser {
110+ const removed = removePlugins ( this . parserOpts . plugins , plugins )
111+ return removed === this . parserOpts . plugins
112+ ? this
113+ : new Parser ( this . babelParser , {
114+ ...this . parserOpts ,
115+ plugins : removed ,
116+ } )
117+ }
118+
119+ get forJs ( ) : Parser {
120+ if ( ! this . parserOpts . plugins ?. some ( ( p ) => pluginName ( p ) === 'typescript' ) )
121+ return this
122+ return this . removePlugins ( 'typescript' , 'decorators-legacy' ) . mergePlugins (
123+ [ 'flow' , { all : true } ] ,
124+ 'flowComments' ,
125+ 'jsx' ,
126+ [ 'decorators' , { decoratorsBeforeExport : false } ]
127+ )
128+ }
129+
130+ get forTs ( ) : Parser {
131+ return this . removePlugins (
132+ 'flow' ,
133+ 'flowComments' ,
134+ 'decorators' ,
135+ 'jsx'
136+ ) . mergePlugins (
137+ [ 'typescript' , { disallowAmbiguousJSXLike : true , dts : false } ] ,
138+ 'decorators-legacy'
139+ )
140+ }
141+
142+ get forTsx ( ) : Parser {
143+ return this . removePlugins (
144+ 'flow' ,
145+ 'flowComments' ,
146+ 'decorators'
147+ ) . mergePlugins (
148+ [ 'typescript' , { disallowAmbiguousJSXLike : true , dts : false } ] ,
149+ 'decorators-legacy' ,
150+ 'jsx'
151+ )
152+ }
153+
154+ get forDts ( ) : Parser {
155+ return this . removePlugins (
156+ 'flow' ,
157+ 'flowComments' ,
158+ 'decorators' ,
159+ 'jsx'
160+ ) . mergePlugins (
161+ [ 'typescript' , { disallowAmbiguousJSXLike : true , dts : true } ] ,
162+ 'decorators-legacy'
163+ )
164+ }
165+
166+ forExtension ( e : string ) : Parser {
167+ if ( / ( \. | ^ ) ( [ c m ] ? j s x ? ( \. f l o w ) ? ) / . test ( e ) ) return this . forJs
168+ if ( / ( \. | ^ ) \. d \. t s / i. test ( e ) ) return this . forDts
169+ if ( / ( \. | ^ ) \. [ c m ] ? t s x / i. test ( e ) ) return this . forTsx
170+ if ( / ( \. | ^ ) \. [ c m ] ? t s / i. test ( e ) ) return this . forTs
171+ return this
172+ }
70173}
71174
72- const tsPlugins : ParserPlugin [ ] = [
73- 'asyncGenerators' ,
74- 'bigInt' ,
75- 'classPrivateMethods' ,
76- 'classPrivateProperties' ,
77- 'classProperties' ,
78- 'decorators-legacy' ,
79- 'doExpressions' ,
80- 'dynamicImport' ,
81- 'exportDefaultFrom' ,
82- 'exportNamespaceFrom' ,
83- 'functionBind' ,
84- 'functionSent' ,
85- 'importMeta' ,
86- 'nullishCoalescingOperator' ,
87- 'numericSeparator' ,
88- 'objectRestSpread' ,
89- 'optionalCatchBinding' ,
90- 'optionalChaining' ,
91- [ 'pipelineOperator' , { proposal : 'minimal' } ] ,
92- 'throwExpressions' ,
93- 'typescript' ,
94- ]
95-
96- export const tsParser : Parser = new Parser ( defaultBabelParser , {
97- sourceType : 'module' ,
98- allowImportExportEverywhere : true ,
99- allowReturnOutsideFunction : true ,
100- startLine : 1 ,
101- plugins : tsPlugins ,
102- } )
103- export const dtsParser : Parser = new Parser ( defaultBabelParser , {
104- sourceType : 'module' ,
105- allowImportExportEverywhere : true ,
106- allowReturnOutsideFunction : true ,
107- startLine : 1 ,
108- plugins : mergePlugins ( tsPlugins , [ [ 'typescript' , { dts : true } ] ] ) ,
109- } )
110- export const tsxParser : Parser = new Parser ( defaultBabelParser , {
111- ...tsParser . parserOpts ,
112- plugins : [ ...tsPlugins , 'jsx' ] ,
113- } )
114175export const jsParser : Parser = new Parser ( defaultBabelParser , {
115176 sourceType : 'module' ,
116177 allowImportExportEverywhere : true ,
@@ -125,33 +186,29 @@ export const jsParser: Parser = new Parser(defaultBabelParser, {
125186 'classProperties' ,
126187 'classPrivateProperties' ,
127188 'classPrivateMethods' ,
128- [ 'decorators' , { decoratorsBeforeExport : false } ] ,
129- 'doExpressions' ,
189+ 'classStaticBlock' ,
130190 'dynamicImport' ,
131- 'exportDefaultFrom' ,
132191 'exportNamespaceFrom' ,
133- 'functionBind' ,
134192 'functionSent' ,
135193 'importMeta' ,
136194 'logicalAssignment' ,
195+ 'moduleStringNames' ,
137196 'nullishCoalescingOperator' ,
138197 'numericSeparator' ,
139198 'objectRestSpread' ,
140199 'optionalCatchBinding' ,
141200 'optionalChaining' ,
142- [ 'pipelineOperator' , { proposal : 'minimal' } ] ,
143- 'throwExpressions ' ,
201+ 'privateIn' ,
202+ 'topLevelAwait ' ,
144203 ] ,
145204} )
146205
206+ export const tsParser : Parser = jsParser . forTs
207+ export const tsxParser : Parser = jsParser . forTsx
208+ export const dtsParser : Parser = jsParser . forDts
209+
147210function defaultParser ( extname : string ) : Parser {
148- return extname === '.tsx'
149- ? tsxParser
150- : extname === '.d.ts'
151- ? dtsParser
152- : extname === '.ts'
153- ? tsParser
154- : jsParser
211+ return jsParser . forExtension ( extname )
155212}
156213
157214const resolve : (
0 commit comments