index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. 'use strict';
  2. var fs = require('fs');
  3. var path = require('path');
  4. Object.defineProperty(exports, 'commentRegex', {
  5. get: function getCommentRegex () {
  6. return /^\s*\/(?:\/|\*)[@#]\s+sourceMappingURL=data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(?:.*)$/mg;
  7. }
  8. });
  9. Object.defineProperty(exports, 'mapFileCommentRegex', {
  10. get: function getMapFileCommentRegex () {
  11. // Matches sourceMappingURL in either // or /* comment styles.
  12. return /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"`]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/){1}[ \t]*$)/mg;
  13. }
  14. });
  15. function decodeBase64(base64) {
  16. return new Buffer(base64, 'base64').toString();
  17. }
  18. function stripComment(sm) {
  19. return sm.split(',').pop();
  20. }
  21. function readFromFileMap(sm, dir) {
  22. // NOTE: this will only work on the server since it attempts to read the map file
  23. var r = exports.mapFileCommentRegex.exec(sm);
  24. // for some odd reason //# .. captures in 1 and /* .. */ in 2
  25. var filename = r[1] || r[2];
  26. var filepath = path.resolve(dir, filename);
  27. try {
  28. return fs.readFileSync(filepath, 'utf8');
  29. } catch (e) {
  30. throw new Error('An error occurred while trying to read the map file at ' + filepath + '\n' + e);
  31. }
  32. }
  33. function Converter (sm, opts) {
  34. opts = opts || {};
  35. if (opts.isFileComment) sm = readFromFileMap(sm, opts.commentFileDir);
  36. if (opts.hasComment) sm = stripComment(sm);
  37. if (opts.isEncoded) sm = decodeBase64(sm);
  38. if (opts.isJSON || opts.isEncoded) sm = JSON.parse(sm);
  39. this.sourcemap = sm;
  40. }
  41. Converter.prototype.toJSON = function (space) {
  42. return JSON.stringify(this.sourcemap, null, space);
  43. };
  44. Converter.prototype.toBase64 = function () {
  45. var json = this.toJSON();
  46. return new Buffer(json).toString('base64');
  47. };
  48. Converter.prototype.toComment = function (options) {
  49. var base64 = this.toBase64();
  50. var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
  51. return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
  52. };
  53. // returns copy instead of original
  54. Converter.prototype.toObject = function () {
  55. return JSON.parse(this.toJSON());
  56. };
  57. Converter.prototype.addProperty = function (key, value) {
  58. if (this.sourcemap.hasOwnProperty(key)) throw new Error('property "' + key + '" already exists on the sourcemap, use set property instead');
  59. return this.setProperty(key, value);
  60. };
  61. Converter.prototype.setProperty = function (key, value) {
  62. this.sourcemap[key] = value;
  63. return this;
  64. };
  65. Converter.prototype.getProperty = function (key) {
  66. return this.sourcemap[key];
  67. };
  68. exports.fromObject = function (obj) {
  69. return new Converter(obj);
  70. };
  71. exports.fromJSON = function (json) {
  72. return new Converter(json, { isJSON: true });
  73. };
  74. exports.fromBase64 = function (base64) {
  75. return new Converter(base64, { isEncoded: true });
  76. };
  77. exports.fromComment = function (comment) {
  78. comment = comment
  79. .replace(/^\/\*/g, '//')
  80. .replace(/\*\/$/g, '');
  81. return new Converter(comment, { isEncoded: true, hasComment: true });
  82. };
  83. exports.fromMapFileComment = function (comment, dir) {
  84. return new Converter(comment, { commentFileDir: dir, isFileComment: true, isJSON: true });
  85. };
  86. // Finds last sourcemap comment in file or returns null if none was found
  87. exports.fromSource = function (content) {
  88. var m = content.match(exports.commentRegex);
  89. return m ? exports.fromComment(m.pop()) : null;
  90. };
  91. // Finds last sourcemap comment in file or returns null if none was found
  92. exports.fromMapFileSource = function (content, dir) {
  93. var m = content.match(exports.mapFileCommentRegex);
  94. return m ? exports.fromMapFileComment(m.pop(), dir) : null;
  95. };
  96. exports.removeComments = function (src) {
  97. return src.replace(exports.commentRegex, '');
  98. };
  99. exports.removeMapFileComments = function (src) {
  100. return src.replace(exports.mapFileCommentRegex, '');
  101. };
  102. exports.generateMapFileComment = function (file, options) {
  103. var data = 'sourceMappingURL=' + file;
  104. return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
  105. };