diff --git a/src/index.ts b/src/index.ts index 5c285cb..20352c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs'; import * as path from 'path'; import * as ts_module from 'typescript/lib/tsserverlibrary'; import { createMatchers } from './helpers/createMatchers'; @@ -79,15 +80,59 @@ function init({ typescript: ts }: { typescript: typeof ts_module }) { ); return moduleNames.map((moduleName, index) => { - if (isRelativeCSS(moduleName)) { - return { - extension: ts_module.Extension.Dts, - isExternalLibraryImport: false, - resolvedFileName: path.resolve( - path.dirname(containingFile), + try { + if (isRelativeCSS(moduleName)) { + return { + extension: ts_module.Extension.Dts, + isExternalLibraryImport: false, + resolvedFileName: path.resolve( + path.dirname(containingFile), + moduleName, + ), + }; + } else if (isCSS(moduleName)) { + // TODO: Move this section to a separate file and add basic tests. + // Attempts to locate the module using TypeScript's previous search paths. These include "baseUrl" and "paths". + const failedModule = info.project.getResolvedModuleWithFailedLookupLocationsFromCache( moduleName, - ), - }; + containingFile, + ); + const baseUrl = info.project.getCompilerOptions().baseUrl; + const match = '/index.ts'; + + // An array of paths TypeScript searched for the module. All include .ts, .tsx, .d.ts, or .json extensions. + const failedLocations: string[] = (failedModule as any) + .failedLookupLocations; + // Filter to only one extension type, and remove that extension. This leaves us with the actual filename. + // Example: "usr/person/project/src/dir/File.module.css/index.d.ts" > "usr/person/project/src/dir/File.module.css" + const normalizedLocations = failedLocations.reduce( + (locations, location) => { + if ( + (baseUrl ? location.includes(baseUrl) : true) && + location.endsWith(match) + ) { + return [...locations, location.replace(match, '')]; + } + return locations; + }, + [] as string[], + ); + + // Find the imported CSS module, if it exists. + const cssModulePath = normalizedLocations.find((location) => + fs.existsSync(location), + ); + + if (cssModulePath) { + return { + extension: ts_module.Extension.Dts, + isExternalLibraryImport: false, + resolvedFileName: path.resolve(cssModulePath), + }; + } + } + } catch (e) { + return resolvedModules[index]; } return resolvedModules[index]; });