@@ -14,7 +14,9 @@ var SassError = {
14
14
file : 'stdin' ,
15
15
status : 1
16
16
} ;
17
- var resolveError = / C a n n o t r e s o l v e / ;
17
+
18
+ var extPrecedence = [ '.scss' , '.sass' , '.css' ] ;
19
+ var matchCss = / \. c s s $ / ;
18
20
19
21
/**
20
22
* The sass-loader makes node-sass available to webpack modules.
@@ -27,12 +29,8 @@ module.exports = function (content) {
27
29
var isSync = typeof callback !== 'function' ;
28
30
var self = this ;
29
31
var resourcePath = this . resourcePath ;
30
- var extensionMatcher = / \. ( s a s s | s c s s | c s s ) $ / ;
31
32
var result ;
32
- var fileExt ;
33
33
var opt ;
34
- var contextMatch ;
35
- var extension ;
36
34
37
35
/**
38
36
* Enhances the sass error with additional information about what actually went wrong.
@@ -70,31 +68,82 @@ module.exports = function (content) {
70
68
function getWebpackImporter ( ) {
71
69
if ( isSync ) {
72
70
return function syncWebpackImporter ( url , context ) {
73
- url = urlToRequest ( url , context ) ;
71
+ url = utils . urlToRequest ( url , opt . root ) ;
74
72
context = normalizeContext ( context ) ;
75
73
76
- return syncResolve ( self , url , context ) ;
74
+ return syncResolve ( context , url , getImportsToResolve ( url ) ) ;
77
75
} ;
78
76
}
79
77
return function asyncWebpackImporter ( url , context , done ) {
80
- url = urlToRequest ( url , context ) ;
78
+ url = utils . urlToRequest ( url , opt . root ) ;
81
79
context = normalizeContext ( context ) ;
82
80
83
- asyncResolve ( self , url , context , done ) ;
81
+ asyncResolve ( context , url , getImportsToResolve ( url ) , done ) ;
84
82
} ;
85
83
}
86
84
87
- function urlToRequest ( url , context ) {
88
- contextMatch = context . match ( extensionMatcher ) ;
85
+ /**
86
+ * Tries to resolve the given url synchronously. If a resolve error occurs, a second try for the same
87
+ * module prefixed with an underscore is started.
88
+ *
89
+ * @param {object } loaderContext
90
+ * @param {string } url
91
+ //* @param {string } context
92
+ * @returns {object }
93
+ */
94
+ function syncResolve ( fileContext , originalImport , importsToResolve ) {
95
+ var importToResolve = importsToResolve . shift ( ) ;
96
+ var resolvedFilename ;
89
97
90
- // Add sass/scss/css extension if it is missing
91
- // The extension is inherited from importing resource or the default is used
92
- if ( ! url . match ( extensionMatcher ) ) {
93
- extension = contextMatch && contextMatch [ 0 ] || fileExt ;
94
- url = url + extension ;
98
+ if ( ! importToResolve ) {
99
+ return {
100
+ file : originalImport
101
+ } ;
95
102
}
96
103
97
- return utils . urlToRequest ( url , opt . root ) ;
104
+ try {
105
+ resolvedFilename = self . resolveSync ( fileContext , importToResolve ) ;
106
+ resolvedFilename = resolvedFilename . replace ( matchCss , '' ) ;
107
+ return {
108
+ file : resolvedFilename
109
+ } ;
110
+ } catch ( err ) {
111
+ return syncResolve ( fileContext , originalImport , importsToResolve ) ;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Tries to resolve the given url asynchronously. If a resolve error occurs, a second try for the same
117
+ * module prefixed with an underscore is started.
118
+ *
119
+ * @param {object } loaderContext
120
+ * @param {string } url
121
+ * @param {string } fileContext
122
+ * @param {function } done
123
+ */
124
+ function asyncResolve ( fileContext , originalImport , importsToResolve , done ) {
125
+ var importToResolve = importsToResolve . shift ( ) ;
126
+
127
+ if ( ! importToResolve ) {
128
+ done ( {
129
+ file : originalImport
130
+ } ) ;
131
+ return ;
132
+ }
133
+
134
+ self . resolve ( fileContext , importToResolve , function onWebpackResolve ( err , resolvedFilename ) {
135
+ if ( err ) {
136
+ asyncResolve ( fileContext , originalImport , importsToResolve , done ) ;
137
+ return ;
138
+ }
139
+ // Use self.loadModule() before calling done() to make imported files available to
140
+ // other webpack tools like postLoaders etc.?
141
+
142
+ resolvedFilename = resolvedFilename . replace ( matchCss , '' ) ;
143
+ done ( {
144
+ file : resolvedFilename . replace ( matchCss , '' )
145
+ } ) ;
146
+ } ) ;
98
147
}
99
148
100
149
function normalizeContext ( context ) {
@@ -145,7 +194,6 @@ module.exports = function (content) {
145
194
146
195
// indentedSyntax is a boolean flag
147
196
opt . indentedSyntax = Boolean ( opt . indentedSyntax ) ;
148
- fileExt = '.' + ( opt . indentedSyntax ? 'sass' : 'scss' ) ;
149
197
150
198
// opt.importer
151
199
opt . importer = getWebpackImporter ( ) ;
@@ -208,94 +256,39 @@ function getFileExcerptIfPossible(err) {
208
256
}
209
257
}
210
258
211
- /**
212
- * Tries to resolve the given url synchronously. If a resolve error occurs, a second try for the same
213
- * module prefixed with an underscore is started.
214
- *
215
- * @param {object } loaderContext
216
- * @param {string } url
217
- * @param {string } context
218
- * @returns {object }
219
- */
220
- function syncResolve ( loaderContext , url , context ) {
221
- var filename ;
222
- var basename ;
223
-
224
- try {
225
- filename = loaderContext . resolveSync ( context , url ) ;
226
- } catch ( err ) {
227
- basename = path . basename ( url ) ;
228
- if ( requiresLookupForUnderscoreModule ( err , basename ) ) {
229
- url = addUnderscoreToBasename ( url , basename ) ;
230
- return syncResolve ( loaderContext , url , context ) ;
231
- }
259
+ function getImportsToResolve ( originalImport ) {
260
+ var ext = path . extname ( originalImport ) ;
261
+ var basename = path . basename ( originalImport ) ;
262
+ var dirname = path . dirname ( originalImport ) ;
263
+ var startsWithUnderscore = basename . charAt ( 0 ) === '_' ;
264
+ var paths = [ ] ;
232
265
233
- // let the libsass do the rest job, e.g. search module in includePaths
234
- filename = path . join ( path . dirname ( url ) , removeUnderscoreFromBasename ( basename ) ) ;
266
+ function add ( file ) {
267
+ paths . push ( dirname + path . sep + file ) ;
235
268
}
236
269
237
- return {
238
- file : filename
239
- } ;
240
- }
241
-
242
- /**
243
- * Tries to resolve the given url asynchronously. If a resolve error occurs, a second try for the same
244
- * module prefixed with an underscore is started.
245
- *
246
- * @param {object } loaderContext
247
- * @param {string } url
248
- * @param {string } context
249
- * @param {function } done
250
- */
251
- function asyncResolve ( loaderContext , url , context , done ) {
252
- loaderContext . resolve ( context , url , function onWebpackResolve ( err , filename ) {
253
- var basename ;
254
-
255
- if ( err ) {
256
- basename = path . basename ( url ) ;
257
- if ( requiresLookupForUnderscoreModule ( err , basename ) ) {
258
- url = addUnderscoreToBasename ( url , basename ) ;
259
- return asyncResolve ( loaderContext , url , context , done ) ;
260
- }
261
-
262
- // Let libsass do the rest of the job, like searching for the module in includePaths
263
- filename = path . join ( path . dirname ( url ) , removeUnderscoreFromBasename ( basename ) ) ;
270
+ if ( originalImport . charAt ( 0 ) !== '.' ) {
271
+ if ( dirname === '.' ) {
272
+ return [ originalImport ] ;
264
273
}
265
-
266
- // Use self.loadModule() before calling done() to make imported files available to
267
- // other webpack tools like postLoaders etc.?
268
-
269
- done ( {
270
- file : filename
274
+ }
275
+ if ( ext ) {
276
+ if ( ext === '.scss' || ext === '.sass' ) {
277
+ add ( basename ) ;
278
+ if ( ! startsWithUnderscore ) {
279
+ add ( '_' + basename ) ;
280
+ }
281
+ } /* else {
282
+ Leave unknown extensions (like .css) untouched
283
+ }*/
284
+ } else {
285
+ extPrecedence . forEach ( function ( ext ) {
286
+ add ( '_' + basename + ext ) ;
271
287
} ) ;
272
- } ) ;
273
- }
274
-
275
- /**
276
- * Check whether its a resolve error and the basename does *not* start with an underscore.
277
- *
278
- * @param {Error } err
279
- * @param {string } basename
280
- * @returns {boolean }
281
- */
282
- function requiresLookupForUnderscoreModule ( err , basename ) {
283
- return resolveError . test ( err . message ) && basename . charAt ( 0 ) !== '_' ;
284
- }
285
-
286
- /**
287
- * @param {string } url
288
- * @param {string } basename
289
- * @returns {string }
290
- */
291
- function addUnderscoreToBasename ( url , basename ) {
292
- return url . slice ( 0 , - basename . length ) + '_' + basename ;
293
- }
288
+ extPrecedence . forEach ( function ( ext ) {
289
+ add ( basename + ext ) ;
290
+ } ) ;
291
+ }
294
292
295
- /**
296
- * @param {string } basename
297
- * @returns {string }
298
- */
299
- function removeUnderscoreFromBasename ( basename ) {
300
- return basename [ 0 ] === '_' ? basename . substring ( 1 ) : basename ;
293
+ return paths ;
301
294
}
0 commit comments