diff --git a/src/importers/__tests__/sassTildeImporter.ts b/src/importers/__tests__/sassTildeImporter.ts new file mode 100644 index 0000000..cbf6edd --- /dev/null +++ b/src/importers/__tests__/sassTildeImporter.ts @@ -0,0 +1,53 @@ +import sass from 'sass'; +import { sassTildeImporter } from '../sassTildeImporter'; + +describe('importers / sassTildeImporter', () => { + const source = 'src/importers/sassTildeImporter.ts'; + const done = (data: sass.ImporterReturnType) => void data; + + it('should return null when not a tilde import', () => { + expect(sassTildeImporter('color.scss', source, done)).toBeNull(); + }); + + it('should return null when node module does not exist', () => { + expect( + sassTildeImporter('~made_up_module/color.scss', source, done), + ).toBeNull(); + }); + + it('should resolve file from node_modules', () => { + expect( + sassTildeImporter('~bootstrap/scss/bootstrap', source, done), + ).toMatchObject({ file: 'node_modules/bootstrap/scss/bootstrap.scss' }); + }); + + it('should resolve sass partial from node_modules', () => { + // explicit + expect( + sassTildeImporter('~bootstrap/scss/_grid.scss', source, done), + ).toMatchObject({ file: 'node_modules/bootstrap/scss/_grid.scss' }); + expect( + sassTildeImporter('~bootstrap/scss/_grid', source, done), + ).toMatchObject({ file: 'node_modules/bootstrap/scss/_grid.scss' }); + // implicit + expect( + sassTildeImporter('~bootstrap/scss/grid.scss', source, done), + ).toMatchObject({ file: 'node_modules/bootstrap/scss/_grid.scss' }); + expect( + sassTildeImporter('~bootstrap/scss/grid', source, done), + ).toMatchObject({ file: 'node_modules/bootstrap/scss/_grid.scss' }); + }); + + it('should resolve .css files', () => { + expect( + sassTildeImporter('~bootstrap/dist/css/bootstrap-grid.css', source, done), + ).toMatchObject({ + file: 'node_modules/bootstrap/dist/css/bootstrap-grid.css', + }); + expect( + sassTildeImporter('~bootstrap/dist/css/bootstrap-grid', source, done), + ).toMatchObject({ + file: 'node_modules/bootstrap/dist/css/bootstrap-grid.css', + }); + }); +}); diff --git a/src/importers/sassTildeImporter.ts b/src/importers/sassTildeImporter.ts index af1cf99..ed8be96 100644 --- a/src/importers/sassTildeImporter.ts +++ b/src/importers/sassTildeImporter.ts @@ -19,11 +19,28 @@ export const sassTildeImporter: sass.Importer = ( // for an import of the form ~@foo/bar/baz(.(scss|sass))? const nodeModSubpath = path.join('node_modules', rawImportPath.substring(1)); const subpathsWithExts: string[] = []; - if (nodeModSubpath.endsWith('.scss') || nodeModSubpath.endsWith('.sass')) { + if ( + nodeModSubpath.endsWith('.scss') || + nodeModSubpath.endsWith('.sass') || + nodeModSubpath.endsWith('.css') + ) { subpathsWithExts.push(nodeModSubpath); } else { // Look for .scss first. - subpathsWithExts.push(`${nodeModSubpath}.scss`, `${nodeModSubpath}.sass`); + subpathsWithExts.push( + `${nodeModSubpath}.scss`, + `${nodeModSubpath}.sass`, + `${nodeModSubpath}.css`, + ); + } + + // Support sass partials by including paths where the file is prefixed by an underscore. + const basename = path.basename(nodeModSubpath); + if (!basename.startsWith('_')) { + const partials = subpathsWithExts.map((file) => + file.replace(basename, `_${basename}`), + ); + subpathsWithExts.push(...partials); } // Climbs the filesystem tree until we get to the root, looking for the first