1 |
|
2 | (function() {
|
3 | var Generator, async, coffee, eco, fs, less, path, util, _;
|
4 |
|
5 | eco = require('eco');
|
6 |
|
7 | path = require('path');
|
8 |
|
9 | fs = require('fs');
|
10 |
|
11 | util = require('util');
|
12 |
|
13 | _ = require('underscore');
|
14 |
|
15 | less = require('less');
|
16 |
|
17 | coffee = require('coffee-script');
|
18 |
|
19 | async = require('async');
|
20 |
|
21 | Generator = (function() {
|
22 |
|
23 | function Generator(options) {
|
24 | var l, url;
|
25 | this.options = _.extend({
|
26 | assetsDir: path.join(__dirname, "assets"),
|
27 | templatesDir: path.join(__dirname, "templates/beautiful-docs"),
|
28 | templates: {
|
29 | layout: 'layout.html',
|
30 | page: 'page.html',
|
31 | index: 'index.html'
|
32 | },
|
33 | baseUrl: '',
|
34 | noHeader: false,
|
35 | noToc: false
|
36 | }, options);
|
37 | url = this.options.baseUrl;
|
38 | l = url.length;
|
39 | if (l > 0 && url[l - l] !== '/') {
|
40 | this.options.baseUrl += '/';
|
41 | }
|
42 | }
|
43 |
|
44 | Generator.prototype.render = function(filename, vars, callback) {
|
45 | var _this = this;
|
46 | return fs.readFile(path.join(this.options.templatesDir, filename), function(err, data) {
|
47 | var html;
|
48 | if (err) {
|
49 | return callback(err);
|
50 | }
|
51 | html = eco.render(data.toString(), _.extend({}, _this.options, vars));
|
52 | return callback(null, html);
|
53 | });
|
54 | };
|
55 |
|
56 | Generator.prototype.mkdir = function(dir, callback) {
|
57 | var _this = this;
|
58 | return fs.exists(dir, function(exists) {
|
59 | if (exists) {
|
60 | return callback(null);
|
61 | }
|
62 | return _this.mkdir(path.dirname(dir), function(err) {
|
63 | if (err) {
|
64 | return callback(err);
|
65 | }
|
66 | return fs.mkdir(dir, callback);
|
67 | });
|
68 | });
|
69 | };
|
70 |
|
71 | Generator.prototype.copy = function(src, dest, callback) {
|
72 | return this.mkdir(path.dirname(dest), function(err) {
|
73 | var ins, outs;
|
74 | if (err) {
|
75 | return callback(err);
|
76 | }
|
77 | ins = fs.createReadStream(src);
|
78 | outs = fs.createWriteStream(dest);
|
79 | return util.pump(ins, outs, callback);
|
80 | });
|
81 | };
|
82 |
|
83 | Generator.prototype.generateIndex = function(title, manifests, filename, callback) {
|
84 | var categories, m, name, vars, _i, _len;
|
85 | if (callback == null) {
|
86 | callback = null;
|
87 | }
|
88 | categories = {};
|
89 | for (_i = 0, _len = manifests.length; _i < _len; _i++) {
|
90 | m = manifests[_i];
|
91 | name = m.category || 'All Projects';
|
92 | if (!categories[name]) {
|
93 | categories[name] = [];
|
94 | }
|
95 | categories[name].push(m);
|
96 | }
|
97 | vars = {
|
98 | title: title,
|
99 | categories: categories
|
100 | };
|
101 | return this.render(this.options.templates.index, vars, function(err, content) {
|
102 | if (err) {
|
103 | if (callback) {
|
104 | callback(err);
|
105 | }
|
106 | return;
|
107 | }
|
108 | return fs.writeFile(filename, content, callback);
|
109 | });
|
110 | };
|
111 |
|
112 | Generator.prototype.generate = function(manifest, destDir, callback) {
|
113 | var allContent, copyStylesheet, render, renderAll, renderFile, renderFiles,
|
114 | _this = this;
|
115 | if (callback == null) {
|
116 | callback = null;
|
117 | }
|
118 | allContent = '';
|
119 | render = function(filename, vars, callback) {
|
120 | return _this.render(filename, _.extend({
|
121 | manifest: manifest
|
122 | }, vars), callback);
|
123 | };
|
124 | renderFile = function(file, filename, cb) {
|
125 | var copyAsset;
|
126 | copyAsset = function(a, c) {
|
127 | return _this.copy(file.makeRelativeUri(a), path.join(destDir, a), c);
|
128 | };
|
129 | return render(_this.options.templates.page, {
|
130 | content: file.content
|
131 | }, function(err, content) {
|
132 | if (err) {
|
133 | return cb(err);
|
134 | }
|
135 | return render(_this.options.templates.layout, {
|
136 | content: content
|
137 | }, function(err, content) {
|
138 | if (err) {
|
139 | return cb(err);
|
140 | }
|
141 | return fs.writeFile(path.join(destDir, filename + '.html'), content, function(err) {
|
142 | if (err) {
|
143 | return cb(err);
|
144 | }
|
145 | return async.forEach(file.assets, copyAsset, cb);
|
146 | });
|
147 | });
|
148 | });
|
149 | };
|
150 | renderFiles = function(cb) {
|
151 | var file, i, lock, _ref, _results;
|
152 | lock = manifest.files.length;
|
153 | _ref = manifest.files;
|
154 | _results = [];
|
155 | for (i in _ref) {
|
156 | file = _ref[i];
|
157 | if (manifest.ignoreFirstFileForToc && i === 0) {
|
158 | continue;
|
159 | }
|
160 | allContent += file.content + "\n";
|
161 | _results.push(renderFile(file, file.slug, function() {
|
162 | if (--lock === 0) {
|
163 | return cb();
|
164 | }
|
165 | }));
|
166 | }
|
167 | return _results;
|
168 | };
|
169 | renderAll = function(cb) {
|
170 | var content;
|
171 | content = "<div id='content'>" + allContent + "</div>";
|
172 | return render(_this.options.templates.layout, {
|
173 | content: content
|
174 | }, function(err, content) {
|
175 | if (err) {
|
176 | return cb(err);
|
177 | }
|
178 | return fs.writeFile(path.join(destDir, 'all.html'), content, cb);
|
179 | });
|
180 | };
|
181 | copyStylesheet = function(cb) {
|
182 | var filename;
|
183 | if (!(manifest.options.css != null)) {
|
184 | return cb();
|
185 | }
|
186 | filename = manifest.options.css;
|
187 | if (filename.substr(0, 1) !== '/' && !filename.match(/^(https?):\/\//)) {
|
188 | return _this.copy(manifest.makeRelativeUri(filename), path.join(destDir, filename), cb);
|
189 | } else {
|
190 | return cb();
|
191 | }
|
192 | };
|
193 | return async.series([
|
194 | (function(cb) {
|
195 | return _this.mkdir(destDir, cb);
|
196 | }), (function(cb) {
|
197 | return renderFile(manifest.files[0], 'index', cb);
|
198 | }), renderFiles, renderAll, copyStylesheet
|
199 | ], function(err) {
|
200 | if (callback) {
|
201 | return callback(err);
|
202 | }
|
203 | });
|
204 | };
|
205 |
|
206 | Generator.prototype.copyAssets = function(destDir, srcDir, compileLessOrCoffee, callback) {
|
207 | var copyFile, handleFile, handleFiles,
|
208 | _this = this;
|
209 | if (srcDir == null) {
|
210 | srcDir = this.options.assetsDir;
|
211 | }
|
212 | if (compileLessOrCoffee == null) {
|
213 | compileLessOrCoffee = true;
|
214 | }
|
215 | if (callback == null) {
|
216 | callback = null;
|
217 | }
|
218 | if (typeof srcDir === 'function') {
|
219 | callback = srcDir;
|
220 | srcDir = this.options.assetsDir;
|
221 | }
|
222 | copyFile = function(pathname, filename, cb) {
|
223 | if (compileLessOrCoffee && path.extname(filename) === '.less') {
|
224 | return fs.readFile(pathname, function(err, data) {
|
225 | var target;
|
226 | if (err) {
|
227 | return cb(err);
|
228 | }
|
229 | target = path.join(destDir, path.basename(filename, path.extname(filename)) + '.css');
|
230 | return less.render(data.toString(), function(e, css) {
|
231 | return fs.writeFile(target, css, cb);
|
232 | });
|
233 | });
|
234 | } else if (compileLessOrCoffee && path.extname(filename) === '.coffee') {
|
235 | return fs.readFile(pathname, function(err, data) {
|
236 | var target;
|
237 | if (err) {
|
238 | return cb(err);
|
239 | }
|
240 | target = path.join(destDir, path.basename(filename, path.extname(filename)) + '.js');
|
241 | return fs.writeFile(target, coffee.compile(data.toString()), cb);
|
242 | });
|
243 | } else {
|
244 | return _this.copy(pathname, path.join(destDir, filename), cb);
|
245 | }
|
246 | };
|
247 | handleFile = function(filename, cb) {
|
248 | var pathname;
|
249 | pathname = path.join(srcDir, filename);
|
250 | return fs.stat(pathname, function(err, stat) {
|
251 | if (err) {
|
252 | return cb(err);
|
253 | }
|
254 | if (stat.isDirectory()) {
|
255 | return _this.copyAssets(path.join(destDir, filename), pathname, compileLessOrCoffee, cb);
|
256 | } else {
|
257 | return copyFile(pathname, filename, cb);
|
258 | }
|
259 | });
|
260 | };
|
261 | handleFiles = function(err, files, cb) {
|
262 | if (err) {
|
263 | return cb(err);
|
264 | }
|
265 | return async.forEach(files, handleFile, cb);
|
266 | };
|
267 | return async.series([
|
268 | (function(cb) {
|
269 | return _this.mkdir(destDir, cb);
|
270 | }), (function(cb) {
|
271 | return fs.readdir(srcDir, function(err, files) {
|
272 | return handleFiles(err, files, cb);
|
273 | });
|
274 | })
|
275 | ], function(err) {
|
276 | if (callback) {
|
277 | return callback(err);
|
278 | }
|
279 | });
|
280 | };
|
281 |
|
282 | return Generator;
|
283 |
|
284 | })();
|
285 |
|
286 | module.exports = Generator;
|
287 |
|
288 | }).call(this);
|