@@ -2,70 +2,58 @@ import path from 'path';
22import fs from 'fs' ;
33import sass from 'sass' ;
44
5+ const DEFAULT_EXTS = [ 'scss' , 'sass' , 'css' ] ;
6+
7+ export function resolveUrls ( url : string , extensions : string [ ] = DEFAULT_EXTS ) {
8+ // We only care about tilde-prefixed imports that do not look like paths.
9+ if ( ! url . startsWith ( '~' ) || url . startsWith ( '~/' ) ) {
10+ return [ ] ;
11+ }
12+
13+ const module_path = path . join ( 'node_modules' , url . substring ( 1 ) ) ;
14+ let variants = [ module_path ] ;
15+
16+ const parts = path . parse ( module_path ) ;
17+
18+ // Support sass partials by including paths where the file is prefixed by an underscore.
19+ if ( ! parts . base . startsWith ( '_' ) ) {
20+ const underscore_name = '_' . concat ( parts . name ) ;
21+ const replacement = {
22+ root : parts . root ,
23+ dir : parts . dir ,
24+ ext : parts . ext ,
25+ base : `${ underscore_name } ${ parts . ext } ` ,
26+ name : underscore_name ,
27+ } ;
28+ variants . push ( path . format ( replacement ) ) ;
29+ }
30+
31+ // Support index files.
32+ variants . push ( path . join ( module_path , '_index' ) ) ;
33+
34+ // Create variants such that it has entries of the form
35+ // node_modules/@foo /bar/baz.(scss|sass)
36+ // for an import of the form ~@foo /bar/baz(.(scss|sass))?
37+ if ( ! extensions . some ( ( ext ) => parts . ext == `.${ ext } ` ) ) {
38+ variants = extensions . flatMap ( ( ext ) =>
39+ variants . map ( ( variant ) => `${ variant } .${ ext } ` ) ,
40+ ) ;
41+ }
42+
43+ return variants ;
44+ }
45+
546/**
647 * Creates a sass importer which resolves Webpack-style tilde-imports.
748 */
849export const sassTildeImporter : sass . FileImporter < 'sync' > = {
950 findFileUrl ( url ) {
10- // We only care about tilde-prefixed imports that do not look like paths.
11- if ( ! url . startsWith ( '~' ) || url . startsWith ( '~/' ) ) {
12- return null ;
13- }
14-
15- // Create subpathsWithExts such that it has entries of the form
16- // node_modules/@foo /bar/baz.(scss|sass)
17- // for an import of the form ~@foo /bar/baz(.(scss|sass))?
18- const nodeModSubpath = path . join ( 'node_modules' , url . substring ( 1 ) ) ;
19- const subpathsWithExts : string [ ] = [ ] ;
20- if (
21- nodeModSubpath . endsWith ( '.scss' ) ||
22- nodeModSubpath . endsWith ( '.sass' ) ||
23- nodeModSubpath . endsWith ( '.css' )
24- ) {
25- subpathsWithExts . push ( nodeModSubpath ) ;
26- } else {
27- // Look for .scss first.
28- subpathsWithExts . push (
29- `${ nodeModSubpath } .scss` ,
30- `${ nodeModSubpath } .sass` ,
31- `${ nodeModSubpath } .css` ,
32- ) ;
33- }
34-
35- // Support index files.
36- subpathsWithExts . push (
37- `${ nodeModSubpath } /_index.scss` ,
38- `${ nodeModSubpath } /_index.sass` ,
39- ) ;
40-
41- // Support sass partials by including paths where the file is prefixed by an underscore.
42- const basename = path . basename ( nodeModSubpath ) ;
43- if ( ! basename . startsWith ( '_' ) ) {
44- const partials = subpathsWithExts . map ( ( file ) => {
45- const parts = path . parse ( file ) ;
46- const replacement = '_' . concat ( parts . name ) ;
47- parts . base = parts . base . replace ( parts . name , replacement ) ;
48- parts . name = replacement ;
49- return path . format ( parts ) ;
50- } ) ;
51- subpathsWithExts . push ( ...partials ) ;
52- }
51+ const searchPaths = resolveUrls ( url ) ;
5352
54- // Climbs the filesystem tree until we get to the root, looking for the first
55- // node_modules directory which has a matching module and filename.
56- let prevDir = '' ;
57- let dir = path . dirname ( url ) ;
58- while ( prevDir !== dir ) {
59- const searchPaths = subpathsWithExts . map ( ( subpathWithExt ) =>
60- path . join ( dir , subpathWithExt ) ,
61- ) ;
62- for ( const searchPath of searchPaths ) {
63- if ( fs . existsSync ( searchPath ) ) {
64- return new URL ( `file://${ path . resolve ( searchPath ) } ` ) ;
65- }
53+ for ( const searchPath of searchPaths ) {
54+ if ( fs . existsSync ( searchPath ) ) {
55+ return new URL ( `file://${ path . resolve ( searchPath ) } ` ) ;
6656 }
67- prevDir = dir ;
68- dir = path . dirname ( dir ) ;
6957 }
7058
7159 // Returning null is not itself an error, it tells sass to instead try the
0 commit comments