Skip to content

Commit 5ed9b55

Browse files
committed
New option: block-indent
1 parent 447479e commit 5ed9b55

9 files changed

Lines changed: 321 additions & 0 deletions

File tree

config/csscomb.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"node_modules/**"
55
],
66
"always-semicolon": true,
7+
"block-indent": " ",
78
"color-case": "lower",
89
"color-shorthand": true,
910
"element-case": "lower",

doc/options.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,60 @@ div {
4646
}
4747
```
4848

49+
## block-indent
50+
51+
Set indent for code inside blocks, including media queries and nested rules.
52+
53+
Acceptable values:
54+
55+
* `{Number}` — number os whitespaces;
56+
* `{String}` — string with whitespaces and tabs. Note that line breaks are not
57+
allowed here.
58+
59+
Example: `{ 'block-indent': 4 }`
60+
61+
```scss
62+
// Before:
63+
a {
64+
top: 0;
65+
p {
66+
color: tomato;
67+
position: happy;
68+
}
69+
}
70+
71+
// After:
72+
a {
73+
top: 0;
74+
p {
75+
color: tomato;
76+
position: happy;
77+
}
78+
}
79+
```
80+
81+
Example: `{ 'block-indent': '' }`
82+
83+
```scss
84+
// Before:
85+
a {
86+
top: 0;
87+
p {
88+
color: tomato;
89+
position: happy;
90+
}
91+
}
92+
93+
// After:
94+
a {
95+
top: 0;
96+
p {
97+
color: tomato;
98+
position: happy;
99+
}
100+
}
101+
```
102+
49103
## color-case
50104

51105
Unify case of hexadecimal colors.

lib/csscomb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var OPTIONS = [
1616
'strip-spaces',
1717
'eof-newline',
1818
'sort-order',
19+
'block-indent',
1920
'unitless-zero',
2021
'vendor-prefix-align'
2122
];

lib/options/block-indent.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
module.exports = {
2+
name: 'block-indent',
3+
4+
accepts: {
5+
number: true,
6+
string: /^[ \t]*$/
7+
},
8+
9+
/**
10+
* Processes tree node.
11+
*
12+
* @param {String} nodeType
13+
* @param {node} node
14+
* @param {Number} level
15+
*/
16+
process: function process(nodeType, node, level) {
17+
var spaces;
18+
19+
if (nodeType === 'stylesheet') {
20+
for (var i = node.length; i--;) {
21+
var whitespaceNode = node[i];
22+
23+
if (whitespaceNode[0] !== 's') continue;
24+
25+
spaces = whitespaceNode[1].replace(/\n[ \t]+/gm, '\n');
26+
if (spaces === '') {
27+
node.splice(i, 1);
28+
} else {
29+
whitespaceNode[1] = spaces;
30+
}
31+
}
32+
return;
33+
}
34+
35+
// Continue only with space nodes inside {...}:
36+
if (level === 0 || nodeType !== 's') return;
37+
38+
// Remove all whitespaces and tabs, leave only new lines:
39+
spaces = node[0].replace(/[ \t]/gm, '');
40+
41+
if (!spaces) return;
42+
43+
spaces += new Array(level + 1).join(this.getValue('block-indent'));
44+
node[0] = spaces;
45+
},
46+
47+
/**
48+
* Detects the value of an option at the tree node.
49+
*
50+
* @param {String} nodeType
51+
* @param {node} node
52+
* @param {Number} level
53+
*/
54+
detect: function(nodeType, node, level) {
55+
var result = [];
56+
57+
// Continue only with non-empty {...} blocks:
58+
if (nodeType !== 'atrulers' && nodeType !== 'block' || !node.length) return;
59+
60+
for (var i = node.length; i--;) {
61+
var whitespaceNode = node[i];
62+
if (whitespaceNode[0] !== 's') continue;
63+
64+
var spaces = whitespaceNode[1];
65+
var lastIndex = spaces.lastIndexOf('\n');
66+
67+
// Do not continue if there is no line break:
68+
if (lastIndex < 0) continue;
69+
70+
// Number of spaces from beginning of line:
71+
var spacesLength = spaces.slice(lastIndex + 1).length;
72+
result.push(new Array(spacesLength / (level + 1) + 1).join(' '));
73+
}
74+
75+
return result;
76+
}
77+
};

test/options/block-indent.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
describe('options/block-indent:', function() {
2+
beforeEach(function() {
3+
this.filename = __filename;
4+
});
5+
6+
it('Array value => should not change anything', function() {
7+
this.comb.configure({ 'block-indent': ['', ' '] });
8+
this.shouldBeEqual('test.css');
9+
});
10+
11+
it('Invalid string value => should not change anything', function() {
12+
this.comb.configure({ 'block-indent': ' nani ' });
13+
this.shouldBeEqual('test.css');
14+
});
15+
16+
it('Float number value => should not change anything', function() {
17+
this.comb.configure({ 'block-indent': 3.5 });
18+
this.shouldBeEqual('test.css');
19+
});
20+
21+
it('Integer value => should set proper number of spaces', function() {
22+
this.comb.configure({ 'block-indent': 0 });
23+
this.shouldBeEqual('test.css', 'test.expected.css');
24+
});
25+
26+
it('Valid string value => should set proper number of spaces', function() {
27+
this.comb.configure({ 'block-indent': ' ' });
28+
this.shouldBeEqual('test.css', 'test-2.expected.css');
29+
});
30+
31+
it('Should detect nothing with an empty block, test 1', function() {
32+
this.shouldDetect(
33+
['block-indent'],
34+
'a{ }',
35+
{}
36+
);
37+
});
38+
39+
it('Should detect nothing with an empty block, test 2', function() {
40+
this.shouldDetect(
41+
['block-indent'],
42+
'a{}',
43+
{}
44+
);
45+
});
46+
47+
it('Should detect correct number of spaces', function() {
48+
this.shouldDetect(
49+
['block-indent'],
50+
'a{\n top: 0;\n color: tomato;\n}',
51+
{ 'block-indent': ' ' }
52+
);
53+
});
54+
55+
it('Should detect no indent for one-line code', function() {
56+
this.shouldDetect(
57+
['block-indent'],
58+
'a{ top: 0; color: tomato; }',
59+
{}
60+
);
61+
});
62+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
a {color: tomato; top: 0;}
2+
3+
a { color: tomato;
4+
top: 0; }
5+
6+
a { color: tomato;
7+
top: 0; }
8+
9+
a {
10+
color: tomato;
11+
top: 0; }
12+
13+
a {
14+
color: tomato;
15+
top: 0;
16+
}
17+
18+
a {
19+
color: tomato;
20+
top: 0;
21+
}
22+
23+
@media print { a {color: tomato; top: 0; } }
24+
25+
@media print {
26+
a {
27+
color: tomato;
28+
top: 0;
29+
}
30+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
a {color: tomato; top: 0;
2+
}
3+
4+
a { color: tomato;
5+
top: 0;
6+
}
7+
8+
a { color: tomato;
9+
top: 0;
10+
}
11+
12+
a {
13+
color: tomato;
14+
top: 0;
15+
}
16+
17+
a {
18+
color: tomato;
19+
top: 0;
20+
}
21+
22+
a {
23+
color: tomato;
24+
top: 0;
25+
}
26+
27+
@media print { a {color: tomato; top: 0;
28+
}
29+
}
30+
31+
@media print {
32+
a {
33+
color: tomato;
34+
top: 0;
35+
}
36+
}

test/options/block-indent/test.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
a {color: tomato; top: 0;}
2+
3+
a { color: tomato;
4+
top: 0; }
5+
6+
a { color: tomato;
7+
top: 0; }
8+
9+
a {
10+
color: tomato;
11+
top: 0; }
12+
13+
a {
14+
color: tomato;
15+
top: 0;
16+
}
17+
18+
a {
19+
color: tomato;
20+
top: 0;
21+
}
22+
23+
@media print { a {color: tomato; top: 0; } }
24+
25+
@media print {
26+
a {
27+
color: tomato;
28+
top: 0;
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
a {color: tomato; top: 0;}
2+
3+
a { color: tomato;
4+
top: 0; }
5+
6+
a { color: tomato;
7+
top: 0; }
8+
9+
a {
10+
color: tomato;
11+
top: 0; }
12+
13+
a {
14+
color: tomato;
15+
top: 0;
16+
}
17+
18+
a {
19+
color: tomato;
20+
top: 0;
21+
}
22+
23+
@media print { a {color: tomato; top: 0; } }
24+
25+
@media print {
26+
a {
27+
color: tomato;
28+
top: 0;
29+
}
30+
}

0 commit comments

Comments
 (0)