1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | var Parser = require('./parser')
|
13 | , EventEmitter = require('events').EventEmitter
|
14 | , Evaluator = require('./visitor/evaluator')
|
15 | , Normalizer = require('./visitor/normalizer')
|
16 | , events = new EventEmitter
|
17 | , utils = require('./utils')
|
18 | , nodes = require('./nodes')
|
19 | , join = require('path').join;
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | module.exports = Renderer;
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | function Renderer(str, options) {
|
36 | options = options || {};
|
37 | options.globals = options.globals || {};
|
38 | options.functions = options.functions || {};
|
39 | options.imports = [join(__dirname, 'functions')];
|
40 | options.paths = options.paths || [];
|
41 | options.filename = options.filename || 'stylus';
|
42 | options.Evaluator = options.Evaluator || Evaluator;
|
43 | this.options = options;
|
44 | this.str = str;
|
45 | this.events = events;
|
46 | };
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | Renderer.prototype.__proto__ = EventEmitter.prototype;
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | module.exports.events = events;
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 | Renderer.prototype.render = function(fn){
|
68 | var parser = this.parser = new Parser(this.str, this.options);
|
69 | try {
|
70 | nodes.filename = this.options.filename;
|
71 |
|
72 | var ast = parser.parse();
|
73 |
|
74 |
|
75 | this.evaluator = new this.options.Evaluator(ast, this.options);
|
76 | this.nodes = nodes;
|
77 | this.evaluator.renderer = this;
|
78 | ast = this.evaluator.evaluate();
|
79 |
|
80 |
|
81 | var normalizer = new Normalizer(ast, this.options);
|
82 | ast = normalizer.normalize();
|
83 |
|
84 |
|
85 | var compiler = this.options.sourcemap
|
86 | ? new (require('./visitor/sourcemapper'))(ast, this.options)
|
87 | : new (require('./visitor/compiler'))(ast, this.options)
|
88 | , css = compiler.compile();
|
89 |
|
90 |
|
91 | if (this.options.sourcemap) this.sourcemap = compiler.map.toJSON();
|
92 |
|
93 | var listeners = this.listeners('end');
|
94 | if (fn) listeners.push(fn);
|
95 | for (var i = 0, len = listeners.length; i < len; i++) {
|
96 | var ret = listeners[i](null, css);
|
97 | if (ret) css = ret;
|
98 | }
|
99 | if (!fn) return css;
|
100 | } catch (err) {
|
101 | var options = {};
|
102 | options.input = err.input || this.str;
|
103 | options.filename = err.filename || this.options.filename;
|
104 | options.lineno = err.lineno || parser.lexer.prev.lineno;
|
105 | options.column = err.column || parser.lexer.prev.column;
|
106 | if (!fn) throw utils.formatException(err, options);
|
107 | fn(utils.formatException(err, options));
|
108 | }
|
109 | };
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 | Renderer.prototype.deps = function(filename){
|
120 | if (filename) this.options.filename = filename;
|
121 |
|
122 | var DepsResolver = require('./visitor/deps-resolver')
|
123 | , parser = new Parser(this.str, this.options);
|
124 |
|
125 | try {
|
126 | nodes.filename = this.options.filename;
|
127 |
|
128 | var ast = parser.parse()
|
129 | , resolver = new DepsResolver(ast, this.options);
|
130 |
|
131 |
|
132 | return resolver.resolve();
|
133 | } catch (err) {
|
134 | var options = {};
|
135 | options.input = err.input || this.str;
|
136 | options.filename = err.filename || this.options.filename;
|
137 | options.lineno = err.lineno || parser.lexer.prev.lineno;
|
138 | options.column = err.column || parser.lexer.prev.column;
|
139 | throw utils.formatException(err, options);
|
140 | }
|
141 | };
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 | Renderer.prototype.set = function(key, val){
|
153 | this.options[key] = val;
|
154 | return this;
|
155 | };
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | Renderer.prototype.get = function(key){
|
166 | return this.options[key];
|
167 | };
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | Renderer.prototype.include = function(path){
|
178 | this.options.paths.push(path);
|
179 | return this;
|
180 | };
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | Renderer.prototype.use = function(fn){
|
194 | fn.call(this, this);
|
195 | return this;
|
196 | };
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | Renderer.prototype.define = function(name, fn, raw){
|
210 | fn = utils.coerce(fn, raw);
|
211 |
|
212 | if (fn.nodeName) {
|
213 | this.options.globals[name] = fn;
|
214 | return this;
|
215 | }
|
216 |
|
217 |
|
218 | this.options.functions[name] = fn;
|
219 | if (undefined != raw) fn.raw = raw;
|
220 | return this;
|
221 | };
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 | Renderer.prototype.import = function(file){
|
232 | this.options.imports.push(file);
|
233 | return this;
|
234 | };
|
235 |
|
236 |
|