source-reader.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. var path = require('path');
  2. var rewriteUrls = require('../urls/rewrite');
  3. var REMOTE_RESOURCE = /^(https?:)?\/\//;
  4. function SourceReader(context, data) {
  5. this.outerContext = context;
  6. this.data = data;
  7. this.sources = {};
  8. }
  9. SourceReader.prototype.sourceAt = function (path) {
  10. return this.sources[path];
  11. };
  12. SourceReader.prototype.trackSource = function (path, source) {
  13. this.sources[path] = {};
  14. this.sources[path][path] = source;
  15. };
  16. SourceReader.prototype.toString = function () {
  17. if (typeof this.data == 'string')
  18. return fromString(this);
  19. if (Buffer.isBuffer(this.data))
  20. return fromBuffer(this);
  21. if (Array.isArray(this.data))
  22. return fromArray(this);
  23. return fromHash(this);
  24. };
  25. function fromString(self) {
  26. var data = self.data;
  27. self.trackSource(undefined, data);
  28. return data;
  29. }
  30. function fromBuffer(self) {
  31. var data = self.data.toString();
  32. self.trackSource(undefined, data);
  33. return data;
  34. }
  35. function fromArray(self) {
  36. return self.data
  37. .map(function (source) {
  38. return self.outerContext.options.processImport === false ?
  39. source + '@shallow' :
  40. source;
  41. })
  42. .map(function (source) {
  43. return !self.outerContext.options.relativeTo || /^https?:\/\//.test(source) ?
  44. source :
  45. path.relative(self.outerContext.options.relativeTo, source);
  46. })
  47. .map(function (source) { return '@import url(' + source + ');'; })
  48. .join('');
  49. }
  50. function fromHash(self) {
  51. var data = [];
  52. var toBase = path.resolve(self.outerContext.options.target || self.outerContext.options.root);
  53. for (var source in self.data) {
  54. var styles = self.data[source].styles;
  55. var inputSourceMap = self.data[source].sourceMap;
  56. var isRemote = REMOTE_RESOURCE.test(source);
  57. var absoluteSource = isRemote ? source : path.resolve(source);
  58. var absoluteSourcePath = path.dirname(absoluteSource);
  59. var rewriteOptions = {
  60. absolute: self.outerContext.options.explicitRoot,
  61. relative: !self.outerContext.options.explicitRoot,
  62. imports: true,
  63. rebase: self.outerContext.options.rebase,
  64. fromBase: absoluteSourcePath,
  65. toBase: isRemote ? absoluteSourcePath : toBase,
  66. urlQuotes: self.outerContext.options.compatibility.properties.urlQuotes
  67. };
  68. styles = rewriteUrls(styles, rewriteOptions, self.outerContext);
  69. self.trackSource(source, styles);
  70. styles = self.outerContext.sourceTracker.store(source, styles);
  71. // here we assume source map lies in the same directory as `source` does
  72. if (self.outerContext.options.sourceMap && inputSourceMap)
  73. self.outerContext.inputSourceMapTracker.trackLoaded(source, source, inputSourceMap);
  74. data.push(styles);
  75. }
  76. return data.join('');
  77. }
  78. module.exports = SourceReader;