Skip to content

Commit 7ec4395

Browse files
committed
Show more descriptive error messages for invalid config #65
1 parent 96810aa commit 7ec4395

File tree

1 file changed

+87
-26
lines changed

1 file changed

+87
-26
lines changed

lib/validateOptions.js

Lines changed: 87 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,33 @@ module.exports = function validateOptions(options) {
1111
return reportError('Options should be an object.');
1212
}
1313

14-
if (!_.isUndefined(options.order) && !_.isNull(options.order) && !validateOrder(options.order)) {
15-
return reportInvalidOption('order');
14+
if (!_.isUndefined(options.order) && !_.isNull(options.order)) {
15+
const { isValid, message } = validateOrder(options.order);
16+
17+
if (!isValid) {
18+
return reportInvalidOption('order', message);
19+
}
1620
}
1721

18-
if (
19-
!_.isUndefined(options['properties-order']) &&
20-
!_.isNull(options['properties-order']) &&
21-
!validatePropertiesOrder(options['properties-order'])
22-
) {
23-
return reportInvalidOption('properties-order');
22+
if (!_.isUndefined(options['properties-order']) && !_.isNull(options['properties-order'])) {
23+
const { isValid, message } = validatePropertiesOrder(options['properties-order']);
24+
25+
if (!isValid) {
26+
return reportInvalidOption('properties-order', message);
27+
}
2428
}
2529

2630
if (
2731
!_.isUndefined(options['unspecified-properties-position']) &&
28-
!_.isNull(options['unspecified-properties-position']) &&
29-
!validateUnspecifiedPropertiesPosition(options['unspecified-properties-position'])
32+
!_.isNull(options['unspecified-properties-position'])
3033
) {
31-
return reportInvalidOption('unspecified-properties-position');
34+
const { isValid, message } = validateUnspecifiedPropertiesPosition(
35+
options['unspecified-properties-position']
36+
);
37+
38+
if (!isValid) {
39+
return reportInvalidOption('unspecified-properties-position', message);
40+
}
3241
}
3342

3443
return true;
@@ -38,46 +47,68 @@ function reportError(errorMessage) {
3847
return `postcss-sorting: ${errorMessage}`;
3948
}
4049

41-
function reportInvalidOption(optionName) {
42-
return reportError(`Invalid "${optionName}" option value`);
50+
function reportInvalidOption(optionName, optionError) {
51+
optionError = optionError || 'Invalid value';
52+
53+
return reportError(`${optionName}: ${optionError}`);
54+
}
55+
56+
function keywordsList(keywords) {
57+
return keywords.reduce(function(accumulator, value, index) {
58+
const comma = index === 0 ? '' : ', ';
59+
60+
return accumulator + comma + value;
61+
}, '');
4362
}
4463

4564
function validateOrder(options) {
4665
// Otherwise, begin checking array options
4766
if (!Array.isArray(options)) {
48-
return false;
67+
return {
68+
isValid: false,
69+
message: 'Should be an array',
70+
};
4971
}
5072

73+
const keywords = ['custom-properties', 'dollar-variables', 'declarations', 'rules', 'at-rules'];
74+
5175
// Every item in the array must be a certain string or an object
5276
// with a "type" property
5377
if (
5478
!options.every(item => {
5579
if (_.isString(item)) {
56-
return _.includes(
57-
['custom-properties', 'dollar-variables', 'declarations', 'rules', 'at-rules'],
58-
item
59-
);
80+
return _.includes(keywords, item);
6081
}
6182

6283
return _.isPlainObject(item) && !_.isUndefined(item.type);
6384
})
6485
) {
65-
return false;
86+
return {
87+
isValid: false,
88+
message: `Every item in the array must be an object with a "type" property, or one of keywords: ${keywordsList(
89+
keywords
90+
)}.`,
91+
};
6692
}
6793

6894
const objectItems = options.filter(_.isPlainObject);
95+
let wrongObjectItem;
6996

7097
if (
7198
!objectItems.every(item => {
7299
let result = true;
73100

74101
if (item.type !== 'at-rule' && item.type !== 'rule') {
102+
wrongObjectItem = `"type" could be 'at-rule' or 'rule' only`;
103+
75104
return false;
76105
}
77106

78107
if (item.type === 'at-rule') {
79108
// if parameter is specified, name should be specified also
80109
if (!_.isUndefined(item.parameter) && _.isUndefined(item.name)) {
110+
wrongObjectItem = `"at-rule" with "parameter" should also has a "name"`;
111+
81112
return false;
82113
}
83114

@@ -101,34 +132,64 @@ function validateOrder(options) {
101132
}
102133
}
103134

135+
if (!result) {
136+
wrongObjectItem = `Following option is incorrect: ${JSON.stringify(item)}`;
137+
}
138+
104139
return result;
105140
})
106141
) {
107-
return false;
142+
return {
143+
isValid: false,
144+
message: wrongObjectItem,
145+
};
108146
}
109147

110-
return true;
148+
return {
149+
isValid: true,
150+
};
111151
}
112152

113153
function validatePropertiesOrder(options) {
114154
// Return true early if alphabetical
115155
if (options === 'alphabetical') {
116-
return true;
156+
return {
157+
isValid: true,
158+
};
117159
}
118160

119161
// Otherwise, begin checking array options
120162
if (!Array.isArray(options)) {
121-
return false;
163+
return {
164+
isValid: false,
165+
message: 'Should be an array',
166+
};
122167
}
123168

124169
// Every item in the array must be a string
125170
if (!options.every(item => _.isString(item))) {
126-
return false;
171+
return {
172+
isValid: false,
173+
message: 'Array should contain strings only',
174+
};
127175
}
128176

129-
return true;
177+
return {
178+
isValid: true,
179+
};
130180
}
131181

132182
function validateUnspecifiedPropertiesPosition(options) {
133-
return _.isString(options) && _.includes(['top', 'bottom', 'bottomAlphabetical'], options);
183+
const keywords = ['top', 'bottom', 'bottomAlphabetical'];
184+
185+
if (_.isString(options) && _.includes(keywords, options)) {
186+
return {
187+
isValid: true,
188+
};
189+
}
190+
191+
return {
192+
isValid: false,
193+
message: `Option should be one of the following values: ${keywordsList(keywords)}.`,
194+
};
134195
}

0 commit comments

Comments
 (0)