diff options
Diffstat (limited to 'node_modules/stylus-loader/index.js')
| -rw-r--r-- | node_modules/stylus-loader/index.js | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/node_modules/stylus-loader/index.js b/node_modules/stylus-loader/index.js new file mode 100644 index 00000000..b8941ddf --- /dev/null +++ b/node_modules/stylus-loader/index.js @@ -0,0 +1,221 @@ +var loaderUtils = require('loader-utils'); +var stylus = require('stylus'); +var path = require('path'); +var fs = require('fs'); +var when = require('when'); +var whenNodefn = require('when/node/function'); +var cloneDeep = require('lodash.clonedeep'); + +var CachedPathEvaluator = require('./lib/evaluator'); +var PathCache = require('./lib/pathcache'); +var resolver = require('./lib/resolver'); + +var globalImportsCaches = {}; +module.exports = function(source) { + var self = this; + this.cacheable && this.cacheable(); + var done = this.async(); + var options = cloneDeep(loaderUtils.getOptions(this) || {}); + options.dest = options.dest || ''; + options.filename = options.filename || this.resourcePath; + options.Evaluator = CachedPathEvaluator; + + var configKey, stylusOptions; + if (this.stylus) { + configKey = options.config || 'default'; + stylusOptions = this.stylus[configKey] || {}; + } else if (this.options) { + configKey = options.config || 'stylus'; + stylusOptions = this.options[configKey] || {}; + } else { + stylusOptions = {}; + } + // Instead of assigning to options, we run them manually later so their side effects apply earlier for + // resolving paths. + var use = options.use || stylusOptions.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 || {}; + options.paths = options.paths || stylusOptions.paths; + + 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)]; + + function needsArray(value) { + return (Array.isArray(value)) ? value : [value]; + } + + if (options.paths && !Array.isArray(options.paths)) { + paths = paths.concat(options.paths); + options.paths = [options.paths]; + } + + var manualImports = []; + Object.keys(options).forEach(function(key) { + var value = options[key]; + if (key === 'use') { + needsArray(value).forEach(function(plugin) { + if (typeof plugin === 'function') { + styl.use(plugin); + } else { + throw new Error('Plugin should be a function'); + } + }); + } else 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(styl.include.bind(styl)); + } else if (key === 'import') { + needsArray(value).forEach(function(stylusModule) { + manualImports.push(stylusModule); + }); + } else { + styl.set(key, value); + + if (key === 'resolve url' && value) { + styl.define('url', resolver()); + } + } + }); + + var shouldCacheImports = stylusOptions.importsCache !== false; + + var importsCache; + if (stylusOptions.importsCache !== false) { + if (typeof stylusOptions.importsCache === 'object') { + importsCache = stylusOptions.importsCache; + } else { + if(!globalImportsCaches[configKey]) globalImportsCaches[configKey] = {}; + importsCache = globalImportsCaches[configKey]; + } + } + + // Use input file system's readFile if available. The normal webpack input + // file system is cached with entries purged when they are detected to be + // changed on disk by the watcher. + var readFile; + try { + var inputFileSystem = this._compiler.inputFileSystem; + readFile = inputFileSystem.readFile.bind(inputFileSystem); + } catch (error) { + readFile = fs.readFile; + } + + var boundResolvers = PathCache.resolvers(options, this.resolve); + var pathCacheHelpers = { + resolvers: boundResolvers, + readFile: readFile, + }; + + // Use plugins here so that resolve related side effects can be used while we resolve imports. + (Array.isArray(use) ? use : [use]).forEach(styl.use, styl); + + when + // Resolve manual imports like @import files. + .reduce(manualImports, function resolveManualImports(carry, filename) { + return PathCache.resolvers + .reduce(boundResolvers, path.dirname(options.filename), filename) + .then(function(paths) { return carry.concat(paths); }); + }, []) + // Resolve dependencies of + .then(function(paths) { + paths.forEach(styl.import.bind(styl)); + paths.forEach(self.addDependency); + + var readFile = whenNodefn.lift(pathCacheHelpers.readFile); + return when.reduce(paths, function(cache, filepath) { + return readFile(filepath) + .then(function(source) { + return PathCache.createFromFile( + pathCacheHelpers, cache, source.toString(), filepath + ); + }); + }, { + contexts: {}, + sources: {}, + imports: importsCache, + }); + }) + .then(function(cache) { + return PathCache + .createFromFile(pathCacheHelpers, cache, source, options.filename); + }) + .then(function(importPathCache) { + // CachedPathEvaluator will use this PathCache to find its dependencies. + options.cache = importPathCache; + importPathCache.allDeps().forEach(function(f) { + self.addDependency(path.normalize(f)); + }); + + // var paths = importPathCache.origins; + + styl.render(function(err, css) { + if (err) { + done(err); + } else { + if (styl.sourcemap) { + styl.sourcemap.sourcesContent = styl.sourcemap.sources.map(function (file) { + return importPathCache.sources[path.resolve(file)] + }); + } + done(null, css, styl.sourcemap); + } + }); + }) + .catch(done); +}; + +var LoaderOptionsPlugin = require('webpack').LoaderOptionsPlugin; + +// Webpack 2 plugin for setting options that'll be available to stylus-loader. +function OptionsPlugin(options) { + if (!LoaderOptionsPlugin) { + throw new Error( + 'webpack.LoaderOptionPlugin is not available. A newer version of webpack is needed.' + ); + } + var stylusOptions = {}; + var test = options.test || /\.styl$/; + var include = options.include; + var exclude = options.exclude; + + var loaderOptions = { + stylus: stylusOptions, + }; + for (var key in options) { + if (['test', 'include', 'exclude'].indexOf(key) === -1) { + stylusOptions[key] = options[key]; + } + } + if (test) { + loaderOptions.test = test; + } + if (include) { + loaderOptions.include = include; + } + if (exclude) { + loaderOptions.exclude = exclude; + } + this.plugin = new LoaderOptionsPlugin(loaderOptions); +}; + +module.exports.OptionsPlugin = OptionsPlugin; + +OptionsPlugin.prototype.apply = function(compiler) { + this.plugin.apply(compiler); +}; |
