Skip to content

Commit 38bffbb

Browse files
committed
add jsx and tsx parsers
1 parent b6360c2 commit 38bffbb

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Note: The implementation here is loosely based on the jsx and tsx parsers in 'jscodeshift'. It doesn't expose its
3+
* parsers, so we have to provide our own if we want to use anything besides the default. Fortunately, its parsers turn
4+
* out to just be wrappers around `babel.parse` with certain options set. The options chosen here are different from the
5+
* `jscodeshift` parsers in that a) unrecognized and deprecated options and options set to default values have been
6+
* removed, and b) all standard plugins are included, meaning the widest range of user code is able to be parsed.
7+
*/
8+
9+
import * as babel from '@babel/parser';
10+
import { File } from '@babel/types';
11+
12+
type Parser = {
13+
parse: (code: string) => babel.ParseResult<File>;
14+
};
15+
16+
const jsxOptions: babel.ParserOptions = {
17+
// Nextjs supports dynamic import, so this seems like a good idea
18+
allowImportExportEverywhere: true,
19+
// We're only supporting wrapping in ESM pages
20+
sourceType: 'module',
21+
// Without `tokens`, jsx parsing breaks
22+
tokens: true,
23+
// The maximal set of non-mutually-exclusive standard plugins, so as to support as much weird syntax in our users'
24+
// code as possible
25+
plugins: [
26+
'asyncDoExpressions',
27+
'decimal',
28+
['decorators', { decoratorsBeforeExport: false }],
29+
'decoratorAutoAccessors',
30+
'destructuringPrivate',
31+
'doExpressions',
32+
'estree',
33+
'exportDefaultFrom',
34+
'functionBind',
35+
'importMeta',
36+
'importAssertions',
37+
'jsx',
38+
'moduleBlocks',
39+
'partialApplication',
40+
['pipelineOperator', { proposal: 'hack', topicToken: '^' }],
41+
'regexpUnicodeSets',
42+
'throwExpressions',
43+
] as babel.ParserPlugin[],
44+
};
45+
46+
const tsxOptions = {
47+
...jsxOptions,
48+
// Because `jsxOptions` is typed as a `ParserOptions` object, TS doesn't discount the possibility of its `plugins`
49+
// property being undefined, even though it is, in fact, very clearly defined - hence the empty array.
50+
plugins: [...(jsxOptions.plugins || []), 'typescript'] as babel.ParserPlugin[],
51+
};
52+
53+
/**
54+
* Create either a jsx or tsx parser to be used by `jscodeshift`.
55+
*
56+
* @param type Either 'jsx' or 'tsx'
57+
* @returns An object with the appropriate `parse` method.
58+
*/
59+
export function makeParser(type: 'jsx' | 'tsx'): Parser {
60+
const options = type === 'jsx' ? jsxOptions : tsxOptions;
61+
return {
62+
parse: code => babel.parse(code, options),
63+
};
64+
}

0 commit comments

Comments
 (0)