UNPKG

3.23 kBJavaScriptView Raw
1
2/**
3 * Validates the order in object keys.
4 *
5 * Types: `Boolean` or `String`
6 *
7 * Values:
8 * - `true` (alias to `asc`)
9 * - `"asc"`: requires sorting in ascending order
10 * - `"asc-insensitive"`: requires sorting in ascending order (case-insensitive)
11 * - `"asc-natural"`: requires sorting in ascending natural order
12 * - `"desc"`: requires sorting in descending order
13 * - `"desc-insensitive"`: requires sorting in descending order (case-insensitive)
14 * - `"desc-natural"`: requires sorting in descending natural order
15 *
16 * #### Example
17 *
18 * ```js
19 * "validateOrderInObjectKeys": "asc"
20 * ```
21 *
22 * ##### Valid
23 *
24 * ```js
25 * var x = {
26 * x: 'foo',
27 * y: 'bar'
28 * }
29 * ```
30 *
31 * ##### Invalid
32 *
33 * ```js
34 * var x = {
35 * y: 'foo',
36 * x: 'bar'
37 * }
38 * ```
39 */
40
41var assert = require('assert');
42var naturalSort = require('natural-compare');
43
44/**
45 * Sort in ascending order.
46 */
47function asc(a, b) {
48 return String(a) < String(b) ? -1 : 1;
49}
50
51/**
52 * Sort in ascending order (case-insensitive).
53 */
54function ascInsensitive(a, b) {
55 var lowercaseA = String(a).toLowerCase();
56 var lowercaseB = String(b).toLowerCase();
57
58 if (lowercaseA < lowercaseB) {
59 return -1;
60 }
61
62 if (lowercaseA > lowercaseB) {
63 return 1;
64 }
65
66 return asc(a, b);
67}
68
69/**
70 * Natural sort in ascending order.
71 */
72function ascNatural(a, b) {
73 return naturalSort(a, b);
74}
75
76/**
77 * Native sort in descending order.
78 */
79function desc(a, b) {
80 return asc(a, b) * -1;
81}
82
83/**
84 * Sort in descending order (case-insensitive).
85 */
86function descInsensitive(a, b) {
87 return ascInsensitive(a, b) * -1;
88}
89
90/**
91 * Native sort in descending order.
92 */
93function descNatural(a, b) {
94 return naturalSort(a, b) * -1;
95}
96
97/**
98 * Available sort methods.
99 */
100var methods = {
101 asc: asc,
102 'asc-insensitive': ascInsensitive,
103 'asc-natural': ascNatural,
104 desc: desc,
105 'desc-insensitive': descInsensitive,
106 'desc-natural': descNatural
107};
108
109module.exports = function() {};
110
111module.exports.prototype = {
112
113 configure: function(options) {
114 assert(
115 options === true || Object.keys(methods).indexOf(options) !== -1,
116 this.getOptionName() + ' option requires a true value or should be removed'
117 );
118
119 this._sort = methods[options] || methods.asc;
120 },
121
122 getOptionName: function() {
123 return 'validateOrderInObjectKeys';
124 },
125
126 check: function(file, errors) {
127 var sort = this._sort;
128
129 file.iterateNodesByType('ObjectExpression', function(node) {
130 var keys = node.properties.map(function(property) {
131 return (property.key.name || property.key.value);
132 });
133
134 var sorted = keys.slice(0).sort(sort);
135 var unsorted;
136
137 for (var i = 0; i < keys.length; i++) {
138 if (keys[i] !== sorted[i]) {
139 unsorted = i;
140
141 break;
142 }
143 }
144
145 if (undefined !== unsorted) {
146 errors.add(
147 'Object keys must be in ' + (/asc/.test(sort.name) ? 'ascending' : 'descending') + ' order',
148 node.properties[unsorted]
149 );
150 }
151 });
152 }
153};