Skip to content

Commit 0f123d1

Browse files
andreypopptj
authored andcommitted
Factor out common compiler code
1 parent 7a84c84 commit 0f123d1

File tree

3 files changed

+101
-146
lines changed

3 files changed

+101
-146
lines changed

lib/compiler.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
var SourceMapGenerator = require('source-map').SourceMapGenerator;
2+
3+
module.exports = Compiler;
4+
5+
function Compiler(options) {
6+
options = options || {};
7+
this.map = new SourceMapGenerator({file: options.filename || 'generated.css'});
8+
this.position = {line: 1, column: 1};
9+
}
10+
11+
/**
12+
* Update current position according to `str` being emitted
13+
*/
14+
Compiler.prototype.updatePosition = function(str) {
15+
var lines = str.match(/\n/g);
16+
if (lines) this.position.line += lines.length;
17+
var i = str.lastIndexOf('\n');
18+
this.position.column = ~i ? str.length - i : this.position.column + str.length;
19+
}
20+
21+
/**
22+
* Emit `str` and update current position, use original source `pos` to
23+
* construct source mapping.
24+
*/
25+
26+
Compiler.prototype.emit = function(str, pos, startOnly) {
27+
if (pos && pos.start) {
28+
this.map.addMapping({
29+
generated: {
30+
line: this.position.line,
31+
column: Math.max(this.position.column - 1, 0)
32+
},
33+
source: 'source.css',
34+
original: {
35+
line: pos.start.line,
36+
column: pos.start.column - 1
37+
}
38+
});
39+
}
40+
41+
this.updatePosition(str);
42+
43+
if (!startOnly && pos && pos.end) {
44+
this.map.addMapping({
45+
generated: {
46+
line: this.position.line,
47+
column: Math.max(this.position.column - 1, 0)
48+
},
49+
source: 'source.css',
50+
original: {
51+
line: pos.end.line,
52+
column: pos.end.column - 1
53+
}
54+
});
55+
}
56+
57+
return str;
58+
}
59+
60+
61+
/**
62+
* Visit `node`.
63+
*/
64+
65+
Compiler.prototype.visit = function(node){
66+
return this[node.type](node);
67+
};
68+
69+
/**
70+
* Map visit over array of `nodes`, optionally using a `delim`
71+
*/
72+
Compiler.prototype.mapVisit = function(nodes, delim){
73+
delim = delim || '';
74+
var result = '';
75+
for (var i = 0, length = nodes.length; i < length; i++) {
76+
result += this.visit(nodes[i]);
77+
if (delim && i < length - 1) result += this.emit(delim);
78+
}
79+
return result;
80+
};

lib/compress.js

Lines changed: 10 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var SourceMapGenerator = require('source-map').SourceMapGenerator;
1+
var CompilerBase = require('./compiler');
22

33
/**
44
* Expose compiler.
@@ -11,55 +11,10 @@ module.exports = Compiler;
1111
*/
1212

1313
function Compiler(options) {
14-
options = options || {};
15-
this.map = new SourceMapGenerator({file: options.filename || 'generated.css'});
16-
this.position = {line: 1, column: 1};
14+
CompilerBase.call(this, options);
1715
}
1816

19-
Compiler.prototype.updatePosition = function(str) {
20-
var lines = str.match(/\n/g);
21-
if (lines) this.position.line += lines.length;
22-
var i = str.lastIndexOf('\n');
23-
this.position.column = ~i ? str.length - i : this.position.column + str.length;
24-
}
25-
26-
/**
27-
* Emit string and update current position
28-
*/
29-
30-
Compiler.prototype.emit = function(str, pos, startOnly) {
31-
if (pos && pos.start) {
32-
this.map.addMapping({
33-
generated: {
34-
line: this.position.line,
35-
column: Math.max(this.position.column - 1, 0)
36-
},
37-
source: 'source.css',
38-
original: {
39-
line: pos.start.line,
40-
column: pos.start.column - 1
41-
}
42-
});
43-
}
44-
45-
this.updatePosition(str);
46-
47-
if (!startOnly && pos && pos.end) {
48-
this.map.addMapping({
49-
generated: {
50-
line: this.position.line,
51-
column: Math.max(this.position.column - 1, 0)
52-
},
53-
source: 'source.css',
54-
original: {
55-
line: pos.end.line,
56-
column: pos.end.column - 1
57-
}
58-
});
59-
}
60-
61-
return str;
62-
}
17+
Compiler.prototype = new CompilerBase();
6318

6419
/**
6520
* Compile `node`.
@@ -71,24 +26,6 @@ Compiler.prototype.compile = function(node){
7126
.join('');
7227
};
7328

74-
/**
75-
* Visit `node`.
76-
*/
77-
78-
Compiler.prototype.visit = function(node){
79-
return this[node.type](node);
80-
};
81-
82-
Compiler.prototype.visitMap = function(nodes, join){
83-
join = join || '';
84-
var result = '';
85-
for (var i = 0, length = nodes.length; i < length; i++) {
86-
result += this.visit(nodes[i]);
87-
if (i < length - 1) result += this.emit(join);
88-
}
89-
return result;
90-
};
91-
9229
/**
9330
* Visit comment node.
9431
*/
@@ -112,7 +49,7 @@ Compiler.prototype.import = function(node){
11249
Compiler.prototype.media = function(node){
11350
return this.emit('@media ' + node.media, node.position, true)
11451
+ this.emit('{')
115-
+ this.visitMap(node.rules)
52+
+ this.mapVisit(node.rules)
11653
+ this.emit('}');
11754
};
11855

@@ -125,7 +62,7 @@ Compiler.prototype.document = function(node){
12562

12663
return this.emit(doc, node.position, true)
12764
+ this.emit('{')
128-
+ this.visitMap(node.rules)
65+
+ this.mapVisit(node.rules)
12966
+ this.emit('}');
13067
};
13168

@@ -152,7 +89,7 @@ Compiler.prototype.namespace = function(node){
15289
Compiler.prototype.supports = function(node){
15390
return this.emit('@supports ' + node.supports, node.position, true)
15491
+ this.emit('{')
155-
+ this.visitMap(node.rules)
92+
+ this.mapVisit(node.rules)
15693
+ this.emit('}');
15794
};
15895

@@ -166,7 +103,7 @@ Compiler.prototype.keyframes = function(node){
166103
+ 'keyframes '
167104
+ node.name, node.position, true)
168105
+ this.emit('{')
169-
+ this.visitMap(node.keyframes)
106+
+ this.mapVisit(node.keyframes)
170107
+ this.emit('}');
171108
};
172109

@@ -179,7 +116,7 @@ Compiler.prototype.keyframe = function(node){
179116

180117
return this.emit(node.values.join(','), node.position, true)
181118
+ this.emit('{')
182-
+ this.visitMap(decls)
119+
+ this.mapVisit(decls)
183120
+ this.emit('}');
184121
};
185122

@@ -194,7 +131,7 @@ Compiler.prototype.page = function(node){
194131

195132
return this.emit('@page ' + sel, node.position, true)
196133
+ this.emit('{')
197-
+ this.visitMap(node.declarations)
134+
+ this.mapVisit(node.declarations)
198135
+ this.emit('}');
199136
};
200137

@@ -208,7 +145,7 @@ Compiler.prototype.rule = function(node){
208145

209146
return this.emit(node.selectors.join(','), node.position, true)
210147
+ this.emit('{')
211-
+ this.visitMap(decls)
148+
+ this.mapVisit(decls)
212149
+ this.emit('}');
213150
};
214151

lib/identity.js

Lines changed: 11 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var SourceMapGenerator = require('source-map').SourceMapGenerator;
1+
var CompilerBase = require('./compiler');
22

33
/**
44
* Expose compiler.
@@ -12,55 +12,11 @@ module.exports = Compiler;
1212

1313
function Compiler(options) {
1414
options = options || {};
15-
this.map = new SourceMapGenerator({file: options.filename || 'generated.css'});
16-
this.position = {line: 1, column: 0};
15+
CompilerBase.call(this, options);
1716
this.indentation = options.indent;
1817
}
1918

20-
Compiler.prototype.updatePosition = function(str) {
21-
var lines = str.match(/\n/g);
22-
if (lines) this.position.line += lines.length;
23-
var i = str.lastIndexOf('\n');
24-
this.position.column = ~i ? str.length - i : this.position.column + str.length;
25-
}
26-
27-
/**
28-
* Emit string and update current position
29-
*/
30-
31-
Compiler.prototype.emit = function(str, pos, startOnly) {
32-
if (pos && pos.start) {
33-
this.map.addMapping({
34-
generated: {
35-
line: this.position.line,
36-
column: Math.max(this.position.column - 1, 0)
37-
},
38-
source: 'source.css',
39-
original: {
40-
line: pos.start.line,
41-
column: pos.start.column - 1
42-
}
43-
});
44-
}
45-
46-
this.updatePosition(str);
47-
48-
if (!startOnly && pos && pos.end) {
49-
this.map.addMapping({
50-
generated: {
51-
line: this.position.line,
52-
column: Math.max(this.position.column - 1, 0)
53-
},
54-
source: 'source.css',
55-
original: {
56-
line: pos.end.line,
57-
column: pos.end.column - 1
58-
}
59-
});
60-
}
61-
62-
return str;
63-
}
19+
Compiler.prototype = new CompilerBase;
6420

6521
/**
6622
* Compile `node`.
@@ -70,30 +26,12 @@ Compiler.prototype.compile = function(node){
7026
return this.stylesheet(node);
7127
};
7228

73-
/**
74-
* Visit `node`.
75-
*/
76-
77-
Compiler.prototype.visit = function(node){
78-
return this[node.type](node);
79-
};
80-
81-
Compiler.prototype.visitMap = function(nodes, join){
82-
join = join || '';
83-
var result = '';
84-
for (var i = 0, length = nodes.length; i < length; i++) {
85-
result += this.visit(nodes[i]);
86-
if (i < length - 1) result += this.emit(join);
87-
}
88-
return result;
89-
};
90-
9129
/**
9230
* Visit stylesheet node.
9331
*/
9432

9533
Compiler.prototype.stylesheet = function(node){
96-
return this.visitMap(node.stylesheet.rules, '\n\n');
34+
return this.mapVisit(node.stylesheet.rules, '\n\n');
9735
};
9836

9937
/**
@@ -121,7 +59,7 @@ Compiler.prototype.media = function(node){
12159
+ this.emit(
12260
' {\n'
12361
+ this.indent(1))
124-
+ this.visitMap(node.rules, '\n\n')
62+
+ this.mapVisit(node.rules, '\n\n')
12563
+ this.emit(
12664
this.indent(-1)
12765
+ '\n}');
@@ -139,7 +77,7 @@ Compiler.prototype.document = function(node){
13977
' '
14078
+ ' {\n'
14179
+ this.indent(1))
142-
+ this.visitMap(node.rules, '\n\n')
80+
+ this.mapVisit(node.rules, '\n\n')
14381
+ this.emit(
14482
this.indent(-1)
14583
+ '\n}');
@@ -170,7 +108,7 @@ Compiler.prototype.supports = function(node){
170108
+ this.emit(
171109
' {\n'
172110
+ this.indent(1))
173-
+ this.visitMap(node.rules, '\n\n')
111+
+ this.mapVisit(node.rules, '\n\n')
174112
+ this.emit(
175113
this.indent(-1)
176114
+ '\n}');
@@ -185,7 +123,7 @@ Compiler.prototype.keyframes = function(node){
185123
+ this.emit(
186124
' {\n'
187125
+ this.indent(1))
188-
+ this.visitMap(node.keyframes, '\n')
126+
+ this.mapVisit(node.keyframes, '\n')
189127
+ this.emit(
190128
this.indent(-1)
191129
+ '}');
@@ -203,7 +141,7 @@ Compiler.prototype.keyframe = function(node){
203141
+ this.emit(
204142
' {\n'
205143
+ this.indent(1))
206-
+ this.visitMap(decls, '\n')
144+
+ this.mapVisit(decls, '\n')
207145
+ this.emit(
208146
this.indent(-1)
209147
+ '\n'
@@ -222,7 +160,7 @@ Compiler.prototype.page = function(node){
222160
return this.emit('@page ' + sel, node.position, true)
223161
+ this.emit('{\n')
224162
+ this.emit(this.indent(1))
225-
+ this.visitMap(node.declarations, '\n')
163+
+ this.mapVisit(node.declarations, '\n')
226164
+ this.emit(this.indent(-1))
227165
+ this.emit('\n}');
228166
};
@@ -239,7 +177,7 @@ Compiler.prototype.rule = function(node){
239177
return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position, true)
240178
+ this.emit(' {\n')
241179
+ this.emit(this.indent(1))
242-
+ this.visitMap(decls, '\n')
180+
+ this.mapVisit(decls, '\n')
243181
+ this.emit(this.indent(-1))
244182
+ this.emit('\n' + this.indent() + '}');
245183
};

0 commit comments

Comments
 (0)