forked from csscomb/csscomb.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
remove-empty-rulesets.js
89 lines (74 loc) · 2.05 KB
/
remove-empty-rulesets.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
'use strict';
module.exports = (function () {
function processNode(node) {
removeEmptyRulesets(node);
mergeAdjacentWhitespace(node);
}
function removeEmptyRulesets(stylesheet) {
stylesheet.forEach('ruleset', function (ruleset, i) {
var block = ruleset.first('block');
processNode(block);
if (isEmptyBlock(block)) stylesheet.removeChild(i);
});
}
/**
* Removing ruleset nodes from tree may result in two adjacent whitespace
* nodes which is not correct AST:
* [space, ruleset, space] => [space, space]
* To ensure correctness of further processing we should merge such nodes
* into one:
* [space, space] => [space]
*/
function mergeAdjacentWhitespace(node) {
var i = node.content.length - 1;
while (i-- > 0) {
if (node.get(i).is('space') && node.get(i + 1).is('space')) {
node.get(i).content += node.get(i + 1).content;
node.removeChild(i + 1);
}
}
}
/**
* Block is considered empty when it has nothing but spaces.
*/
function isEmptyBlock(node) {
if (!node.length) return true;
return !node.content.some(function (node) {
return !node.is('space');
});
}
return {
name: 'remove-empty-rulesets',
runBefore: 'block-indent',
syntax: ['css', 'less', 'sass', 'scss'],
accepts: {
boolean: [true]
},
/**
* Remove rulesets with no declarations.
*
* @param {String} ast
*/
process: function process(ast) {
processNode(ast);
},
detectDefault: true,
/**
* Detects the value of an option at the tree node.
* This option is treated as `true` by default, but any trailing space
* would invalidate it.
*
* @param {node} ast
*/
detect: function detect(ast) {
var detected = [];
ast.traverse(function (node) {
if (!node.is('atrulers') && !node.is('block')) return;
if (node.length === 0 || node.length === 1 && node.first().is('space')) {
detected.push(false);
}
});
return detected;
}
};
})();