@@ -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
4564function 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
113153function 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
132182function 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