forked from walmartlabs/stylus-relative-loader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
134 lines (114 loc) · 3.89 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
'use strict';
var loaderUtils = require('loader-utils');
var stylus = require('stylus');
var path = require('path');
var Promise = require('es6-promise').Promise;
var CachedPathEvaluator = require('./lib/evaluator');
var ImportCache = require('./lib/import-cache');
var resolver = require('./lib/resolver');
var debug = require('debug')('stylus-relative-loader:index');
function needsArray(value) {
return Array.isArray(value) ? value : [value];
}
module.exports = function(source) {
var self = this;
if (this.cacheable) {
this.cacheable();
}
var done = this.async();
var options = loaderUtils.parseQuery(this.query);
options.dest = options.dest || '';
options.filename = options.filename || this.resourcePath;
options.Evaluator = CachedPathEvaluator;
// Attach `importCache` to `options` so that the `Evaluator` can access it.
var importCache = options.importCache = new ImportCache(this, options);
var configKey = options.config || 'stylus';
var stylusOptions = this.options[configKey] || {};
// Handle `use` ahead of time for Stylus, otherwise it will try to call
// each plugin on every render attempt.
var use = needsArray(options.use || stylusOptions.use || []);
options.use = [];
options.import = options.import || stylusOptions.import || [];
options.include = options.include || stylusOptions.include || [];
options.set = options.set || stylusOptions.set || {};
options.define = options.define || stylusOptions.define || {};
if (options.sourceMap != null) {
options.sourcemap = options.sourceMap;
delete options.sourceMap;
} else if (this.sourceMap) {
options.sourcemap = { comment: false };
}
var styl = stylus(source, options);
var paths = [path.dirname(options.filename)];
if (options.paths && !Array.isArray(options.paths)) {
paths = paths.concat(options.paths);
options.paths = [options.paths];
}
needsArray(use).forEach(function(plugin) {
if (typeof plugin === 'function') {
styl.use(plugin);
} else {
throw new Error('Plugin should be a function');
}
});
Object.keys(options).forEach(function(key) {
var value = options[key];
if (key === 'set') {
for (var name in value) {
styl.set(name, value[name]);
}
} else if (key === 'define') {
for (var defineName in value) {
styl.define(defineName, value[defineName]);
}
} else if (key === 'include') {
needsArray(value).forEach(function(includePath) {
styl.include(includePath);
});
} else if (key === 'import') {
needsArray(value).forEach(function(file) {
styl.import(file);
});
} else {
styl.set(key, value);
if (key === 'resolve url' && value) {
styl.define('url', resolver());
}
}
});
// `styl.render`, promisified.
var renderStylus = function() {
return new Promise(function(resolve, reject) {
styl.render(function(err, css) {
return err ? reject(err) : resolve(css);
});
});
};
var attempt = 0;
function tryRender() {
attempt += 1;
return renderStylus().then(function(css) {
return {
css: css,
sourcemap: styl.sourcemap
};
}).catch(function(err) {
debug('Error: %s', err);
return importCache.handleUnresolvedImport(err).then(tryRender);
});
}
// Visit this base file before even attempting to render, so we can already
// have a bunch of imports in the cache.
importCache.enqueueVisit(options.filename, source);
debug('Starting: %s', options.filename);
importCache.flushQueues().then(function() {
return tryRender().then(function(result) {
// Tell `webpack` about all the dependencies found during render.
importCache.getDependencies().forEach(function(file) {
self.addDependency(file);
});
debug('Render attempts: %s', attempt);
done(null, result.css, result.sourcemap);
});
}).catch(done);
};