Skip to content
This repository was archived by the owner on Jan 31, 2025. It is now read-only.

Commit 3651c78

Browse files
committed
Add comments to source-code
1 parent c5f311f commit 3651c78

File tree

1 file changed

+67
-34
lines changed

1 file changed

+67
-34
lines changed

index.js

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ var SassError = {
1515
status: 1
1616
};
1717

18+
// libsass uses this precedence when importing files without extension
1819
var extPrecedence = ['.scss', '.sass', '.css'];
1920
var matchCss = /\.css$/;
2021

2122
/**
2223
* The sass-loader makes node-sass available to webpack modules.
2324
*
2425
* @param {string} content
25-
* @returns {*}
26+
* @returns {string}
2627
*/
2728
module.exports = function (content) {
2829
var callback = this.async();
@@ -69,93 +70,106 @@ module.exports = function (content) {
6970
*/
7071
function getWebpackImporter() {
7172
if (isSync) {
72-
return function syncWebpackImporter(url, context) {
73+
return function syncWebpackImporter(url, fileContext) {
74+
var dirContext;
75+
7376
url = utils.urlToRequest(url, opt.root);
74-
context = normalizeContext(context);
77+
dirContext = fileToDirContext(fileContext);
7578

76-
return syncResolve(context, url, getImportsToResolve(url));
79+
return resolveSync(dirContext, url, getImportsToResolve(url));
7780
};
7881
}
79-
return function asyncWebpackImporter(url, context, done) {
82+
return function asyncWebpackImporter(url, fileContext, done) {
83+
var dirContext;
84+
8085
url = utils.urlToRequest(url, opt.root);
81-
context = normalizeContext(context);
86+
dirContext = fileToDirContext(fileContext);
8287

83-
asyncResolve(context, url, getImportsToResolve(url), done);
88+
resolve(dirContext, url, getImportsToResolve(url), done);
8489
};
8590
}
8691

8792
/**
88-
* Tries to resolve the given url synchronously. If a resolve error occurs, a second try for the same
89-
* module prefixed with an underscore is started.
93+
* Tries to resolve the first url of importsToResolve. If that resolve fails, the next url is tried.
94+
* If all imports fail, the import is passed to libsass which also take includePaths into account.
9095
*
91-
* @param {object} loaderContext
92-
* @param {string} url
93-
//* @param {string} context
96+
* @param {string} dirContext
97+
* @param {string} originalImport
98+
* @param {Array} importsToResolve
9499
* @returns {object}
95100
*/
96-
function syncResolve(fileContext, originalImport, importsToResolve) {
101+
function resolveSync(dirContext, originalImport, importsToResolve) {
97102
var importToResolve = importsToResolve.shift();
98103
var resolvedFilename;
99104

100105
if (!importToResolve) {
106+
// No import possibilities left. Let's pass that one back to libsass...
101107
return {
102108
file: originalImport
103109
};
104110
}
105111

106112
try {
107-
resolvedFilename = self.resolveSync(fileContext, importToResolve);
113+
resolvedFilename = self.resolveSync(dirContext, importToResolve);
114+
// Add the resolvedFilename as dependency. Although we're also using stats.includedFiles, this might come
115+
// in handy when an error occurs. In this case, we don't get stats.includedFiles from node-sass.
108116
self.dependency(resolvedFilename);
117+
// By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
109118
resolvedFilename = resolvedFilename.replace(matchCss, '');
110119
return {
111120
file: resolvedFilename
112121
};
113122
} catch (err) {
114-
return syncResolve(fileContext, originalImport, importsToResolve);
123+
return resolveSync(dirContext, originalImport, importsToResolve);
115124
}
116125
}
117126

118127
/**
119-
* Tries to resolve the given url asynchronously. If a resolve error occurs, a second try for the same
120-
* module prefixed with an underscore is started.
128+
* Tries to resolve the first url of importsToResolve. If that resolve fails, the next url is tried.
129+
* If all imports fail, the import is passed to libsass which also take includePaths into account.
121130
*
122-
* @param {object} loaderContext
123-
* @param {string} url
124-
* @param {string} fileContext
131+
* @param {string} dirContext
132+
* @param {string} originalImport
133+
* @param {Array} importsToResolve
125134
* @param {function} done
126135
*/
127-
function asyncResolve(fileContext, originalImport, importsToResolve, done) {
136+
function resolve(dirContext, originalImport, importsToResolve, done) {
128137
var importToResolve = importsToResolve.shift();
129138

130139
if (!importToResolve) {
140+
// No import possibilities left. Let's pass that one back to libsass...
131141
done({
132142
file: originalImport
133143
});
134144
return;
135145
}
136146

137-
self.resolve(fileContext, importToResolve, function onWebpackResolve(err, resolvedFilename) {
147+
self.resolve(dirContext, importToResolve, function onWebpackResolve(err, resolvedFilename) {
138148
if (err) {
139-
asyncResolve(fileContext, originalImport, importsToResolve, done);
149+
resolve(dirContext, originalImport, importsToResolve, done);
140150
return;
141151
}
152+
// Add the resolvedFilename as dependency. Although we're also using stats.includedFiles, this might come
153+
// in handy when an error occurs. In this case, we don't get stats.includedFiles from node-sass.
142154
self.dependency(resolvedFilename);
155+
// By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
156+
resolvedFilename = resolvedFilename.replace(matchCss, '');
157+
143158
// Use self.loadModule() before calling done() to make imported files available to
144159
// other webpack tools like postLoaders etc.?
145160

146-
resolvedFilename = resolvedFilename.replace(matchCss, '');
147161
done({
148162
file: resolvedFilename.replace(matchCss, '')
149163
});
150164
});
151165
}
152166

153-
function normalizeContext(context) {
167+
function fileToDirContext(fileContext) {
154168
// The first file is 'stdin' when we're using the data option
155-
if (context === 'stdin') {
156-
context = resourcePath;
169+
if (fileContext === 'stdin') {
170+
fileContext = resourcePath;
157171
}
158-
return path.dirname(context);
172+
return path.dirname(fileContext);
159173
}
160174

161175
// When files have been imported via the includePaths-option, these files need to be
@@ -266,6 +280,22 @@ function getFileExcerptIfPossible(err) {
266280
}
267281
}
268282

283+
/**
284+
* When libsass tries to resolve an import, it uses this "funny" algorithm:
285+
*
286+
* - Imports with no file extension:
287+
 * - Prefer modules starting with '_'
288+
 * - File extension precedence: .scss, .sass, .css
289+
* - Imports with file extension:
290+
 * - If the file is a CSS-file, do not include it all, but just link it via @import url()
291+
 * - The exact file name must match (no auto-resolving of '_'-modules)
292+
*
293+
* Since the sass-loader uses webpack to resolve the modules, we need to simulate that algorithm. This function
294+
* returns an array of import paths to try.
295+
*
296+
* @param {string} originalImport
297+
* @returns {Array}
298+
*/
269299
function getImportsToResolve(originalImport) {
270300
var ext = path.extname(originalImport);
271301
var basename = path.basename(originalImport);
@@ -278,23 +308,26 @@ function getImportsToResolve(originalImport) {
278308
}
279309

280310
if (originalImport.charAt(0) !== '.') {
311+
// If true: originalImport is a module import like 'bootstrap-sass...'
281312
if (dirname === '.') {
313+
// If true: originalImport is just a module import without a path like 'bootstrap-sass'
314+
// In this case we don't do that auto-resolving dance at all.
282315
return [originalImport];
283316
}
284317
}
285318
if (ext) {
286319
if (ext === '.scss' || ext === '.sass') {
287320
add(basename);
288-
if (!startsWithUnderscore) {
289-
add('_' + basename);
290-
}
291321
}/* else {
292322
Leave unknown extensions (like .css) untouched
293323
}*/
294324
} else {
295-
extPrecedence.forEach(function (ext) {
296-
add('_' + basename + ext);
297-
});
325+
if (!startsWithUnderscore) {
326+
// Prefer modules starting with '_' first
327+
extPrecedence.forEach(function (ext) {
328+
add('_' + basename + ext);
329+
});
330+
}
298331
extPrecedence.forEach(function (ext) {
299332
add(basename + ext);
300333
});

0 commit comments

Comments
 (0)