1
+ var SourceMapGenerator = require ( 'source-map' ) . SourceMapGenerator ;
1
2
2
3
/**
3
4
* Expose compiler.
@@ -11,9 +12,56 @@ module.exports = Compiler;
11
12
12
13
function Compiler ( options ) {
13
14
options = options || { } ;
15
+ this . map = new SourceMapGenerator ( { file : options . filename || 'generated.css' } ) ;
16
+ this . position = { line : 1 , column : 0 } ;
14
17
this . indentation = options . indent ;
15
18
}
16
19
20
+ /**
21
+ * Emit string and update current position
22
+ */
23
+
24
+ Compiler . prototype . updatePosition = function ( str ) {
25
+ var lines = str . match ( / \n / g) ;
26
+ if ( lines ) this . position . line += lines . length ;
27
+ var i = str . lastIndexOf ( '\n' ) ;
28
+ this . position . column = ~ i ? str . length - i : this . position . column + str . length ;
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
+ }
64
+
17
65
/**
18
66
* Compile `node`.
19
67
*/
@@ -30,44 +78,53 @@ Compiler.prototype.visit = function(node){
30
78
return this [ node . type ] ( node ) ;
31
79
} ;
32
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
+
33
91
/**
34
92
* Visit stylesheet node.
35
93
*/
36
94
37
95
Compiler . prototype . stylesheet = function ( node ) {
38
- return node . stylesheet
39
- . rules . map ( this . visit , this )
40
- . join ( '\n\n' ) ;
96
+ return this . visitMap ( node . stylesheet . rules , '\n\n' ) ;
41
97
} ;
42
98
43
99
/**
44
100
* Visit comment node.
45
101
*/
46
102
47
103
Compiler . prototype . comment = function ( node ) {
48
- return this . indent ( ) + '/*' + node . comment + '*/' ;
104
+ return this . emit ( this . indent ( ) + '/*' + node . comment + '*/' , node . position ) ;
49
105
} ;
50
106
51
107
/**
52
108
* Visit import node.
53
109
*/
54
110
55
111
Compiler . prototype . import = function ( node ) {
56
- return '@import ' + node . import + ';' ;
112
+ return this . emit ( '@import ' + node . import + ';' , node . position ) ;
57
113
} ;
58
114
59
115
/**
60
116
* Visit media node.
61
117
*/
62
118
63
119
Compiler . prototype . media = function ( node ) {
64
- return '@media '
65
- + node . media
66
- + ' {\n'
67
- + this . indent ( 1 )
68
- + node . rules . map ( this . visit , this ) . join ( '\n\n' )
69
- + this . indent ( - 1 )
70
- + '\n}' ;
120
+ return this . emit ( '@media ' + node . media , node . position , true )
121
+ + this . emit (
122
+ ' {\n'
123
+ + this . indent ( 1 ) )
124
+ + this . visitMap ( node . rules , '\n\n' )
125
+ + this . emit (
126
+ this . indent ( - 1 )
127
+ + '\n}' ) ;
71
128
} ;
72
129
73
130
/**
@@ -77,58 +134,61 @@ Compiler.prototype.media = function(node){
77
134
Compiler . prototype . document = function ( node ) {
78
135
var doc = '@' + ( node . vendor || '' ) + 'document ' + node . document ;
79
136
80
- return doc + ' '
81
- + ' {\n'
82
- + this . indent ( 1 )
83
- + node . rules . map ( this . visit , this ) . join ( '\n\n' )
84
- + this . indent ( - 1 )
85
- + '\n}' ;
137
+ return this . emit ( doc , node . position , true )
138
+ + this . emit (
139
+ ' '
140
+ + ' {\n'
141
+ + this . indent ( 1 ) )
142
+ + this . visitMap ( node . rules , '\n\n' )
143
+ + this . emit (
144
+ this . indent ( - 1 )
145
+ + '\n}' ) ;
86
146
} ;
87
147
88
148
/**
89
149
* Visit charset node.
90
150
*/
91
151
92
152
Compiler . prototype . charset = function ( node ) {
93
- return '@charset ' + node . charset + ';\n' ;
153
+ return this . emit ( '@charset ' + node . charset + ';' , node . position ) ;
94
154
} ;
95
155
96
156
/**
97
157
* Visit namespace node.
98
158
*/
99
159
100
160
Compiler . prototype . namespace = function ( node ) {
101
- return '@namespace ' + node . namespace + ';\n' ;
161
+ return this . emit ( '@namespace ' + node . namespace + ';' , node . position ) ;
102
162
} ;
103
163
104
164
/**
105
165
* Visit supports node.
106
166
*/
107
167
108
168
Compiler . prototype . supports = function ( node ) {
109
- return '@supports '
110
- + node . supports
111
- + ' {\n'
112
- + this . indent ( 1 )
113
- + node . rules . map ( this . visit , this ) . join ( '\n\n' )
114
- + this . indent ( - 1 )
115
- + '\n}' ;
169
+ return this . emit ( '@supports ' + node . supports , node . position , true )
170
+ + this . emit (
171
+ ' {\n'
172
+ + this . indent ( 1 ) )
173
+ + this . visitMap ( node . rules , '\n\n' )
174
+ + this . emit (
175
+ this . indent ( - 1 )
176
+ + '\n}' ) ;
116
177
} ;
117
178
118
179
/**
119
180
* Visit keyframes node.
120
181
*/
121
182
122
183
Compiler . prototype . keyframes = function ( node ) {
123
- return '@'
124
- + ( node . vendor || '' )
125
- + 'keyframes '
126
- + node . name
127
- + ' {\n'
128
- + this . indent ( 1 )
129
- + node . keyframes . map ( this . visit , this ) . join ( '\n' )
130
- + this . indent ( - 1 )
131
- + '}' ;
184
+ return this . emit ( '@' + ( node . vendor || '' ) + 'keyframes ' + node . name , node . position , true )
185
+ + this . emit (
186
+ ' {\n'
187
+ + this . indent ( 1 ) )
188
+ + this . visitMap ( node . keyframes , '\n' )
189
+ + this . emit (
190
+ this . indent ( - 1 )
191
+ + '}' ) ;
132
192
} ;
133
193
134
194
/**
@@ -138,13 +198,16 @@ Compiler.prototype.keyframes = function(node){
138
198
Compiler . prototype . keyframe = function ( node ) {
139
199
var decls = node . declarations ;
140
200
141
- return this . indent ( )
142
- + node . values . join ( ', ' )
143
- + ' {\n'
144
- + this . indent ( 1 )
145
- + decls . map ( this . visit , this ) . join ( '\n' )
146
- + this . indent ( - 1 )
147
- + '\n' + this . indent ( ) + '}\n' ;
201
+ return this . emit ( this . indent ( ) )
202
+ + this . emit ( node . values . join ( ', ' ) , node . position , true )
203
+ + this . emit (
204
+ ' {\n'
205
+ + this . indent ( 1 ) )
206
+ + this . visitMap ( decls , '\n' )
207
+ + this . emit (
208
+ this . indent ( - 1 )
209
+ + '\n'
210
+ + this . indent ( ) + '}\n' ) ;
148
211
} ;
149
212
150
213
/**
@@ -156,12 +219,12 @@ Compiler.prototype.page = function(node){
156
219
? node . selectors . join ( ', ' ) + ' '
157
220
: '' ;
158
221
159
- return '@page ' + sel
160
- + '{\n'
161
- + this . indent ( 1 )
162
- + node . declarations . map ( this . visit , this ) . join ( '\n' )
163
- + this . indent ( - 1 )
164
- + '\n}' ;
222
+ return this . emit ( '@page ' + sel , node . position , true )
223
+ + this . emit ( '{\n' )
224
+ + this . emit ( this . indent ( 1 ) )
225
+ + this . visitMap ( node . declarations , '\n' )
226
+ + this . emit ( this . indent ( - 1 ) )
227
+ + this . emit ( '\n}' ) ;
165
228
} ;
166
229
167
230
/**
@@ -173,20 +236,24 @@ Compiler.prototype.rule = function(node){
173
236
var decls = node . declarations ;
174
237
if ( ! decls . length ) return '' ;
175
238
176
- return node . selectors . map ( function ( s ) { return indent + s } ) . join ( ',\n' )
177
- + ' {\n'
178
- + this . indent ( 1 )
179
- + decls . map ( this . visit , this ) . join ( '\n' )
180
- + this . indent ( - 1 )
181
- + '\n' + this . indent ( ) + '}' ;
239
+ return this . emit ( node . selectors . map ( function ( s ) { return indent + s } ) . join ( ',\n' ) , node . position , true )
240
+ + this . emit ( ' {\n' )
241
+ + this . emit ( this . indent ( 1 ) )
242
+ + this . visitMap ( decls , '\n' )
243
+ + this . emit ( this . indent ( - 1 ) )
244
+ + this . emit ( '\n' + this . indent ( ) + '}' ) ;
182
245
} ;
183
246
184
247
/**
185
248
* Visit declaration node.
186
249
*/
187
250
188
251
Compiler . prototype . declaration = function ( node ) {
189
- return this . indent ( ) + node . property + ': ' + node . value + ';' ;
252
+ return this . emit ( this . indent ( ) )
253
+ + this . emit ( node . property , node . position )
254
+ + this . emit ( ': ' )
255
+ + this . emit ( node . value , node . position )
256
+ + this . emit ( ';' ) ;
190
257
} ;
191
258
192
259
/**
0 commit comments