You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
4.0 KiB

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