Skip to content

Commit f423395

Browse files
author
scalder
committed
some code refactoring
When I was reading the code for the first time it was a little hard to reason about, so I would like to suggest some small code improvements (maybe): 1) ditched one small piece of code duplication 2) splitted a long code, that was setting indexes for node, to a bunch of smaller and a bit more understandable pieces
1 parent 1013953 commit f423395

File tree

1 file changed

+106
-99
lines changed

1 file changed

+106
-99
lines changed

index.js

Lines changed: 106 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var postcss = require('postcss');
22
var path = require('path');
33
var fs = require('fs');
44

5-
function getSortOrder(options) {
5+
function getSortOrderFromOptions(options) {
66
// If no options use default config
77
if (options === null || typeof options !== 'object' || !options['sort-order']) {
88
options = { 'sort-order': 'default' };
@@ -29,27 +29,34 @@ function getSortOrder(options) {
2929
// Add sorting indexes to order
3030
var order = {};
3131

32-
if (typeof sortOrder[0] === 'string') {
33-
sortOrder.forEach(function (prop, propIndex) {
34-
order[prop] = {
35-
group: 0,
36-
prop: propIndex
37-
};
38-
});
39-
} else {
40-
sortOrder.forEach(function (group, groupIndex) {
32+
(typeof sortOrder[0] === 'string' ? [sortOrder] : sortOrder)
33+
.forEach(function (group, groupIndex) {
4134
group.forEach(function (prop, propIndex) {
4235
order[prop] = {
4336
group: groupIndex,
4437
prop: propIndex
4538
};
4639
});
4740
});
48-
}
4941

5042
return order;
5143
}
5244

45+
function getLinesBetweenChildrenFromOptions(opts) {
46+
var options = opts || {};
47+
var lines = options['empty-lines-between-children-rules'];
48+
49+
if (lines === undefined || lines === null) {
50+
return 0;
51+
}
52+
53+
if (typeof lines !== 'number' || isNaN(lines) || !isFinite(lines) || lines < 0 || Math.floor(lines) !== lines) {
54+
throw new Error('Type of "empty-lines-between-children-rules" option must be integer with positive value.');
55+
}
56+
57+
return lines;
58+
}
59+
5360
// Replace multiple line breaks with one
5461
function cleanLineBreaks(node) {
5562
if (node.raws.before) {
@@ -63,26 +70,100 @@ function createLineBreaks(lineBreaksCount) {
6370
return new Array(lineBreaksCount + 1).join('\n');
6471
}
6572

66-
function getLinesBetweenChildrenFromOptions(opts) {
67-
var options = opts || {};
68-
var lines = options['empty-lines-between-children-rules'];
73+
function getAtruleSortName(node, order) {
74+
var atruleName = '@' + node.name;
6975

70-
if (lines === undefined || lines === null) {
71-
return 0;
76+
// If atRule has a parameter like @mixin name or @include name, sort by this parameter
77+
var atruleParameter = /^[\w-]+/.exec(node.params);
78+
79+
if (atruleParameter && atruleParameter.length) {
80+
var sortNameExtended = atruleName + ' ' + atruleParameter[0];
81+
82+
if (order[sortNameExtended]) {
83+
return sortNameExtended;
84+
}
7285
}
7386

74-
if (typeof lines !== 'number' || isNaN(lines) || !isFinite(lines) || lines < 0 || Math.floor(lines) !== lines) {
75-
throw new Error('Type of "empty-lines-between-children-rules" option must be integer with positive value.');
87+
// If atrule with name is in order use the name
88+
if (order[atruleName]) {
89+
return atruleName;
7690
}
7791

78-
return lines;
92+
return '@atrule';
93+
}
94+
95+
function getSortName(node, order) {
96+
switch (node.type) {
97+
case 'decl':
98+
return /^\$[\w-]+/.test(node.prop) ? '$variable' : node.prop;
99+
100+
case 'atrule':
101+
return getAtruleSortName(node, order);
102+
103+
case 'rule':
104+
return '>child';
105+
106+
default:
107+
return null;
108+
}
109+
}
110+
111+
function getOrderProperty(node, order) {
112+
var sortName = getSortName(node, order);
113+
114+
// Trying to get property indexes from order's list
115+
var orderProperty = order[sortName];
116+
117+
// If no property in the list and this property is prefixed then trying to get parameters for unprefixed property
118+
if (!orderProperty && postcss.vendor.prefix(sortName)) {
119+
sortName = postcss.vendor.unprefixed(sortName);
120+
orderProperty = order[sortName];
121+
}
122+
123+
return orderProperty;
79124
}
80125

126+
function fetchAllCommentsBeforeNode(comments, previousNode, node) {
127+
if (!previousNode || previousNode.type !== 'comment') {
128+
return comments;
129+
}
130+
131+
if (!previousNode.raws.before || previousNode.raws.before.indexOf('\n') === -1) {
132+
return comments;
133+
}
134+
135+
previousNode.groupIndex = node.groupIndex;
136+
previousNode.propertyIndex = node.propertyIndex;
137+
previousNode.initialIndex = node.initialIndex - 1;
138+
139+
var previousNodeClone = cleanLineBreaks(previousNode);
140+
var newComments = [previousNodeClone].concat(comments);
141+
142+
return fetchAllCommentsBeforeNode(newComments, previousNode.prev(), node);
143+
}
144+
145+
function fetchAllCommentsAfterNode(comments, nextNode, node) {
146+
if (!nextNode || nextNode.type !== 'comment') {
147+
return comments;
148+
}
149+
150+
if (!nextNode.raws.before || nextNode.raws.before.indexOf('\n') >= 0) {
151+
return comments;
152+
}
153+
154+
nextNode.groupIndex = node.groupIndex;
155+
nextNode.propertyIndex = node.propertyIndex;
156+
nextNode.initialIndex = node.initialIndex + 1;
157+
158+
return fetchAllCommentsAfterNode(comments.concat(nextNode), nextNode.next(), node);
159+
}
160+
161+
81162
module.exports = postcss.plugin('postcss-sorting', function (opts) {
82163
var linesBetweenChildrenRules = getLinesBetweenChildrenFromOptions(opts);
83164

84165
return function (css) {
85-
var order = getSortOrder(opts);
166+
var order = getSortOrderFromOptions(opts);
86167

87168
// Index to place the nodes that shouldn't be sorted
88169
var lastGroupIndex = order['...'] ? order['...'].group : Infinity;
@@ -96,49 +177,11 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {
96177
var processed = [];
97178

98179
rule.each(function (node, index) {
99-
var sortName = null;
100-
101180
if (node.type === 'comment') {
102181
return;
103-
} else if (node.type === 'decl') {
104-
sortName = node.prop;
105-
106-
// If property start with $ and letters it's a variable
107-
if (/^\$[\w-]+/.test(node.prop)) {
108-
sortName = '$variable';
109-
}
110-
} else if (node.type === 'atrule') {
111-
sortName = '@atrule';
112-
113-
// If atrule with name is in order use the name
114-
var atruleName = '@' + node.name;
115-
116-
if (order[atruleName]) {
117-
sortName = atruleName;
118-
}
119-
120-
// Ff atRule has a parameter like @mixin name or @include name, sort by this parameter
121-
var atruleParameter = /^[\w-]+/.exec(node.params);
122-
123-
if (atruleParameter && atruleParameter.length) {
124-
var sortNameExtended = atruleName + ' ' + atruleParameter[0];
125-
126-
if (order[sortNameExtended]) {
127-
sortName = sortNameExtended;
128-
}
129-
}
130-
} else if (node.type === 'rule') {
131-
sortName = '>child';
132182
}
133183

134-
// Trying to get property indexes from order's list
135-
var orderProperty = order[sortName];
136-
137-
// If no property in the list and this property is prefixed then trying to get parameters for unprefixed property
138-
if (!orderProperty && postcss.vendor.prefix(sortName)) {
139-
sortName = postcss.vendor.unprefixed(sortName);
140-
orderProperty = order[sortName];
141-
}
184+
var orderProperty = getOrderProperty(node, order);
142185

143186
// If the declaration's property is in order's list, save its
144187
// group and property indexes. Otherwise set them to 10000, so
@@ -148,47 +191,12 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {
148191
node.initialIndex = index;
149192

150193
// If comment on separate line before node, use node's indexes for comment
151-
var commentsBefore = [];
152-
var previousNode = node.prev();
153-
154-
while (previousNode && previousNode.type === 'comment') {
155-
if (previousNode.raws.before && previousNode.raws.before.indexOf('\n') > -1) {
156-
previousNode.groupIndex = node.groupIndex;
157-
previousNode.propertyIndex = node.propertyIndex;
158-
previousNode.initialIndex = index - 1;
159-
160-
var previousNodeClone = cleanLineBreaks(previousNode);
161-
162-
commentsBefore.unshift(previousNodeClone);
163-
164-
previousNode = previousNode.prev();
165-
} else {
166-
break;
167-
}
168-
}
169-
170-
if (commentsBefore.length) {
171-
processed = processed.concat(commentsBefore);
172-
}
173-
174-
// Add node itself
175-
processed.push(node);
194+
var commentsBefore = fetchAllCommentsBeforeNode([], node.prev(), node);
176195

177196
// If comment on same line with the node and node, use node's indexes for comment
178-
var nextNode = node.next();
179-
180-
while (nextNode && nextNode.type === 'comment') {
181-
if (nextNode.raws.before && nextNode.raws.before.indexOf('\n') < 0) {
182-
nextNode.groupIndex = node.groupIndex;
183-
nextNode.propertyIndex = node.propertyIndex;
184-
nextNode.initialIndex = index + 1;
185-
186-
processed.push(nextNode);
187-
nextNode = nextNode.next();
188-
} else {
189-
break;
190-
}
191-
}
197+
var commentsAfter = fetchAllCommentsAfterNode([], node.next(), node);
198+
199+
processed = processed.concat(commentsBefore, node, commentsAfter);
192200
});
193201

194202
// Sort declarations saved for sorting:
@@ -228,7 +236,6 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {
228236
}
229237
}
230238
});
231-
232239
}
233240
});
234241
};

0 commit comments

Comments
 (0)