formatSassError.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. "use strict";
  2. const path = require("path");
  3. const os = require("os");
  4. const fs = require("fs");
  5. // A typical sass error looks like this
  6. const SassError = { // eslint-disable-line no-unused-vars
  7. message: "invalid property name",
  8. column: 14,
  9. line: 1,
  10. file: "stdin",
  11. status: 1
  12. };
  13. /**
  14. * Enhances the sass error with additional information about what actually went wrong.
  15. *
  16. * @param {SassError} err
  17. * @param {string} resourcePath
  18. */
  19. function formatSassError(err, resourcePath) {
  20. // Instruct webpack to hide the JS stack from the console
  21. // Usually you're only interested in the SASS stack in this case.
  22. err.hideStack = true;
  23. // The file property is missing in rare cases.
  24. // No improvement in the error is possible.
  25. if (!err.file) {
  26. return;
  27. }
  28. let msg = err.message;
  29. if (err.file === "stdin") {
  30. err.file = resourcePath;
  31. }
  32. // node-sass returns UNIX-style paths
  33. err.file = path.normalize(err.file);
  34. // The 'Current dir' hint of node-sass does not help us, we're providing
  35. // additional information by reading the err.file property
  36. msg = msg.replace(/\s*Current dir:\s*/, "");
  37. err.message = getFileExcerptIfPossible(err) +
  38. msg.charAt(0).toUpperCase() + msg.slice(1) + os.EOL +
  39. " in " + err.file + " (line " + err.line + ", column " + err.column + ")";
  40. }
  41. /**
  42. * Tries to get an excerpt of the file where the error happened.
  43. * Uses err.line and err.column.
  44. *
  45. * Returns an empty string if the excerpt could not be retrieved.
  46. *
  47. * @param {SassError} err
  48. * @returns {string}
  49. */
  50. function getFileExcerptIfPossible(err) {
  51. try {
  52. const content = fs.readFileSync(err.file, "utf8");
  53. return os.EOL +
  54. content.split(os.EOL)[err.line - 1] + os.EOL +
  55. new Array(err.column - 1).join(" ") + "^" + os.EOL +
  56. " ";
  57. } catch (err) {
  58. // If anything goes wrong here, we don't want any errors to be reported to the user
  59. return "";
  60. }
  61. }
  62. module.exports = formatSassError;