Skip to content

Commit 1990bb7

Browse files
committed
add ruleset support. Closes reworkcss#1
1 parent e2b4874 commit 1990bb7

13 files changed

+143
-74
lines changed

examples/example.css

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
11

2-
@charset "utf-8"
3-
4-
@import "foo.css"
5-
6-
body
7-
padding: 50px
8-
background: black
9-
color: white
10-
11-
// just an example comment
12-
132
button
143
// moar comments
154
// hurrrrrrrr
@@ -27,4 +16,4 @@ button
2716

2817
button
2918
border-radius: 0
30-
width: 100%
19+
width: 100%

lib/compiler.js

+52-35
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var debug = require('debug')('css-whitespace:parser')
1515
*/
1616

1717
module.exports = function(node){
18-
var indents = 1;
18+
var indents = 0;
1919
var rules = [];
2020
var stash = [];
2121
var level = 0;
@@ -36,9 +36,9 @@ module.exports = function(node){
3636
case 'root':
3737
return root(node);
3838
case 'rule':
39-
if ('@' == node[1][0]) ++nest;
39+
if ('@' == node[1][0][0]) ++nest;
4040
var ret = rule(node);
41-
if ('@' == node[1][0]) --nest;
41+
if ('@' == node[1][0][0]) --nest;
4242
return ret;
4343
case 'block':
4444
++level;
@@ -84,27 +84,33 @@ module.exports = function(node){
8484
function rule(node) {
8585
var rule = node[1];
8686
var block = node[2];
87+
var buf;
8788

88-
if (!block) return rule + ';';
89+
// TODO: tests
90+
if (!block) return rule.join(',\n') + ';';
8991

9092
rules.push(node);
9193

92-
if ('@' == rule[0]) {
93-
var buf = join(rules) + '{\n'
94+
if ('@' == rule[0][0]) {
95+
buf = join(rules) + '{\n';
9496
visit(block);
9597
buf += stash.join('\n');
9698
buf += '\n}';
9799
stash = [];
98100
} else if (nest) {
101+
indents = 1;
102+
buf = join(rules, 1) + ' {\n';
99103
indents = 2;
100-
var buf = ' ' + join(rules, 1) + '{\n';
101104
buf += visit(block);
102105
buf += ' }';
103106
indents = 1;
104107
} else {
105-
var buf = join(rules) + '{\n'
106-
+ visit(block)
107-
+ '}';
108+
indents = 0;
109+
buf = join(rules) + '{\n'
110+
indents = 1;
111+
buf += visit(block);
112+
indents = 0;
113+
buf += '}';
108114
}
109115

110116
if (rules.length > 1) {
@@ -133,6 +139,42 @@ module.exports = function(node){
133139
return buf.join('\n\n');
134140
}
135141

142+
/**
143+
* Join the given rules.
144+
*
145+
* @param {Array} rules
146+
* @param {Number} [offset]
147+
* @return {String}
148+
* @api private
149+
*/
150+
151+
function join(rules, offset) {
152+
offset = offset || 0;
153+
var selectors = [];
154+
var buf = [];
155+
var curr;
156+
var next;
157+
158+
function compile(rules, i) {
159+
if (offset != i) {
160+
rules[i][1].forEach(function(selector){
161+
buf.unshift(selector);
162+
compile(rules, i - 1);
163+
buf.shift();
164+
});
165+
} else {
166+
rules[i][1].forEach(function(selector){
167+
var tail = buf.join(' ');
168+
selectors.push(indent() + selector + ' ' + tail);
169+
});
170+
}
171+
}
172+
173+
compile(rules, rules.length - 1);
174+
175+
return selectors.join(',\n');
176+
}
177+
136178
/**
137179
* Return indent.
138180
*/
@@ -142,31 +184,6 @@ module.exports = function(node){
142184
}
143185
};
144186

145-
/**
146-
* Join the given rules.
147-
*
148-
* @param {Array} rules
149-
* @param {Number} [offset]
150-
* @return {String}
151-
* @api private
152-
*/
153-
154-
function join(rules, offset) {
155-
var buf = '';
156-
var curr;
157-
var next;
158-
159-
for (var i = offset || 0; i < rules.length; ++i) {
160-
curr = rules[i];
161-
next = rules[i + 1];
162-
buf += curr[1];
163-
if (next && next.parent) continue;
164-
buf += ' ';
165-
}
166-
167-
return buf;
168-
}
169-
170187
/**
171188
* Check if `block` has properties.
172189
*

lib/lexer.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ module.exports = function(str) {
125125
}
126126

127127
/**
128-
* &<val>
128+
* Parent reference.
129129
*/
130130

131131
function parent() {
@@ -138,7 +138,7 @@ module.exports = function(str) {
138138
}
139139

140140
/**
141-
* <prop>: <val>
141+
* Property.
142142
*/
143143

144144
function prop() {
@@ -149,14 +149,14 @@ module.exports = function(str) {
149149
}
150150

151151
/**
152-
* (^ newline)+
152+
* Rule.
153153
*/
154154

155155
function rule() {
156-
var line = str.match(/^[^\n]+/);
157-
if (!line) return;
158-
line = line[0];
159-
str = str.slice(line.length);
160-
return ['rule', line];
156+
var m = str.match(/^([^\n,]+, *\n|[^\n]+)+/);
157+
if (!m) return;
158+
str = str.slice(m[0].length);
159+
m = m[0].split(/\s*,\s*/);
160+
return ['rule', m];
161161
}
162162
}

lib/parser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ module.exports = function(str) {
9191
next();
9292
while (!is('outdent')) {
9393
var tok = next();
94-
prop[2] += ' ' + tok[1];
94+
prop[2] += ' ' + tok[1].join(', ');
9595
}
9696
expect('outdent');
9797
}

test/cases/combinations.css

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
ol,
3+
ul
4+
margin: 0
5+
li
6+
a
7+
color: blue
8+
9+
@media print
10+
.content
11+
ul
12+
li.first,
13+
li.last,
14+
li.odd
15+
display: none
16+
body
17+
padding: 0
18+
19+
ul,
20+
ol
21+
li
22+
a
23+
color: blue

test/cases/combinations.out.css

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
ol ,
2+
ul {
3+
margin: 0;
4+
}
5+
6+
ol li a,
7+
ul li a{
8+
color: blue;
9+
}
10+
11+
@media print {
12+
.content ul li.first,
13+
.content ul li.last,
14+
.content ul li.odd {
15+
display: none;
16+
}
17+
body {
18+
padding: 0;
19+
}
20+
ul li a,
21+
ol li a {
22+
color: blue;
23+
}
24+
}

test/cases/comments.css

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
// foo
3+
button
4+
// bar
5+
color: #eee
6+
// bar
7+
8+
9+
10+
// baz
11+
background: blue

test/cases/comments.out.css

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
button {
2+
color: #eee;
3+
background: blue;
4+
}

test/cases/media.out.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ body {
33
}
44

55
@media print {
6-
body {
6+
body {
77
padding: 0;
88
}
99
ul li a {

test/cases/multiline.css

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
button
3+
border-radius: 5px
4+
padding: 5px 10px
5+
box-shadow:
6+
0 0 3px red,
7+
0 0 10px green,
8+
inset 0 0 3px blue
9+
color: blue

test/cases/multiline.out.css

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
button {
2+
border-radius: 5px;
3+
padding: 5px 10px;
4+
box-shadow: 0 0 3px red, 0 0 10px green, inset 0 0 3px blue;
5+
color: blue;
6+
}

test/cases/nesting.out.css

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ body {
22
padding: 50px;
33
}
44

5-
body ul li a {
5+
body ul li a{
66
color: blue;
77
}
88

9-
body ul li {
9+
body ul li{
1010
list-style: none;
1111
}
1212

13-
body ul {
13+
body ul{
1414
margin: 0;
1515
padding: 0;
1616
}

test/cases/parent.out.css

-14
Original file line numberDiff line numberDiff line change
@@ -1,14 +0,0 @@
1-
ul {
2-
}
3-
4-
ul li:hover {
5-
background: white;
6-
}
7-
8-
ul li:active {
9-
background: #ddd;
10-
}
11-
12-
ul li {
13-
background: #eee;
14-
}

0 commit comments

Comments
 (0)