formatSassError.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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 = {
  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. // eslint-disable-next-line no-param-reassign
  23. err.hideStack = true;
  24. // The file property is missing in rare cases.
  25. // No improvement in the error is possible.
  26. if (!err.file) {
  27. return;
  28. }
  29. let msg = err.message;
  30. if (err.file === 'stdin') {
  31. // eslint-disable-next-line no-param-reassign
  32. err.file = resourcePath;
  33. }
  34. // node-sass returns UNIX-style paths
  35. // eslint-disable-next-line no-param-reassign
  36. err.file = path.normalize(err.file);
  37. // The 'Current dir' hint of node-sass does not help us, we're providing
  38. // additional information by reading the err.file property
  39. msg = msg.replace(/\s*Current dir:\s*/, '');
  40. // eslint-disable-next-line no-param-reassign
  41. err.message = `${getFileExcerptIfPossible(err) +
  42. msg.charAt(0).toUpperCase() +
  43. msg.slice(1) +
  44. os.EOL} in ${err.file} (line ${err.line}, column ${err.column})`;
  45. }
  46. /**
  47. * Tries to get an excerpt of the file where the error happened.
  48. * Uses err.line and err.column.
  49. *
  50. * Returns an empty string if the excerpt could not be retrieved.
  51. *
  52. * @param {SassError} err
  53. * @returns {string}
  54. */
  55. function getFileExcerptIfPossible(err) {
  56. try {
  57. const content = fs.readFileSync(err.file, 'utf8');
  58. return `${os.EOL +
  59. content.split(os.EOL)[err.line - 1] +
  60. os.EOL +
  61. new Array(err.column - 1).join(' ')}^${os.EOL} `;
  62. } catch (ignoreErr) {
  63. // If anything goes wrong here, we don't want any errors to be reported to the user
  64. return '';
  65. }
  66. }
  67. module.exports = formatSassError;