Skip to content

Commit 2006336

Browse files
committed
autofix for 'sort-styles' rule
1 parent 89c3a11 commit 2006336

File tree

3 files changed

+275
-64
lines changed

3 files changed

+275
-64
lines changed

lib/rules/sort-styles.js

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
const { astHelpers } = require('../util/stylesheet');
1313

1414
const {
15-
getStyleDeclarations,
15+
getStyleDeclarationsChunks,
16+
getPropertiesChunks,
1617
getStylePropertyIdentifier,
1718
isStyleSheetDeclaration,
1819
} = astHelpers;
@@ -28,13 +29,41 @@ module.exports = (context) => {
2829
const ignoreStyleProperties = options.ignoreStyleProperties;
2930
const isValidOrder = order === 'asc' ? (a, b) => a <= b : (a, b) => a >= b;
3031

31-
function report(type, node, prev, current) {
32+
const sourceCode = context.getSourceCode();
33+
34+
function sort(array) {
35+
return [].concat(array).sort((a, b) => {
36+
const identifierA = getStylePropertyIdentifier(a);
37+
const identifierB = getStylePropertyIdentifier(b);
38+
39+
let sortOrder = 0;
40+
if (identifierA < identifierB) {
41+
sortOrder = -1;
42+
} else if (identifierA > identifierB) {
43+
sortOrder = 1;
44+
}
45+
return sortOrder * (order === 'asc' ? 1 : -1);
46+
});
47+
}
48+
49+
function report(array, type, node, prev, current) {
3250
const currentName = getStylePropertyIdentifier(current);
3351
const prevName = getStylePropertyIdentifier(prev);
3452
context.report({
3553
node,
3654
message: `Expected ${type} to be in ${order}ending order. '${currentName}' should be before '${prevName}'.`,
3755
loc: current.key.loc,
56+
fix(fixer) {
57+
const sortedArray = sort(array);
58+
return array
59+
.map((item, i) => {
60+
if (item !== sortedArray[i]) {
61+
return fixer.replaceText(item, sourceCode.getText(sortedArray[i]));
62+
}
63+
return null;
64+
})
65+
.filter(Boolean);
66+
},
3867
});
3968
}
4069

@@ -51,7 +80,7 @@ module.exports = (context) => {
5180
const currentName = getStylePropertyIdentifier(current);
5281

5382
if (!isValidOrder(prevName, currentName)) {
54-
return report(arrayName, node, previous, current);
83+
return report(array, arrayName, node, previous, current);
5584
}
5685
}
5786
}
@@ -62,26 +91,33 @@ module.exports = (context) => {
6291
return;
6392
}
6493

65-
const classDefinitions = getStyleDeclarations(node);
94+
const classDefinitionsChunks = getStyleDeclarationsChunks(node);
6695

6796
if (!ignoreClassNames) {
68-
checkIsSorted(classDefinitions, 'class names', node);
97+
classDefinitionsChunks.forEach((classDefinitions) => {
98+
checkIsSorted(classDefinitions, 'class names', node);
99+
});
69100
}
70101

71102
if (ignoreStyleProperties) return;
72103

73-
classDefinitions.forEach((classDefinition) => {
74-
const styleProperties = classDefinition.value.properties;
75-
if (!styleProperties || styleProperties.length < 2) {
76-
return;
77-
}
78-
79-
checkIsSorted(styleProperties, 'style properties', node);
104+
classDefinitionsChunks.forEach((classDefinitions) => {
105+
classDefinitions.forEach((classDefinition) => {
106+
const styleProperties = classDefinition.value.properties;
107+
if (!styleProperties || styleProperties.length < 2) {
108+
return;
109+
}
110+
const stylePropertyChunks = getPropertiesChunks(styleProperties);
111+
stylePropertyChunks.forEach((stylePropertyChunk) => {
112+
checkIsSorted(stylePropertyChunk, 'style properties', node);
113+
});
114+
});
80115
});
81116
},
82117
};
83118
};
84119

120+
module.exports.fixable = 'code';
85121
module.exports.schema = [
86122
{
87123
enum: ['asc', 'desc'],

lib/util/stylesheet.js

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,32 +127,72 @@ const astHelpers = {
127127
},
128128

129129
getStyleSheetName: function (node) {
130+
if (node && node.id) {
131+
return node.id.name;
132+
}
133+
},
134+
135+
getStyleDeclarations: function (node) {
130136
if (
131137
node &&
132-
node.id
138+
node.init &&
139+
node.init.arguments &&
140+
node.init.arguments[0] &&
141+
node.init.arguments[0].properties
133142
) {
134-
return node.id.name;
143+
return node.init.arguments[0].properties.filter(property => property.type === 'Property');
135144
}
145+
146+
return [];
136147
},
137148

138-
getStyleDeclarations: function (node) {
149+
getStyleDeclarationsChunks: function (node) {
139150
if (
140151
node &&
141152
node.init &&
142153
node.init.arguments &&
143154
node.init.arguments[0] &&
144155
node.init.arguments[0].properties
145156
) {
146-
return node
147-
.init
148-
.arguments[0]
149-
.properties
150-
.filter(property => property.type === 'Property');
157+
const properties = node.init.arguments[0].properties;
158+
const result = [];
159+
let chunk = [];
160+
for (let i = 0; i < properties.length; i += 1) {
161+
const property = properties[i];
162+
if (property.type === 'Property') {
163+
chunk.push(property);
164+
} else if (chunk.length) {
165+
result.push(chunk);
166+
chunk = [];
167+
}
168+
}
169+
if (chunk.length) {
170+
result.push(chunk);
171+
}
172+
return result;
151173
}
152174

153175
return [];
154176
},
155177

178+
getPropertiesChunks: function (properties) {
179+
const result = [];
180+
let chunk = [];
181+
for (let i = 0; i < properties.length; i += 1) {
182+
const property = properties[i];
183+
if (property.type === 'Property') {
184+
chunk.push(property);
185+
} else if (chunk.length) {
186+
result.push(chunk);
187+
chunk = [];
188+
}
189+
}
190+
if (chunk.length) {
191+
result.push(chunk);
192+
}
193+
return result;
194+
},
195+
156196
getExpressionIdentifier: function (node) {
157197
if (node) {
158198
switch (node.type) {

0 commit comments

Comments
 (0)