diff options
Diffstat (limited to 'node_modules/stylus-loader')
| -rw-r--r-- | node_modules/stylus-loader/LICENSE | 22 | ||||
| -rw-r--r-- | node_modules/stylus-loader/README.md | 232 | ||||
| -rw-r--r-- | node_modules/stylus-loader/index.js | 221 | ||||
| -rw-r--r-- | node_modules/stylus-loader/lib/evaluator.js | 166 | ||||
| -rw-r--r-- | node_modules/stylus-loader/lib/listimports.js | 80 | ||||
| -rw-r--r-- | node_modules/stylus-loader/lib/pathcache.js | 304 | ||||
| -rw-r--r-- | node_modules/stylus-loader/lib/resolver.js | 112 | ||||
| l--------- | node_modules/stylus-loader/node_modules/.bin/stylus | 1 | ||||
| -rw-r--r-- | node_modules/stylus-loader/package.json | 53 |
9 files changed, 1191 insertions, 0 deletions
diff --git a/node_modules/stylus-loader/LICENSE b/node_modules/stylus-loader/LICENSE new file mode 100644 index 00000000..0733a63c --- /dev/null +++ b/node_modules/stylus-loader/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2018 Kyle Robinson Young + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/stylus-loader/README.md b/node_modules/stylus-loader/README.md new file mode 100644 index 00000000..6c444730 --- /dev/null +++ b/node_modules/stylus-loader/README.md @@ -0,0 +1,232 @@ +# stylus-loader +A [stylus](http://learnboost.github.io/stylus/) loader for [webpack](https://github.com/webpack/webpack). + +[](https://travis-ci.org/shama/stylus-loader) +[](https://badge.fury.io/js/stylus-loader) + +## Install + +`npm install stylus-loader stylus --save-dev` + +**Important**: in order to have ability use any `stylus` package version, +it won't be installed automatically. So it's required to +add it to `package.json` along with `stylus-loader`. + +The latest version supporting webpack 1 can be installed with: + +`npm install stylus-loader@webpack1 stylus --save-dev` + +## Usage + +```js +var css = require('!raw!stylus!./file.styl'); // Just the CSS +var css = require('!css!stylus!./file.styl'); // CSS with processed url(...)s +``` + +See [css-loader](https://github.com/webpack/css-loader) to see the effect of processed `url(...)`s. + +Or within the webpack config: + +```js +module: { + loaders: [{ + test: /\.styl$/, + loader: 'css-loader!stylus-loader?paths=node_modules/bootstrap-stylus/stylus/' + }] +} +``` + +Then you can: `var css = require('./file.styl');`. + +Use in tandem with the [style-loader](https://github.com/webpack/style-loader) to add the css rules to your `document`: + +```js +module: { + loaders: [ + { test: /\.styl$/, loader: 'style-loader!css-loader!stylus-loader' } + ] +} +``` + +and then `require('./file.styl');` will compile and add the CSS to your page. + +`stylus-loader` can also take advantage of webpack's resolve options. With the default options it'll find files in `web_modules` as well as `node_modules`, make sure to prefix any lookup in node_modules with `~`. For example if you have a styles package lookup files in it like `@import '~styles/my-styles`. It can also find stylus files without having the extension specified in the `@import` and index files in folders if webpack is configured for stylus's file extension. + +```js +module: { + resolve: { + extensions: ['', '.js', '.styl'] + } +} +``` + +will let you have an `index.styl` file in your styles package and `require('styles')` or `@import '~styles'` it. It also lets you load a stylus file from a package installed in node_modules or if you add a modulesDirectories, like `modulesDirectories: ['node_modules', 'web_modules', 'bower_components']` option you could load from a folder like bower_components. To load files from a relative path leave off the `~` and `@import 'relative-styles/my-styles';` it. + +Be careful though not to use the extensions configuration for two types of in one folder. If a folder has a `index.js` and a `index.styl` and you `@import './that-folder'`, it'll end up importing a javascript file into your stylus. + +### Stylus Plugins + +You can also use stylus plugins by adding an extra `stylus` section to your `webpack.config.js`. + +```js +var stylus_plugin = require('stylus_plugin'); +module: { + loaders: [ + { test: /\.styl$/, loader: 'style-loader!css-loader!stylus-loader' } + ] +}, +stylus: { + use: [stylus_plugin()] +} +``` + +Multiple configs can be used by giving other configs different names and referring to the with the `config` query option. + + +```js +var stylus_plugin = require('stylus_plugin'); +module: { + loaders: [ + { + test: /\.other\.styl$/, + loader: 'style-loader!css-loader!stylus-loader?config=stylusOther' + } + ] +}, +stylusOther: { + use: [stylus_plugin()] +} +``` + +#### Webpack 2 + +Webpack 2 formalizes its options with a schema. Options can be provided to `stylus-loader` in the options field to `module.rules` or through LoaderOptionsPlugin or `stylus-loader`'s OptionsPlugin (a convenience wrapper around LoaderOptionsPlugin). + +Config through module rules: + +```js +module: { + rules: [ + { + test: /\.styl$/, + use: [ + 'style-loader', + 'css-loader', + { + loader: 'stylus-loader', + options: { + use: [stylus_plugin()], + }, + }, + ], + } + ], +}, +``` + +Config through LoaderOptionsPlugin: + +```js +module: { + rules: [ + { + test: /\.styl$/, + loader: 'style-loader!css-loader!stylus-loader', + }, + ], +}, +plugins: [ + new webpack.LoaderOptionsPlugin({ + test: /\.styl$/, + stylus: { + // You can have multiple stylus configs with other names and use them + // with `stylus-loader?config=otherConfig`. + default: { + use: [stylus_plugin()], + }, + otherConfig: { + use: [other_plugin()], + }, + }, + }), +], +``` + +Config through `stylus-loader`'s OptionsPlugin (convenience wrapper for LoaderOptionsPlugin): + +```js +plugins: [ + new stylusLoader.OptionsPlugin({ + default: { + use: [stylus_plugin()], + }, + }), +], +``` + +#### Using nib with stylus + +The easiest way of enabling `nib` is to import it in the stylus options: + +```js +stylus: { + use: [require('nib')()], + import: ['~nib/lib/nib/index.styl'] +} +``` + +where `~` resolves to `node_modules/` + +### Prefer webpack resolving + +`stylus-loader` currently prefers resolving paths with stylus's resovling utilities and then falling back to webpack when it can't find files. Use the `preferPathResolver` option with the value `'webpack'` to swap this. This has the benefit of using webpack's async resolving instead of stylus's sync resolving. If you have a lot of dependencies in your stylus files this'll let those dependencies be found in parallel. + +```js +stylus: { + preferPathResolver: 'webpack', +} +``` + +## Testing + +``` +npm test +open http://localhost:8080/test/ +``` + + +## Contributing +In lieu of a formal styleguide, take care to maintain the existing coding style. + +## Release History +* Please see https://github.com/shama/stylus-loader/releases +* 3.0.1 - Update install instructions mentioning how to get a version supporting webpack 1 (@mzgoddard) +* 3.0.0 - Fix loader-utils deprecation warning (@ryani33), Drop webpack 1 and Node<4 support (@mzgoddard) +* 2.5.1 - Fix paths mutation in options (@vio) +* 2.5.0 - Define paths in global stylusOptions, in addtion to query params (@JounQin) +* 2.4.0 - Add OptionsPlugin to help support webpack 2 (@mzgoddard) +* 2.3.1 - Fix typo in README (@stevewillard) +* 2.3.0 - Fix most use cases of relative path resolving (@mzgoddard), Add option to prefer a path resolver (webpack or stylus) (@mzgoddard) +* 2.2.0 - Let stylus use option be just a function (@yuffiy), Track json calls as imports like use calls (@gnarf) +* 2.1.2 - Fix support for stylus include config (@andrewburgess), Add block-level imports to listimports (@kenaniah) +* 2.1.1 - Support Node 6 (@yyx990803), Test in webpack 1 and 2 (@phyllisstein) +* 2.1.0 - Add support for stylus's include and set (@michaek) +* 2.0.1 - Add peer dependency on stylus (@jchitel), fix PathCache for webpack 2 (@Unhelpful) +* 2.0.0 - Remove dependency on stylus (@kossnocorps) +* 1.6.1 - Remove version breaking change in 1.6.0 +* 1.6.0 - Remove dependency on stylus (@kossnocorps) +* 1.3.0 - resolve use() calls (@mzgoddard), manual imports through path cache (@mzgoddard) +* 1.2.0 - files in package.json (@SimenB), test running with testem (@mzgoddard), and some performance changes (@mzgoddard) +* 1.1.0 - Pass through sourceMap option to stylus instead of defaulting to inline. Inherit source-map from devtool (@jordansexton). +* 1.0.0 - Basic source map support (@skozin). Remove nib as dep. stylus is now a direct dep (as peerDependencies are deprecated). +* 0.6.0 - Support loader prefixes when resolving paths (@kpdecker). +* 0.5.0 - Disable Stylus parser caching in listImports (@DaQuirm). Update to stylus@0.49.2 and nib@1.0.4 as peerDependencies (@kompot). +* 0.4.0 - Allow configuration of plugins through webpack config (@bobzoller). Update to stylus 0.47.2 (@shanewilson). +* 0.3.1 - Fix when dependency (@tkellen) +* 0.3.0 - Define url resolver() when "resolve url" option is true (@mzgoddard). +* 0.2.0 - Now tracks dependencies for @import statements making cacheable work. Update stylus dep. +* 0.1.0 - Initial release + +## License +Copyright (c) 2018 Kyle Robinson Young +Licensed under the MIT license. 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); +}; diff --git a/node_modules/stylus-loader/lib/evaluator.js b/node_modules/stylus-loader/lib/evaluator.js new file mode 100644 index 00000000..dc6013d8 --- /dev/null +++ b/node_modules/stylus-loader/lib/evaluator.js @@ -0,0 +1,166 @@ +// Except for a block in #visitImport, everything here is an exact copy of the +// source in stylus this currently depends on. If stylus is updated, update +// this appropriately. + +var Evaluator = require('stylus/lib/visitor/evaluator') + , nodes = require('stylus/lib/nodes') + , Stack = require('stylus/lib/stack') + , Frame = require('stylus/lib/stack/frame') + , Scope = require('stylus/lib/stack/scope') + , utils = require('stylus/lib/utils') + , bifs = require('stylus/lib/functions') + , basename = require('path').basename + , dirname = require('path').dirname + , relative = require('path').relative + , join = require('path').join + , colors = require('stylus/lib/colors') + // , debug = require('debug')('stylus:evaluator') + , fs = require('fs'); + +module.exports = CachedPathEvaluator; + +/** + * Import `file` and return Block node. + * + * @api private + */ +function importFile(node, file, literal, index) { + var importStack = this.importStack + , Parser = require('stylus/lib/parser') + , stat; + + // Handling the `require` + if (node.once) { + if (this.requireHistory[file]) return nodes.null; + this.requireHistory[file] = true; + + if (literal && !this.includeCSS) { + return node; + } + } + + // Expose imports + node.path = file; + node.dirname = dirname(file); + // Store the modified time + stat = fs.statSync(file); + node.mtime = stat.mtime; + this.paths.push(node.dirname); + + // Avoid overflows from importing the same file over again + if (file === importStack[importStack.length - 1]) return nodes.null; + + if (this.options._imports) this.options._imports.push(node.clone()); + + // Parse the file + importStack.push(file); + nodes.filename = file; + + var str; + if (this.cache.sources && this.cache.sources[file]) { + str = this.cache.sources[file]; + } else { + str = fs.readFileSync(file, 'utf8'); + } + + if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n')); + + // parse + var block = new nodes.Block + , parser = new Parser(str, utils.merge({ root: block }, this.options)); + + try { + block = parser.parse(); + } catch (err) { + err.filename = file; + err.lineno = parser.lexer.lineno; + err.input = str; + throw err; + } + + // Evaluate imported "root" + block.parent = this.root; + block.scope = false; + var ret = this.visit(block); + importStack.pop(); + if (importStack.length || index) this.paths.pop(); + + return ret; +} + +function CachedPathEvaluator(root, options) { + Evaluator.apply(this, arguments); + + this.cache = options.cache; +} + +CachedPathEvaluator.prototype = Object.create(Evaluator.prototype); +CachedPathEvaluator.prototype.constructor = CachedPathEvaluator; + +CachedPathEvaluator.prototype.visitImport = function(imported) { + this.return++; + + var path = this.visit(imported.path).first + , nodeName = imported.once ? 'require' : 'import' + , found + , literal + , index; + + this.return--; + // debug('import %s', path); + + // url() passed + if ('url' == path.name) { + if (imported.once) throw new Error('You cannot @require a url'); + + return imported; + } + + // Ensure string + if (!path.string) throw new Error('@' + nodeName + ' string expected'); + + var name = path = path.string; + + // Absolute URL + if (/url\s*\(\s*['"]?(?:https?:)?\/\//i.test(path)) { + if (imported.once) throw new Error('You cannot @require a url'); + return imported; + } + + // Literal + if (/\.css(?:"|$)/.test(path)) { + literal = true; + if (!imported.once && !this.includeCSS) { + return imported; + } + } + + // support optional .styl + if (!literal && !/\.styl$/i.test(path)) path += '.styl'; + + /***************************************************************************** + * THIS IS THE ONLY BLOCK THAT DIFFERS FROM THE ACTUAL STYLUS IMPLEMENTATION. * + *****************************************************************************/ + // Lookup + var dirname = this.paths[this.paths.length - 1]; + found = this.cache.find(path, dirname); + index = this.cache.isIndex(path, dirname); + if (!found) { + found = utils.find(path, this.paths, this.filename); + if (!found) { + found = utils.lookupIndex(name, this.paths, this.filename); + index = true; + } + } + + // Throw if import failed + if (!found) throw new Error('failed to locate @' + nodeName + ' file ' + path); + + var block = new nodes.Block; + + for (var i = 0, len = found.length; i < len; ++i) { + block.push(importFile.call(this, imported, found[i], literal, index)); + } + + return block; +} diff --git a/node_modules/stylus-loader/lib/listimports.js b/node_modules/stylus-loader/lib/listimports.js new file mode 100644 index 00000000..bcf9540f --- /dev/null +++ b/node_modules/stylus-loader/lib/listimports.js @@ -0,0 +1,80 @@ +var Parser = require('stylus/lib/parser'); +var Visitor = require('stylus/lib/visitor'); +var nodes = require('stylus/lib/nodes'); + +module.exports = listImports; + +// ImportVisitor is a simple stylus ast visitor that navigates the graph +// building a list of imports in it. +function ImportVisitor() { + Visitor.apply(this, arguments); + this.importPaths = []; +} + +ImportVisitor.prototype = Object.create(Visitor.prototype); +ImportVisitor.prototype.constructor = ImportVisitor; + +ImportVisitor.prototype.visitImport = function(node) { + this.importPaths.push(node.path.first.string); + return node; +}; + +ImportVisitor.prototype.visitRoot = function(block){ + for (var i = 0; i < block.nodes.length; ++i) { + this.visit(block.nodes[i]); + } + return block; +}; + +ImportVisitor.prototype.visitExpression = function(expr) { + for (var i = 0; i < expr.nodes.length; ++i) { + this.visit(expr.nodes[i]); + } + return expr; +}; + +ImportVisitor.prototype.visitCall = function(fn) { + if (fn.name === 'use' || fn.name === 'json') { + this.importPaths.push(fn.args.first.string); + } + return fn; +}; + +ImportVisitor.prototype.visitSelector = function(sel) { + for (var i = 0; i < sel.block.nodes.length; i++) { + this.visit(sel.block.nodes[i]); + } + return sel; +} + +ImportVisitor.prototype.visitBlock = ImportVisitor.prototype.visitRoot; +ImportVisitor.prototype.visitGroup = ImportVisitor.prototype.visitRoot; + +// Returns a list of paths that given source imports. +function listImports(source, options) { + // Store source -> imports work in a cache. The Parser is the most expensive + // part of stylus and we can't use their cache without creating undesired side + // effects later during the actual render. In single run builds this will + // benefit repeated files imported like common styling. In multiple run builds + // this will help stylus import trees when a dependency changes, the higher up + // files won't need to be parsed again. + var cache = options.cache; + if (cache && cache[source]) { return cache[source]; } + + // Current idea here is to silence errors and let them rise in stylus's + // renderer which has more handling so that the error message is more + // meaningful and easy to understand. + try { + var ast = new Parser(source, { cache: false }).parse(); + } catch (e) { + return []; + } + var importVisitor = new ImportVisitor(ast, {}); + importVisitor.visit(ast); + + if (cache) { + cache[source] = importVisitor.importPaths; + } + + return importVisitor.importPaths; +} diff --git a/node_modules/stylus-loader/lib/pathcache.js b/node_modules/stylus-loader/lib/pathcache.js new file mode 100644 index 00000000..5437cef9 --- /dev/null +++ b/node_modules/stylus-loader/lib/pathcache.js @@ -0,0 +1,304 @@ +var path = require('path'); +var fs = require('fs'); + +var Evaluator = require('stylus/lib/visitor/evaluator'); +var loaderUtils = require('loader-utils'); +var nodes = require('stylus/lib/nodes'); +var utils = require('stylus/lib/utils'); +var when = require('when'); +var whenNodefn = require('when/node/function'); + +var listImports = require('./listimports'); + +module.exports = PathCache; + +var readFile = whenNodefn.lift(fs.readFile); + +// A cache of import paths of a stylus file resolved to their location on disk +// before the stylus file is rendered. With a special evaluator this lets us +// webpack's resolver. +function PathCache(contexts, sources, imports) { + this.contexts = contexts; + this.sources = sources; + this.imports = imports; + + // Non relative paths are simpler and looked up in this as a fallback + // to this.context. + this.simpleContext = {}; + for (var dirname in this.contexts) { + for (var path in this.contexts[dirname]) { + this.simpleContext[path] = this.contexts[dirname][path]; + } + } +} + +// Return a promise for a PathCache. +PathCache.create = function(contexts, sources, imports) { + return when(new PathCache(contexts, sources, imports)); +}; +PathCache.createFromFile = resolveFileDeep; + +// Create a list of ways to resolve paths. +PathCache.resolvers = resolvers; + +PathCache.resolvers.reduce = reduceResolvers; + +// Lookup the path in this cache. +PathCache.prototype.find = function(path, dirname) { + if (this.contexts[dirname] && this.contexts[dirname][path]) { + return this.contexts[dirname][path].path; + } else if (this.simpleContext[path]) { + return this.simpleContext[path].path; + } else if (/.styl$/.test(path)) { + // A user can specify @import 'something.styl' but if they specify + // @import 'something' stylus adds .styl, we drop that here to see if we + // looked for it without .styl. + return this.find(path.replace(/.styl$/, ''), dirname); + } else { + return undefined; + } +}; + +// Return if the path in this cache is an index file. +PathCache.prototype.isIndex = function(path, dirname) { + if (this.contexts[dirname] && this.contexts[dirname][path]) { + return this.contexts[dirname][path].index; + } else { + return undefined; + } +}; + +// Return an array of all imports the original file depends on. +PathCache.prototype.allDeps = function() { + var deps = []; + for (var dirname in this.contexts) { + for (var path in this.contexts[dirname]) { + if (this.contexts[dirname][path]) { + deps = deps.concat(this.contexts[dirname][path].path); + } + } + } + return deps; +}; + +// Create an array of ways to resolve a path. +// +// The resolved paths may be a path or an object specifying path and index +// members. The index member is used later by stylus, we store it at this point. +function resolvers(options, webpackResolver) { + var evaluator = new Evaluator(nodes.null, options); + var whenWebpackResolver = whenNodefn.lift(webpackResolver); + + // Stylus's normal resolver for single files. + var stylusFile = function(context, path) { + // Stylus adds .styl to paths for normal "paths" lookup if it isn't there. + if (!/.styl$/.test(path)) { + path += '.styl'; + } + + var paths = options.paths.concat(context); + var found = utils.find(path, paths, options.filename) + if (found) { + return normalizePaths(found); + } + }; + + // Stylus's normal resolver for node_modules packages. Cannot locate paths + // inside a package. + var stylusIndex = function(context, path) { + // Stylus calls the argument name. If it exists it should match the name + // of a module in node_modules. + if (!path) { + return null; + } + + var paths = options.paths.concat(context); + var found = utils.lookupIndex(path, paths, options.filename); + if (found) { + return {path: normalizePaths(found), index: true}; + } + }; + + // Fallback to resolving with webpack's configured resovler. + var webpackResolve = function(context, path) { + // Follow the webpack stylesheet idiom of '~path' meaning a path in a + // modules folder and a unprefixed 'path' meaning a relative path like + // './path'. + path = loaderUtils.urlToRequest(path, options.root); + // First try with a '.styl' extension. + return whenWebpackResolver(context, path + '.styl') + // If the user adds ".styl" to resolve.extensions, webpack can find + // index files like stylus but it uses all of webpack's configuration, + // by default for example the module could be web_modules. + .catch(function() { return whenWebpackResolver(context, path); }) + .catch(function() { return null; }) + .then(function(result) { + return Array.isArray(result) && result[1] && result[1].path || result + }); + }; + + if (options.preferPathResolver === 'webpack') { + return [ + webpackResolve, + stylusFile, + stylusIndex + ]; + } + else { + return [ + stylusFile, + stylusIndex, + webpackResolve + ]; + } +} + +function reduceResolvers(resolvers, context, path) { + return when + .reduce(resolvers, function(result, resolver) { + return result ? result : resolver(context, path); + }, undefined); +} + +// Run resolvers on one path and return an object with the found path under a +// key of the original path. +// +// Example: +// resolving the path +// 'a/file' +// returns an object +// {'a/file': {path: ['node_modules/a/file'], index: true}} +function resolveOne(resolvers, context, path) { + return reduceResolvers(resolvers, context, path) + .then(function(result) { + result = typeof result === 'string' ? [result] : result; + result = Array.isArray(result) ? {path: result, index: false} : result; + var map = {}; + map[path] = result; + return map; + }); +} + +// Run the resolvers on an array of paths and return an object like resolveOne. +function resolveMany(resolvers, context, paths) { + return when + .map(paths, resolveOne.bind(null, resolvers, context)) + .then(function(maps) { + return maps.reduce(function(map, resolvedPaths) { + Object.keys(resolvedPaths).forEach(function(path) { + map[path] = resolvedPaths[path]; + }); + return map; + }, {}); + }); +} + +// Load a file at fullPath, resolve all of it's imports and report for those. +function resolveFileDeep(helpers, parentCache, source, fullPath) { + var resolvers = helpers.resolvers; + var readFile = helpers.readFile; + + var contexts = parentCache.contexts; + var sources = parentCache.sources; + + contexts = contexts || {}; + var nestResolve = resolveFileDeep.bind(null, helpers, parentCache, null); + var context = path.dirname(fullPath); + readFile = whenNodefn.lift(readFile); + + return when + .resolve(source || sources[fullPath] || readFile(fullPath)) + // Cast the buffer from the cached input file system to a string. + .then(String) + // Store the source so that the evaluator doesn't need to touch the + // file system. + .then(function(_source) { + sources[fullPath] = _source; + return _source; + }) + // Make sure the stylus functions/index.styl source is stored. + .then(partial(ensureFunctionsSource, sources)) + // List imports and use its cache. The source file is translated into a + // list of imports. Where the source file came from isn't important for the + // list. The where is added by resolveMany with the context and resolvers. + .then(partialRight(listImports, { cache: parentCache.imports })) + .then(resolveMany.bind(null, resolvers, context)) + .then(function(newPaths) { + // Contexts are the full path since multiple could be in the same folder + // but different deps. + contexts[context] = merge(contexts[context] || {}, newPaths); + return when.map(Object.keys(newPaths), function(key) { + var found = newPaths[key] && newPaths[key].path; + if (found) { + return when.map(found, nestResolve); + } + }); + }) + .then(function() { + return PathCache.create(contexts, sources, parentCache.imports); + }); +} + +// Resolve functions in a promise wrapper to catch any errors from resolving. +var functionsPath = + new when.Promise(function(resolve) { + resolve(require.resolve('stylus/lib/functions/index.styl')); + }) + .catch(function() { return ''; }); + +var functionsSource = functionsPath + .then(readFile) + .catch(function(error) { + // Ignore error if functions/index.styl doesn't exist. + if (error.code !== 'ENOENT') { + throw error; + } + return ''; + }) + .then(String); + +function ensureFunctionsSource(sources, source) { + if (!sources[functionsPath]) { + return functionsSource + .then(function(functionsSource) { + if (functionsSource) { + sources[functionsPath] = functionsSource; + } + }) + // Pass through the source given to this function. + .yield(source); + } + // Pass through the source given to this function. + return source; +} + +var slice = Array.prototype.slice.call.bind(Array.prototype.slice); + +function merge(a, b) { + var key; + for (key in b) { + a[key] = b[key]; + } + return a; +} + +function partial(fn) { + var args = slice(arguments, 1); + return function() { + return fn.apply(this, args.concat(slice(arguments))); + }; +} + +function partialRight(fn) { + var args = slice(arguments, 1); + return function() { + return fn.apply(this, slice(arguments).concat(args)); + }; +} + +function normalizePaths(paths) { + for(var i in paths) { + paths[i] = path.normalize(paths[i]); + } + return paths; +}
\ No newline at end of file diff --git a/node_modules/stylus-loader/lib/resolver.js b/node_modules/stylus-loader/lib/resolver.js new file mode 100644 index 00000000..c4cb0785 --- /dev/null +++ b/node_modules/stylus-loader/lib/resolver.js @@ -0,0 +1,112 @@ +// This implementation of the url resolver adds awareness for webpack loaders +/* + +Modified from the stylus implementation: + +(The MIT License) + +Copyright (c) 2010–2014 LearnBoost <dev@learnboost.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/*jshint laxcomma:true */ +var Stylus = require('stylus') + , Compiler = Stylus.Compiler + , nodes = Stylus.nodes + , utils = Stylus.utils + , parse = require('url').parse + , relative = require('path').relative + , dirname = require('path').dirname + , extname = require('path').extname + , sep = require('path').sep; + +/** + * Return a url() function with the given `options`. + * + * Options: + * + * - `paths` resolution path(s), merged with general lookup paths + * + * Examples: + * + * stylus(str) + * .set('filename', __dirname + '/css/test.styl') + * .define('url', stylus.resolver({ paths: [__dirname + '/public'] })) + * .render(function(err, css){ ... }) + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function(options) { + options = options || {}; + + var _paths = options.paths || []; + + function url(url) { + var paths = _paths.concat(this.paths), + filename = this.filename; + + // Compile the url + var compiler = new Compiler(url); + compiler.isURL = true; + url = url.nodes.map(function(node){ + return compiler.visit(node); + }).join(''); + + function resolveComponent(url) { + if (!url) { + return url; + } + + url = parse(url); + if (url.protocol) { + return url.href; + } + + // Lookup + var found = utils.lookup(url.pathname, paths, '', true); + if (!found) { + return url.href; + } + + var tail = ''; + if (url.search) { + tail += url.search; + } + if (url.hash) { + tail += url.hash; + } + + var res = relative(dirname(filename), found) + tail; + if ('\\' == sep) res = res.replace(/\\/g, '/'); + return res; + } + + var components = url.split(/!/g); + components = components.map(resolveComponent); + return new nodes.Literal('url("' + components.join('!') + '")'); + } + + url.raw = true; + return url; +}; diff --git a/node_modules/stylus-loader/node_modules/.bin/stylus b/node_modules/stylus-loader/node_modules/.bin/stylus new file mode 120000 index 00000000..52487a66 --- /dev/null +++ b/node_modules/stylus-loader/node_modules/.bin/stylus @@ -0,0 +1 @@ +../../../stylus/bin/stylus
\ No newline at end of file diff --git a/node_modules/stylus-loader/package.json b/node_modules/stylus-loader/package.json new file mode 100644 index 00000000..29a26b8b --- /dev/null +++ b/node_modules/stylus-loader/package.json @@ -0,0 +1,53 @@ +{ + "name": "stylus-loader", + "version": "3.0.2", + "description": "Stylus loader for webpack", + "main": "index.js", + "files": [ + "index.js", + "lib/" + ], + "scripts": { + "test": "testem ci", + "test-dev": "testem -l firefox", + "test-one": "testem ci -l firefox", + "test-build": "webpack --config test/webpack.config.js --output-path=test/tmp --output-filename=bundle.js" + }, + "author": "Kyle Robinson Young <kyle@dontkry.com> (http://dontkry.com)", + "license": "MIT", + "repository": { + "type": "git", + "url": "git@github.com:shama/stylus-loader.git" + }, + "bugs": { + "url": "https://github.com/shama/stylus-loader/issues" + }, + "dependencies": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + }, + "devDependencies": { + "benchmark": "^1.0.0", + "css-loader": "^0.14.0", + "mocha": "~2.1.0", + "mocha-loader": "^1.0.0", + "nib": "^1.0.4", + "node-libs-browser": "^0.5.2", + "raw-loader": "~0.5.1", + "should": "~4.6.1", + "style-loader": "^0.12.2", + "stylus": ">=0.52.4", + "testem": "^0.8.3", + "webpack": "^2.2.0", + "webpack-dev-server": "^2.0.0" + }, + "peerDependencies": { + "stylus": ">=0.52.4" + }, + "keywords": [ + "webpack", + "loader", + "stylus" + ] +} |
