source-map-output.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. module.exports = function (environment) {
  2. var SourceMapOutput = function (options) {
  3. this._css = [];
  4. this._rootNode = options.rootNode;
  5. this._contentsMap = options.contentsMap;
  6. this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;
  7. if (options.sourceMapFilename) {
  8. this._sourceMapFilename = options.sourceMapFilename.replace(/\\/g, '/');
  9. }
  10. this._outputFilename = options.outputFilename;
  11. this.sourceMapURL = options.sourceMapURL;
  12. if (options.sourceMapBasepath) {
  13. this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/');
  14. }
  15. if (options.sourceMapRootpath) {
  16. this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
  17. if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
  18. this._sourceMapRootpath += '/';
  19. }
  20. } else {
  21. this._sourceMapRootpath = "";
  22. }
  23. this._outputSourceFiles = options.outputSourceFiles;
  24. this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator();
  25. this._lineNumber = 0;
  26. this._column = 0;
  27. };
  28. SourceMapOutput.prototype.normalizeFilename = function(filename) {
  29. filename = filename.replace(/\\/g, '/');
  30. if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
  31. filename = filename.substring(this._sourceMapBasepath.length);
  32. if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
  33. filename = filename.substring(1);
  34. }
  35. }
  36. return (this._sourceMapRootpath || "") + filename;
  37. };
  38. SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
  39. //ignore adding empty strings
  40. if (!chunk) {
  41. return;
  42. }
  43. var lines,
  44. sourceLines,
  45. columns,
  46. sourceColumns,
  47. i;
  48. if (fileInfo) {
  49. var inputSource = this._contentsMap[fileInfo.filename];
  50. // remove vars/banner added to the top of the file
  51. if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
  52. // adjust the index
  53. index -= this._contentsIgnoredCharsMap[fileInfo.filename];
  54. if (index < 0) { index = 0; }
  55. // adjust the source
  56. inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
  57. }
  58. inputSource = inputSource.substring(0, index);
  59. sourceLines = inputSource.split("\n");
  60. sourceColumns = sourceLines[sourceLines.length - 1];
  61. }
  62. lines = chunk.split("\n");
  63. columns = lines[lines.length - 1];
  64. if (fileInfo) {
  65. if (!mapLines) {
  66. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
  67. original: { line: sourceLines.length, column: sourceColumns.length},
  68. source: this.normalizeFilename(fileInfo.filename)});
  69. } else {
  70. for (i = 0; i < lines.length; i++) {
  71. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
  72. original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
  73. source: this.normalizeFilename(fileInfo.filename)});
  74. }
  75. }
  76. }
  77. if (lines.length === 1) {
  78. this._column += columns.length;
  79. } else {
  80. this._lineNumber += lines.length - 1;
  81. this._column = columns.length;
  82. }
  83. this._css.push(chunk);
  84. };
  85. SourceMapOutput.prototype.isEmpty = function() {
  86. return this._css.length === 0;
  87. };
  88. SourceMapOutput.prototype.toCSS = function(context) {
  89. this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
  90. if (this._outputSourceFiles) {
  91. for (var filename in this._contentsMap) {
  92. if (this._contentsMap.hasOwnProperty(filename)) {
  93. var source = this._contentsMap[filename];
  94. if (this._contentsIgnoredCharsMap[filename]) {
  95. source = source.slice(this._contentsIgnoredCharsMap[filename]);
  96. }
  97. this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
  98. }
  99. }
  100. }
  101. this._rootNode.genCSS(context, this);
  102. if (this._css.length > 0) {
  103. var sourceMapURL,
  104. sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
  105. if (this.sourceMapURL) {
  106. sourceMapURL = this.sourceMapURL;
  107. } else if (this._sourceMapFilename) {
  108. sourceMapURL = this._sourceMapFilename;
  109. }
  110. this.sourceMapURL = sourceMapURL;
  111. this.sourceMap = sourceMapContent;
  112. }
  113. return this._css.join('');
  114. };
  115. return SourceMapOutput;
  116. };