diff --git a/.changeset/long-hats-retire.md b/.changeset/long-hats-retire.md new file mode 100644 index 000000000..d97e913dc --- /dev/null +++ b/.changeset/long-hats-retire.md @@ -0,0 +1,6 @@ +--- +"skott": patch +--- + +Add support for tsx/jsx index modules. +index.tsx or index.jsx file resolution for modules diff --git a/packages/skott/src/modules/resolvers/base-resolver.ts b/packages/skott/src/modules/resolvers/base-resolver.ts index ddd0c4b34..724d92070 100644 --- a/packages/skott/src/modules/resolvers/base-resolver.ts +++ b/packages/skott/src/modules/resolvers/base-resolver.ts @@ -205,6 +205,11 @@ export function resolveImportedModulePath( * Example: `require("./component")` will resolve to `./component.jsx`. */ JSX_MODULE: module.concat(".jsx"), + /** + * or a JSX module targetted through a directory + * import e.g: require("./lib") which will eventually resolve to "lib/index.jsx". + */ + JSX_INDEX_MODULE: path.join(module, "index.jsx"), /** * In case of TypeScript modules, the module can be targetted through a directory * import e.g: import "./lib" which will eventually resolve to "lib/index.ts". @@ -219,6 +224,11 @@ export function resolveImportedModulePath( * Example: `require("./component")` will resolve to `./component.tsx`. */ TSX_MODULE: module.concat(".tsx"), + /** + * or a TSX module targetted through a directory + * import e.g: require("./lib") which will eventually resolve to "lib/index.tsx". + */ + TSX_INDEX_MODULE: path.join(module, "index.tsx"), /** * In case of TypeScript modules but when targetting ECMAScript modules, * modules are suffixed with ".js" but should resolve to their corresponding @@ -248,9 +258,15 @@ export function resolveImportedModulePath( Effect.orElse(() => resolveToModuleIfExists(ecmaScriptModuleCombinations.TSX_MODULE) ), + Effect.orElse(() => + resolveToModuleIfExists(ecmaScriptModuleCombinations.TSX_INDEX_MODULE) + ), Effect.orElse(() => resolveToModuleIfExists(ecmaScriptModuleCombinations.JSX_MODULE) ), + Effect.orElse(() => + resolveToModuleIfExists(ecmaScriptModuleCombinations.JSX_INDEX_MODULE) + ), Effect.orElse(() => resolveToModuleIfExists(ecmaScriptModuleCombinations.JS_INDEX_MODULE) ) diff --git a/packages/skott/test/unit/ecmascript/jsx-and-tsx.ts b/packages/skott/test/unit/ecmascript/jsx-and-tsx.ts index e8ab48717..2a04d163e 100644 --- a/packages/skott/test/unit/ecmascript/jsx-and-tsx.ts +++ b/packages/skott/test/unit/ecmascript/jsx-and-tsx.ts @@ -207,6 +207,103 @@ export function makeTestSuiteForJsxOrTsx(rawLanguage: "ts" | "js"): void { }); }); }); + + describe(`When ${jsxOrTsx} index module is imported via "./" or "." module declaration`, () => { + describe(`When there is only a ${jsxOrTsx} index module`, () => { + it(`it should resolve to index.${jsxOrTsx}`, async () => { + mountFakeFileSystem({ + [`index.${rawLanguage}`]: ` + import "./component_1"; + import "./component_2"; + `, + [`component_1/index.${jsxOrTsx}`]: ` + export default function Component() { + return
Hello World
; + } + `, + [`component_2/index.${jsxOrTsx}`]: ` + export default function Component() { + return
Hello World
; + } + ` + }); + + const { graph } = await buildSkottProjectUsingInMemoryFileExplorer({ + entrypoint: `index.${rawLanguage}` + }); + + expect(graph).to.be.deep.equal({ + [`index.${rawLanguage}`]: { + adjacentTo: [`component_1/index.${jsxOrTsx}`, `component_2/index.${jsxOrTsx}`], + id: `index.${rawLanguage}`, + body: fakeNodeBody + }, + [`component_1/index.${jsxOrTsx}`]: { + adjacentTo: [], + id: `component_1/index.${jsxOrTsx}`, + body: fakeNodeBody + }, + [`component_2/index.${jsxOrTsx}`]: { + adjacentTo: [], + id: `component_2/index.${jsxOrTsx}`, + body: fakeNodeBody + } + }); + }); + }); + describe(`When there is both ${jsxOrTsx} and ${rawLanguage} index modules`, () => { + it(`it should resolve to index.${rawLanguage} in priority over index.${jsxOrTsx}`, async () => { + mountFakeFileSystem({ + [`index.${rawLanguage}`]: ` + import "./component_1"; + import "./component_2"; + `, + [`component_1/index.${rawLanguage}`]: ` + export default function Component() { + return
Hello World
; + } + `, + [`component_1/index.${jsxOrTsx}`]: ` + export default function Component() { + return
Hello World
; + } + `, + [`component_2/index.${rawLanguage}`]: ` + export default function Component() { + return
Hello World
; + } + `, + [`component_2/index.${jsxOrTsx}`]: ` + export default function Component() { + return
Hello World
; + } + ` + }); + + const { graph } = await buildSkottProjectUsingInMemoryFileExplorer({ + entrypoint: `index.${rawLanguage}` + }); + + expect(graph).to.be.deep.equal({ + [`index.${rawLanguage}`]: { + adjacentTo: [`component_1/index.${rawLanguage}`, `component_2/index.${rawLanguage}`], + id: `index.${rawLanguage}`, + body: fakeNodeBody + }, + [`component_1/index.${rawLanguage}`]: { + adjacentTo: [], + id: `component_1/index.${rawLanguage}`, + body: fakeNodeBody + }, + [`component_2/index.${rawLanguage}`]: { + adjacentTo: [], + id: `component_2/index.${rawLanguage}`, + body: fakeNodeBody + } + }); + }); + }); + }); } describe("When some TypeScript code is not TSX compliant", () => {