Skip to content

Commit 4991e6f

Browse files
committed
feat: STRF-10507 Scss autofix issue: Undefined variable
1 parent 5507b5e commit 4991e6f

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

lib/nodeSass/AutoFixer.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ const cssCompiler = require('../css/compile');
1010
const BaseRulesFixer = require('./BaseRulesFixer');
1111
const ConditionaImportFixer = require('./ConditionalImportFixer');
1212
const CommaRemovalFixer = require('./CommaRemovalFixer');
13+
const UndefinedVariableFixer = require('./UndefinedVariableFixer');
1314

1415
const CONDITIONAL_IMPORT = 'conditional-import';
1516
const BASE_LEVEL_RULES = 'base-level-rules';
1617
const POSSIBLE_WRONG_COMMA = 'possible-wrong-comma';
18+
const UNDEFINED_VARIABLE = 'undefined-variable';
1719

1820
class AutoFixer {
1921
/**
@@ -75,13 +77,17 @@ class AutoFixer {
7577
const toFixFile = err.file === 'stdin' ? file : err.file;
7678
const commaRemovalFixer = new CommaRemovalFixer(dirname, toFixFile);
7779
files = await commaRemovalFixer.run();
80+
} else if (problem === UNDEFINED_VARIABLE) {
81+
const toFixFile = err.file === 'stdin' ? file : err.file;
82+
const fixer = new UndefinedVariableFixer(dirname, toFixFile);
83+
files = await fixer.run(err.message);
7884
}
7985
this.parseChangedFiles(files);
8086
} else {
8187
const filePath = path.join(this.themePath, 'assets/scss', file + '.scss');
8288
console.log("Couldn't determine and autofix the problem. Please fix it manually.".red);
83-
console.log('Found trying compile file:'.red, filePath);
84-
throw new Error(err);
89+
console.log('Found trying to compile file:'.red, filePath);
90+
throw new Error(err.formatted ? err.formatted : err);
8591
}
8692
}
8793

@@ -107,6 +113,9 @@ class AutoFixer {
107113
) {
108114
return POSSIBLE_WRONG_COMMA;
109115
}
116+
if (err.formatted.includes('Undefined variable')) {
117+
return UNDEFINED_VARIABLE;
118+
}
110119
}
111120

112121
return null;

lib/nodeSass/BaseRulesFixer.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ class BaseRulesFixer extends BaseFixer {
1616
return {
1717
postcssPlugin: 'Transform Base Rules Issues into Comments',
1818
Rule(rule, { Comment }) {
19-
if (rule.parent.type === 'root' && rule.selector.startsWith('&--')) {
19+
if (
20+
rule.parent.type === 'root' &&
21+
(rule.selector.startsWith('&--') || rule.selector.startsWith('&.'))
22+
) {
2023
const comment = new Comment({ text: rule.toString() });
2124
rule.replaceWith(comment);
2225
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
const fs = require('fs');
2+
const BaseFixer = require('./BaseFixer');
3+
4+
class UndefinedVariableFixer extends BaseFixer {
5+
async run(errorMessage) {
6+
const varName = this.getUndefinedVariableName(errorMessage);
7+
const value = await this.guessVariableValue(varName);
8+
9+
const scss = fs.readFileSync(this.filePath, 'utf8');
10+
const processedFile = await this.processCss(scss, this.transform(varName, value));
11+
12+
return [{ filePath: this.filePath, data: processedFile.css }];
13+
}
14+
15+
getUndefinedVariableName(errorMessage) {
16+
const match = errorMessage.match(/\$([a-zA-Z]{1,})/gi);
17+
if (!match) {
18+
throw new Error("Couldn't detemine undefined variable name!");
19+
}
20+
return match[0];
21+
}
22+
23+
transform(varName, value) {
24+
return {
25+
postcssPlugin: 'Declare unvariable variable value',
26+
Once(root, { Declaration }) {
27+
const newRule = new Declaration({
28+
value,
29+
prop: varName,
30+
source: '',
31+
});
32+
root.prepend(newRule);
33+
},
34+
};
35+
}
36+
37+
async guessVariableValue(varName) {
38+
const scss = fs.readFileSync(this.filePath, 'utf8');
39+
const processedFile = await this.processCss(
40+
scss,
41+
this.transformForGuessingVariableValue(varName),
42+
);
43+
return processedFile.varValue;
44+
}
45+
46+
transformForGuessingVariableValue(varName) {
47+
return {
48+
postcssPlugin: 'Get first variable value found in the file',
49+
Declaration: (decl, { result }) => {
50+
if (decl.prop === varName) {
51+
// eslint-disable-next-line no-param-reassign
52+
result.varValue = decl.value;
53+
// todo propertly break on first found declaration
54+
}
55+
},
56+
};
57+
}
58+
}
59+
60+
module.exports = UndefinedVariableFixer;

0 commit comments

Comments
 (0)