UNPKG

6.24 kBJavaScriptView Raw
1/*!
2 * Stylus - CSS to Stylus conversion
3 * Copyright (c) Automattic <developer.wordpress.com>
4 * MIT Licensed
5 */
6
7/**
8 * Convert the given `css` to Stylus source.
9 *
10 * @param {String} css
11 * @return {String}
12 * @api public
13 */
14
15module.exports = function(css){
16 return new Converter(css).stylus();
17};
18
19/**
20 * Initialize a new `Converter` with the given `css`.
21 *
22 * @param {String} css
23 * @api private
24 */
25
26function Converter(css) {
27 var parse = require('css-parse');
28 this.css = css;
29 this.root = parse(css, { position: false });
30 this.indents = 0;
31}
32
33/**
34 * Convert to Stylus.
35 *
36 * @return {String}
37 * @api private
38 */
39
40Converter.prototype.stylus = function(){
41 return this.visitRules(this.root.stylesheet.rules);
42};
43
44/**
45 * Return indent string.
46 *
47 * @return {String}
48 * @api private
49 */
50
51Converter.prototype.__defineGetter__('indent', function(){
52 return Array(this.indents + 1).join(' ');
53});
54
55/**
56 * Visit `node`.
57 *
58 * @param {*} node
59 * @return {String}
60 * @api private
61 */
62
63Converter.prototype.visit = function(node){
64 switch (node.type) {
65 case 'rule':
66 case 'comment':
67 case 'charset':
68 case 'namespace':
69 case 'media':
70 case 'import':
71 case 'document':
72 case 'keyframes':
73 case 'page':
74 case 'host':
75 case 'supports':
76 var name = node.type[0].toUpperCase() + node.type.slice(1);
77 return this['visit' + name](node);
78 case 'font-face':
79 return this.visitFontFace(node);
80 }
81};
82
83/**
84 * Visit the rules on `node`.
85 *
86 * @param {Array} node
87 * @return {String}
88 * @api private
89 */
90
91Converter.prototype.visitRules = function(node){
92 var buf = '';
93 for (var i = 0, len = node.length; i < len; ++i) {
94 buf += this.visit(node[i]);
95 }
96 return buf;
97};
98
99/**
100 * Visit FontFace `node`.
101 *
102 * @param {FontFace} node
103 * @return {String}
104 * @api private
105 */
106
107 Converter.prototype.visitFontFace = function(node){
108 var buf = this.indent + '@font-face';
109 buf += '\n';
110 ++this.indents;
111 for (var i = 0, len = node.declarations.length; i < len; ++i) {
112 buf += this.visitDeclaration(node.declarations[i]);
113 }
114 --this.indents;
115 return buf;
116 };
117
118/**
119 * Visit Media `node`.
120 *
121 * @param {Media} node
122 * @return {String}
123 * @api private
124 */
125
126Converter.prototype.visitMedia = function(node){
127 var buf = this.indent + '@media ' + node.media;
128 buf += '\n';
129 ++this.indents;
130 buf += this.visitRules(node.rules);
131 --this.indents;
132 return buf;
133};
134
135/**
136 * Visit Declaration `node`.
137 *
138 * @param {Declaration} node
139 * @return {String}
140 * @api private
141 */
142
143Converter.prototype.visitDeclaration = function(node){
144 if ('comment' == node.type) {
145 return this.visitComment(node);
146 } else {
147 var buf = this.indent + node.property + ': ' + node.value + '\n';
148 return buf;
149 }
150};
151
152/**
153 * Visit Rule `node`.`
154 *
155 * @param {Rule} node
156 * @return {String}
157 * @api private
158 */
159
160Converter.prototype.visitRule = function(node){
161 var buf = this.indent + node.selectors.join(',\n' + this.indent) + '\n';
162 ++this.indents;
163 for (var i = 0, len = node.declarations.length; i < len; ++i) {
164 buf += this.visitDeclaration(node.declarations[i]);
165 }
166 --this.indents;
167 return buf + '\n';
168};
169
170/**
171 * Visit Comment `node`.`
172 *
173 * @param {Comment} node
174 * @return {String}
175 * @api private
176 */
177
178Converter.prototype.visitComment = function(node){
179 var buf = this.indent + '/*' + node.comment + '*/';
180 return buf + '\n';
181};
182
183/**
184 * Visit Charset `node`.`
185 *
186 * @param {Charset} node
187 * @return {String}
188 * @api private
189 */
190
191Converter.prototype.visitCharset = function(node){
192 var buf = this.indent + '@charset ' + node.charset;
193 return buf + '\n';
194};
195
196/**
197 * Visit Namespace `node`.`
198 *
199 * @param {Namespace} node
200 * @return {String}
201 * @api private
202 */
203
204Converter.prototype.visitNamespace = function(node){
205 var buf = this.indent + '@namespace ' + node.namespace;
206 return buf + '\n';
207};
208
209/**
210 * Visit Import `node`.`
211 *
212 * @param {Import} node
213 * @return {String}
214 * @api private
215 */
216
217Converter.prototype.visitImport = function(node){
218 var buf = this.indent + '@import ' + node.import;
219 return buf + '\n';
220};
221
222/**
223 * Visit Document `node`.`
224 *
225 * @param {Document} node
226 * @return {String}
227 * @api private
228 */
229
230Converter.prototype.visitDocument = function(node){
231 var buf = this.indent + '@' + node.vendor + 'document ' + node.document;
232 buf += '\n';
233 ++this.indents;
234 buf += this.visitRules(node.rules);
235 --this.indents;
236 return buf;
237};
238
239/**
240 * Visit Keyframes `node`.`
241 *
242 * @param {Keyframes} node
243 * @return {String}
244 * @api private
245 */
246
247Converter.prototype.visitKeyframes = function(node){
248 var buf = this.indent + '@keyframes ' + node.name;
249 buf += '\n';
250 ++this.indents;
251 for (var i = 0, len = node.keyframes.length; i < len; ++i) {
252 buf += this.visitKeyframe(node.keyframes[i]);
253 }
254 --this.indents;
255 return buf;
256};
257
258/**
259 * Visit Keyframe `node`.`
260 *
261 * @param {Keyframe} node
262 * @return {String}
263 * @api private
264 */
265
266Converter.prototype.visitKeyframe = function(node){
267 var buf = this.indent + node.values.join(', ');
268 buf += '\n';
269 ++this.indents;
270 for (var i = 0, len = node.declarations.length; i < len; ++i) {
271 buf += this.visitDeclaration(node.declarations[i]);
272 }
273 --this.indents;
274 return buf;
275};
276
277/**
278 * Visit Page `node`.`
279 *
280 * @param {Page} node
281 * @return {String}
282 * @api private
283 */
284
285Converter.prototype.visitPage = function(node){
286 var buf = this.indent + '@page' + (node.selectors.length ? ' ' + node.selectors.join(', ') : '');
287 buf += '\n';
288 ++this.indents;
289 for (var i = 0, len = node.declarations.length; i < len; ++i) {
290 buf += this.visitDeclaration(node.declarations[i]);
291 }
292 --this.indents;
293 return buf;
294};
295
296/**
297 * Visit Supports `node`.`
298 *
299 * @param {Supports} node
300 * @return {String}
301 * @api private
302 */
303
304Converter.prototype.visitSupports = function(node){
305 var buf = this.indent + '@supports ' + node.supports;
306 buf += '\n';
307 ++this.indents;
308 buf += this.visitRules(node.rules);
309 --this.indents;
310 return buf;
311};
312
313/**
314 * Visit Host `node`.`
315 *
316 * @param {Host} node
317 * @return {String}
318 * @api private
319 */
320
321Converter.prototype.visitHost = function(node){
322 var buf = this.indent + '@host';
323 buf += '\n';
324 ++this.indents;
325 buf += this.visitRules(node.rules);
326 --this.indents;
327 return buf;
328};