resolver.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /**
  2. * Module dependencies.
  3. */
  4. var Compiler = require('../visitor/compiler')
  5. , nodes = require('../nodes')
  6. , parse = require('url').parse
  7. , relative = require('path').relative
  8. , join = require('path').join
  9. , dirname = require('path').dirname
  10. , extname = require('path').extname
  11. , sep = require('path').sep;
  12. /**
  13. * Return a url() function which resolves urls.
  14. *
  15. * Options:
  16. *
  17. * - `paths` resolution path(s), merged with general lookup paths
  18. * - `nocheck` don't check file existence
  19. *
  20. * Examples:
  21. *
  22. * stylus(str)
  23. * .set('filename', __dirname + '/css/test.styl')
  24. * .define('url', stylus.resolver({ nocheck: true }))
  25. * .render(function(err, css){ ... })
  26. *
  27. * @param {Object} [options]
  28. * @return {Function}
  29. * @api public
  30. */
  31. module.exports = function(options) {
  32. options = options || {};
  33. function resolver(url) {
  34. // Compile the url
  35. var compiler = new Compiler(url)
  36. , filename = url.filename;
  37. compiler.isURL = true;
  38. url = parse(url.nodes.map(function(node){
  39. return compiler.visit(node);
  40. }).join(''));
  41. // Parse literal
  42. var literal = new nodes.Literal('url("' + url.href + '")')
  43. , path = url.pathname
  44. , dest = this.options.dest
  45. , tail = ''
  46. , res;
  47. // Absolute or hash
  48. if (url.protocol || !path || '/' == path[0]) return literal;
  49. // Check that file exists
  50. if (!options.nocheck) {
  51. var _paths = options.paths || [];
  52. path = require('../utils').lookup(path, _paths.concat(this.paths));
  53. if (!path) return literal;
  54. }
  55. if (this.includeCSS && extname(path) == '.css')
  56. return new nodes.Literal(url.href);
  57. if (url.search) tail += url.search;
  58. if (url.hash) tail += url.hash;
  59. if (dest && extname(dest) == '.css')
  60. dest = dirname(dest);
  61. res = relative(dest || dirname(this.filename), options.nocheck
  62. ? join(dirname(filename), path)
  63. : path) + tail;
  64. if ('\\' == sep) res = res.replace(/\\/g, '/');
  65. return new nodes.Literal('url("' + res + '")');
  66. };
  67. // Expose options to Evaluator
  68. resolver.options = options;
  69. resolver.raw = true;
  70. return resolver;
  71. };