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.
79 lines
2.1 KiB
79 lines
2.1 KiB
'use strict'; |
|
|
|
const path = require('path'); |
|
const os = require('os'); |
|
const fs = require('fs'); |
|
|
|
// A typical sass error looks like this |
|
// const SassError = { |
|
// message: "invalid property name", |
|
// column: 14, |
|
// line: 1, |
|
// file: "stdin", |
|
// status: 1 |
|
// }; |
|
|
|
/** |
|
* Enhances the sass error with additional information about what actually went wrong. |
|
* |
|
* @param {SassError} err |
|
* @param {string} resourcePath |
|
*/ |
|
function formatSassError(err, resourcePath) { |
|
// Instruct webpack to hide the JS stack from the console |
|
// Usually you're only interested in the SASS stack in this case. |
|
// eslint-disable-next-line no-param-reassign |
|
err.hideStack = true; |
|
|
|
// The file property is missing in rare cases. |
|
// No improvement in the error is possible. |
|
if (!err.file) { |
|
return; |
|
} |
|
|
|
let msg = err.message; |
|
|
|
if (err.file === 'stdin') { |
|
// eslint-disable-next-line no-param-reassign |
|
err.file = resourcePath; |
|
} |
|
|
|
// node-sass returns UNIX-style paths |
|
// eslint-disable-next-line no-param-reassign |
|
err.file = path.normalize(err.file); |
|
|
|
// The 'Current dir' hint of node-sass does not help us, we're providing |
|
// additional information by reading the err.file property |
|
msg = msg.replace(/\s*Current dir:\s*/, ''); |
|
|
|
// eslint-disable-next-line no-param-reassign |
|
err.message = `${getFileExcerptIfPossible(err) + |
|
msg.charAt(0).toUpperCase() + |
|
msg.slice(1) + |
|
os.EOL} in ${err.file} (line ${err.line}, column ${err.column})`; |
|
} |
|
|
|
/** |
|
* Tries to get an excerpt of the file where the error happened. |
|
* Uses err.line and err.column. |
|
* |
|
* Returns an empty string if the excerpt could not be retrieved. |
|
* |
|
* @param {SassError} err |
|
* @returns {string} |
|
*/ |
|
function getFileExcerptIfPossible(err) { |
|
try { |
|
const content = fs.readFileSync(err.file, 'utf8'); |
|
|
|
return `${os.EOL + |
|
content.split(os.EOL)[err.line - 1] + |
|
os.EOL + |
|
new Array(err.column - 1).join(' ')}^${os.EOL} `; |
|
} catch (ignoreErr) { |
|
// If anything goes wrong here, we don't want any errors to be reported to the user |
|
return ''; |
|
} |
|
} |
|
|
|
module.exports = formatSassError;
|
|
|