diff --git a/lib/nodeSass/AutoFixer.js b/lib/nodeSass/AutoFixer.js index ea1c66ad..c36ec691 100644 --- a/lib/nodeSass/AutoFixer.js +++ b/lib/nodeSass/AutoFixer.js @@ -10,10 +10,12 @@ const cssCompiler = require('../css/compile'); const BaseRulesFixer = require('./BaseRulesFixer'); const ConditionaImportFixer = require('./ConditionalImportFixer'); const CommaRemovalFixer = require('./CommaRemovalFixer'); +const UndefinedVariableFixer = require('./UndefinedVariableFixer'); const CONDITIONAL_IMPORT = 'conditional-import'; const BASE_LEVEL_RULES = 'base-level-rules'; const POSSIBLE_WRONG_COMMA = 'possible-wrong-comma'; +const UNDEFINED_VARIABLE = 'undefined-variable'; class AutoFixer { /** @@ -75,13 +77,17 @@ class AutoFixer { const toFixFile = err.file === 'stdin' ? file : err.file; const commaRemovalFixer = new CommaRemovalFixer(dirname, toFixFile); files = await commaRemovalFixer.run(); + } else if (problem === UNDEFINED_VARIABLE) { + const toFixFile = err.file === 'stdin' ? file : err.file; + const fixer = new UndefinedVariableFixer(dirname, toFixFile); + files = await fixer.run(err.message); } this.parseChangedFiles(files); } else { const filePath = path.join(this.themePath, 'assets/scss', file + '.scss'); console.log("Couldn't determine and autofix the problem. Please fix it manually.".red); - console.log('Found trying compile file:'.red, filePath); - throw new Error(err); + console.log('Found trying to compile file:'.red, filePath); + throw new Error(err.formatted ? err.formatted : err); } } @@ -107,6 +113,9 @@ class AutoFixer { ) { return POSSIBLE_WRONG_COMMA; } + if (err.formatted.includes('Undefined variable')) { + return UNDEFINED_VARIABLE; + } } return null; diff --git a/lib/nodeSass/BaseRulesFixer.js b/lib/nodeSass/BaseRulesFixer.js index e983a888..2d7cfb51 100644 --- a/lib/nodeSass/BaseRulesFixer.js +++ b/lib/nodeSass/BaseRulesFixer.js @@ -16,7 +16,10 @@ class BaseRulesFixer extends BaseFixer { return { postcssPlugin: 'Transform Base Rules Issues into Comments', Rule(rule, { Comment }) { - if (rule.parent.type === 'root' && rule.selector.startsWith('&--')) { + if ( + rule.parent.type === 'root' && + (rule.selector.startsWith('&--') || rule.selector.startsWith('&.')) + ) { const comment = new Comment({ text: rule.toString() }); rule.replaceWith(comment); } diff --git a/lib/nodeSass/UndefinedVariableFixer.js b/lib/nodeSass/UndefinedVariableFixer.js new file mode 100644 index 00000000..56a49f66 --- /dev/null +++ b/lib/nodeSass/UndefinedVariableFixer.js @@ -0,0 +1,60 @@ +const fs = require('fs'); +const BaseFixer = require('./BaseFixer'); + +class UndefinedVariableFixer extends BaseFixer { + async run(errorMessage) { + const varName = this.getUndefinedVariableName(errorMessage); + const value = await this.guessVariableValue(varName); + + const scss = fs.readFileSync(this.filePath, 'utf8'); + const processedFile = await this.processCss(scss, this.transform(varName, value)); + + return [{ filePath: this.filePath, data: processedFile.css }]; + } + + getUndefinedVariableName(errorMessage) { + const match = errorMessage.match(/\$([a-zA-Z]{1,})/gi); + if (!match) { + throw new Error("Couldn't detemine undefined variable name!"); + } + return match[0]; + } + + transform(varName, value) { + return { + postcssPlugin: 'Declare unvariable variable value', + Once(root, { Declaration }) { + const newRule = new Declaration({ + value, + prop: varName, + source: '', + }); + root.prepend(newRule); + }, + }; + } + + async guessVariableValue(varName) { + const scss = fs.readFileSync(this.filePath, 'utf8'); + const processedFile = await this.processCss( + scss, + this.transformForGuessingVariableValue(varName), + ); + return processedFile.varValue; + } + + transformForGuessingVariableValue(varName) { + return { + postcssPlugin: 'Get first variable value found in the file', + Declaration: (decl, { result }) => { + if (decl.prop === varName) { + // eslint-disable-next-line no-param-reassign + result.varValue = decl.value; + // todo propertly break on first found declaration + } + }, + }; + } +} + +module.exports = UndefinedVariableFixer;