|
| 1 | +import * as fs from 'fs'; |
1 | 2 | import * as path from 'path';
|
2 | 3 | import * as ts_module from 'typescript/lib/tsserverlibrary';
|
3 | 4 | import { createMatchers } from './helpers/createMatchers';
|
@@ -79,15 +80,59 @@ function init({ typescript: ts }: { typescript: typeof ts_module }) {
|
79 | 80 | );
|
80 | 81 |
|
81 | 82 | return moduleNames.map((moduleName, index) => {
|
82 |
| - if (isRelativeCSS(moduleName)) { |
83 |
| - return { |
84 |
| - extension: ts_module.Extension.Dts, |
85 |
| - isExternalLibraryImport: false, |
86 |
| - resolvedFileName: path.resolve( |
87 |
| - path.dirname(containingFile), |
| 83 | + try { |
| 84 | + if (isRelativeCSS(moduleName)) { |
| 85 | + return { |
| 86 | + extension: ts_module.Extension.Dts, |
| 87 | + isExternalLibraryImport: false, |
| 88 | + resolvedFileName: path.resolve( |
| 89 | + path.dirname(containingFile), |
| 90 | + moduleName, |
| 91 | + ), |
| 92 | + }; |
| 93 | + } else if (isCSS(moduleName)) { |
| 94 | + // TODO: Move this section to a separate file and add basic tests. |
| 95 | + // Attempts to locate the module using TypeScript's previous search paths. These include "baseUrl" and "paths". |
| 96 | + const failedModule = info.project.getResolvedModuleWithFailedLookupLocationsFromCache( |
88 | 97 | moduleName,
|
89 |
| - ), |
90 |
| - }; |
| 98 | + containingFile, |
| 99 | + ); |
| 100 | + const baseUrl = info.project.getCompilerOptions().baseUrl; |
| 101 | + const match = '/index.ts'; |
| 102 | + |
| 103 | + // An array of paths TypeScript searched for the module. All include .ts, .tsx, .d.ts, or .json extensions. |
| 104 | + const failedLocations: string[] = (failedModule as any) |
| 105 | + .failedLookupLocations; |
| 106 | + // Filter to only one extension type, and remove that extension. This leaves us with the actual filename. |
| 107 | + // Example: "usr/person/project/src/dir/File.module.css/index.d.ts" > "usr/person/project/src/dir/File.module.css" |
| 108 | + const normalizedLocations = failedLocations.reduce( |
| 109 | + (locations, location) => { |
| 110 | + if ( |
| 111 | + (baseUrl ? location.includes(baseUrl) : true) && |
| 112 | + location.endsWith(match) |
| 113 | + ) { |
| 114 | + return [...locations, location.replace(match, '')]; |
| 115 | + } |
| 116 | + return locations; |
| 117 | + }, |
| 118 | + [] as string[], |
| 119 | + ); |
| 120 | + |
| 121 | + // Find the imported CSS module, if it exists. |
| 122 | + const cssModulePath = normalizedLocations.find((location) => |
| 123 | + fs.existsSync(location), |
| 124 | + ); |
| 125 | + |
| 126 | + if (cssModulePath) { |
| 127 | + return { |
| 128 | + extension: ts_module.Extension.Dts, |
| 129 | + isExternalLibraryImport: false, |
| 130 | + resolvedFileName: path.resolve(cssModulePath), |
| 131 | + }; |
| 132 | + } |
| 133 | + } |
| 134 | + } catch (e) { |
| 135 | + return resolvedModules[index]; |
91 | 136 | }
|
92 | 137 | return resolvedModules[index];
|
93 | 138 | });
|
|
0 commit comments