less-error.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var tslib_1 = require("tslib");
  4. var utils = tslib_1.__importStar(require("./utils"));
  5. var anonymousFunc = /(<anonymous>|Function):(\d+):(\d+)/;
  6. /**
  7. * This is a centralized class of any error that could be thrown internally (mostly by the parser).
  8. * Besides standard .message it keeps some additional data like a path to the file where the error
  9. * occurred along with line and column numbers.
  10. *
  11. * @class
  12. * @extends Error
  13. * @type {module.LessError}
  14. *
  15. * @prop {string} type
  16. * @prop {string} filename
  17. * @prop {number} index
  18. * @prop {number} line
  19. * @prop {number} column
  20. * @prop {number} callLine
  21. * @prop {number} callExtract
  22. * @prop {string[]} extract
  23. *
  24. * @param {Object} e - An error object to wrap around or just a descriptive object
  25. * @param {Object} fileContentMap - An object with file contents in 'contents' property (like importManager) @todo - move to fileManager?
  26. * @param {string} [currentFilename]
  27. */
  28. var LessError = function (e, fileContentMap, currentFilename) {
  29. Error.call(this);
  30. var filename = e.filename || currentFilename;
  31. this.message = e.message;
  32. this.stack = e.stack;
  33. if (fileContentMap && filename) {
  34. var input = fileContentMap.contents[filename];
  35. var loc = utils.getLocation(e.index, input);
  36. var line = loc.line;
  37. var col = loc.column;
  38. var callLine = e.call && utils.getLocation(e.call, input).line;
  39. var lines = input ? input.split('\n') : '';
  40. this.type = e.type || 'Syntax';
  41. this.filename = filename;
  42. this.index = e.index;
  43. this.line = typeof line === 'number' ? line + 1 : null;
  44. this.column = col;
  45. if (!this.line && this.stack) {
  46. var found = this.stack.match(anonymousFunc);
  47. /**
  48. * We have to figure out how this environment stringifies anonymous functions
  49. * so we can correctly map plugin errors.
  50. *
  51. * Note, in Node 8, the output of anonymous funcs varied based on parameters
  52. * being present or not, so we inject dummy params.
  53. */
  54. var func = new Function('a', 'throw new Error()');
  55. var lineAdjust = 0;
  56. try {
  57. func();
  58. }
  59. catch (e) {
  60. var match = e.stack.match(anonymousFunc);
  61. lineAdjust = 1 - parseInt(match[2]);
  62. }
  63. if (found) {
  64. if (found[2]) {
  65. this.line = parseInt(found[2]) + lineAdjust;
  66. }
  67. if (found[3]) {
  68. this.column = parseInt(found[3]);
  69. }
  70. }
  71. }
  72. this.callLine = callLine + 1;
  73. this.callExtract = lines[callLine];
  74. this.extract = [
  75. lines[this.line - 2],
  76. lines[this.line - 1],
  77. lines[this.line]
  78. ];
  79. }
  80. };
  81. if (typeof Object.create === 'undefined') {
  82. var F = function () { };
  83. F.prototype = Error.prototype;
  84. LessError.prototype = new F();
  85. }
  86. else {
  87. LessError.prototype = Object.create(Error.prototype);
  88. }
  89. LessError.prototype.constructor = LessError;
  90. /**
  91. * An overridden version of the default Object.prototype.toString
  92. * which uses additional information to create a helpful message.
  93. *
  94. * @param {Object} options
  95. * @returns {string}
  96. */
  97. LessError.prototype.toString = function (options) {
  98. options = options || {};
  99. var message = '';
  100. var extract = this.extract || [];
  101. var error = [];
  102. var stylize = function (str) { return str; };
  103. if (options.stylize) {
  104. var type = typeof options.stylize;
  105. if (type !== 'function') {
  106. throw Error("options.stylize should be a function, got a ".concat(type, "!"));
  107. }
  108. stylize = options.stylize;
  109. }
  110. if (this.line !== null) {
  111. if (typeof extract[0] === 'string') {
  112. error.push(stylize("".concat(this.line - 1, " ").concat(extract[0]), 'grey'));
  113. }
  114. if (typeof extract[1] === 'string') {
  115. var errorTxt = "".concat(this.line, " ");
  116. if (extract[1]) {
  117. errorTxt += extract[1].slice(0, this.column) +
  118. stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') +
  119. extract[1].slice(this.column + 1), 'red'), 'inverse');
  120. }
  121. error.push(errorTxt);
  122. }
  123. if (typeof extract[2] === 'string') {
  124. error.push(stylize("".concat(this.line + 1, " ").concat(extract[2]), 'grey'));
  125. }
  126. error = "".concat(error.join('\n') + stylize('', 'reset'), "\n");
  127. }
  128. message += stylize("".concat(this.type, "Error: ").concat(this.message), 'red');
  129. if (this.filename) {
  130. message += stylize(' in ', 'red') + this.filename;
  131. }
  132. if (this.line) {
  133. message += stylize(" on line ".concat(this.line, ", column ").concat(this.column + 1, ":"), 'grey');
  134. }
  135. message += "\n".concat(error);
  136. if (this.callLine) {
  137. message += "".concat(stylize('from ', 'red') + (this.filename || ''), "/n");
  138. message += "".concat(stylize(this.callLine, 'grey'), " ").concat(this.callExtract, "/n");
  139. }
  140. return message;
  141. };
  142. exports.default = LessError;
  143. //# sourceMappingURL=less-error.js.map