11"use strict"
22
3+ const { getTSConfig, getTSConfigForFile } = require ( "./get-tsconfig" )
4+
35const DEFAULT_MAPPING = normalise ( [
6+ [ "" , ".js" ] ,
7+ [ ".ts" , ".js" ] ,
8+ [ ".cts" , ".cjs" ] ,
9+ [ ".mts" , ".mjs" ] ,
10+ [ ".tsx" , ".js" ] ,
11+ ] )
12+
13+ const PRESERVE_MAPPING = normalise ( [
414 [ "" , ".js" ] ,
515 [ ".ts" , ".js" ] ,
616 [ ".cts" , ".cjs" ] ,
717 [ ".mts" , ".mjs" ] ,
818 [ ".tsx" , ".jsx" ] ,
919] )
1020
21+ const tsConfigMapping = {
22+ react : DEFAULT_MAPPING , // Emit .js files with JSX changed to the equivalent React.createElement calls
23+ "react-jsx" : DEFAULT_MAPPING , // Emit .js files with the JSX changed to _jsx calls
24+ "react-jsxdev" : DEFAULT_MAPPING , // Emit .js files with the JSX changed to _jsx calls
25+ "react-native" : DEFAULT_MAPPING , // Emit .js files with the JSX unchanged
26+ preserve : PRESERVE_MAPPING , // Emit .jsx files with the JSX unchanged
27+ }
28+
1129/**
1230 * @typedef {Object } ExtensionMap
1331 * @property {Record<string, string> } forward Convert from typescript to javascript
@@ -28,6 +46,22 @@ function normalise(typescriptExtensionMap) {
2846 return { forward, backward }
2947}
3048
49+ /**
50+ * Attempts to get the ExtensionMap from the resolved tsconfig.
51+ *
52+ * @param {import("get-tsconfig").TsConfigJsonResolved } [tsconfig] - The resolved tsconfig
53+ * @returns {ExtensionMap } The `typescriptExtensionMap` value, or `null`.
54+ */
55+ function getMappingFromTSConfig ( tsconfig ) {
56+ const jsx = tsconfig ?. compilerOptions ?. jsx
57+
58+ if ( { } . hasOwnProperty . call ( tsConfigMapping , jsx ) ) {
59+ return tsConfigMapping [ jsx ]
60+ }
61+
62+ return null
63+ }
64+
3165/**
3266 * Gets `typescriptExtensionMap` property from a given option object.
3367 *
@@ -36,46 +70,82 @@ function normalise(typescriptExtensionMap) {
3670 */
3771function get ( option ) {
3872 if (
39- option &&
40- option . typescriptExtensionMap &&
41- Array . isArray ( option . typescriptExtensionMap )
73+ { } . hasOwnProperty . call ( tsConfigMapping , option ?. typescriptExtensionMap )
4274 ) {
75+ return tsConfigMapping [ option . typescriptExtensionMap ]
76+ }
77+
78+ if ( Array . isArray ( option ?. typescriptExtensionMap ) ) {
4379 return normalise ( option . typescriptExtensionMap )
4480 }
4581
82+ if ( option ?. tsconfigPath ) {
83+ return getMappingFromTSConfig ( getTSConfig ( option ?. tsconfigPath ) )
84+ }
85+
4686 return null
4787}
4888
89+ /**
90+ * Attempts to get the ExtensionMap from the tsconfig of a given file.
91+ *
92+ * @param {string } filename - The filename we're getting from
93+ * @returns {ExtensionMap } The `typescriptExtensionMap` value, or `null`.
94+ */
95+ function getFromTSConfigFromFile ( filename ) {
96+ return getMappingFromTSConfig ( getTSConfigForFile ( filename ) ?. config )
97+ }
98+
4999/**
50100 * Gets "typescriptExtensionMap" setting.
51101 *
52- * 1. This checks `options` property, then returns it if exists.
53- * 2. This checks `settings.n` | `settings.node` property, then returns it if exists.
54- * 3. This returns `DEFAULT_MAPPING`.
102+ * 1. This checks `options.typescriptExtensionMap`, if its an array then it gets returned.
103+ * 2. This checks `options.typescriptExtensionMap`, if its a string, convert to the correct mapping.
104+ * 3. This checks `settings.n.typescriptExtensionMap`, if its an array then it gets returned.
105+ * 4. This checks `settings.node.typescriptExtensionMap`, if its an array then it gets returned.
106+ * 5. This checks `settings.n.typescriptExtensionMap`, if its a string, convert to the correct mapping.
107+ * 6. This checks `settings.node.typescriptExtensionMap`, if its a string, convert to the correct mapping.
108+ * 7. This checks for a `tsconfig.json` `config.compilerOptions.jsx` property, if its a string, convert to the correct mapping.
109+ * 8. This returns `PRESERVE_MAPPING`.
55110 *
56- * @param {import(' eslint' ).Rule.RuleContext } context - The rule context.
111+ * @param {import(" eslint" ).Rule.RuleContext } context - The rule context.
57112 * @returns {string[] } A list of extensions.
58113 */
59114module . exports = function getTypescriptExtensionMap ( context ) {
60115 return (
61- get ( context . options && context . options [ 0 ] ) ||
62- get (
63- context . settings && ( context . settings . n || context . settings . node )
116+ get ( context . options ?. [ 0 ] ) ||
117+ get ( context . settings ?. n ?? context . settings ?. node ) ||
118+ getFromTSConfigFromFile (
119+ // eslint ^8
120+ context . physicalFilename ??
121+ // eslint ^7.28 (deprecated ^8)
122+ context . getPhysicalFilename ?. ( ) ??
123+ // eslint ^8 (if physicalFilename undefined)
124+ context . filename ??
125+ // eslint ^7 (deprecated ^8)
126+ context . getFilename ?. ( )
64127 ) ||
65- // TODO: Detect tsconfig.json here
66- DEFAULT_MAPPING
128+ PRESERVE_MAPPING
67129 )
68130}
69131
70132module . exports . schema = {
71- type : "array" ,
72- items : {
73- type : "array" ,
74- prefixItems : [
75- { type : "string" , pattern : "^(?:|\\.\\w+)$" } ,
76- { type : "string" , pattern : "^\\.\\w+$" } ,
77- ] ,
78- additionalItems : false ,
79- } ,
80- uniqueItems : true ,
133+ oneOf : [
134+ {
135+ type : "array" ,
136+ items : {
137+ type : "array" ,
138+ prefixItems : [
139+ { type : "string" , pattern : "^(?:|\\.\\w+)$" } ,
140+ { type : "string" , pattern : "^\\.\\w+$" } ,
141+ ] ,
142+ additionalItems : false ,
143+ } ,
144+ uniqueItems : true ,
145+ } ,
146+ {
147+ type : "string" ,
148+ enum : Object . keys ( tsConfigMapping ) ,
149+ } ,
150+ ] ,
81151}
0 commit comments