index.js 4.0 KB

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