1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | 1 1 1 1 1 1 1 1 2 2 2 2 2 20 2 1 1 3 2 2 2 2 2 2 20 10 10 2 2 | // vim: set shiftwidth=2: expandtab: 'use strict'; var fs = require('fs'); var async = require('async'); var findit = require('findit'); var jade = require('jade'); var path = require('path'); var helper = require('./helper'); // Find first file matching `re` in `dir`. var findFile = function(dir, re, cb) { fs.stat(dir, function(err, stat) { var files = fs.readdir(dir, function(err, files) { files = files.sort().filter(function(file) { return file.match(re); }); if (!files.length) cb(new Error('No file found.')); else cb(null, path.join(dir, files[0])); }); }); }; var getFiles = function(inPath, cb) { fs.stat(inPath, function(err, stat) { Iif (err != null) return cb(err); Iif (stat.isFile()) { cb(null, [ inPath ]); } else { var finder = findit(inPath); var files = []; finder.on('file', function(file) { files.push(file); }); finder.on('end', function() { cb(null, files); }); } }); }; var resourcesDir = __dirname + '/../share/'; // TODO Write unit tests for these module.exports = function(options) { // TODO: Cache each method result so that we can treat these as resources. return { template: function(cb) { fs.readFile(resourcesDir + 'docs.jade', 'utf8', function(err, contents) { if (err != null) return cb(err); cb(null, jade.compile(contents)); }); }, docs: function(cb) { async.parallel({ css: async.apply(fs.readFile, resourcesDir + 'docs.css', 'utf8'), js: function(cb) { async.parallel([ async.apply(fs.readFile, resourcesDir + 'docs.ui.js', 'utf8'), async.apply(fs.readFile, resourcesDir + 'docs.previews.js', 'utf8') ], function(err, res) { if (err != null) return cb(err); cb(null, res.join('')); }); } }, cb); }, // Extra JavaScript and CSS files to include in previews. previews: function(cb) { fs.readFile(resourcesDir + 'previews.js', 'utf8', function(err, js) { if (err != null) return cb(err); var code = { js: js, css: '' }; var files = options.include.filter(function(file) { return helper.inArray(['.css', '.js'], path.extname(file)); }); async.filter(files, path.exists, function(files) { async.reduce(files, code, function(tot, cur, cb) { fs.readFile(cur, 'utf8', function(err, contents) { if (err != null) return cb(err); tot[path.extname(cur).slice(1)] += contents; cb(null, tot); }); }, cb); }); }); }, // Find input files. files: function(cb) { async.reduce(options['in'], [], function(all, cur, cb) { getFiles(cur, function(err, files) { Iif (err != null) return cb(err); cb(null, all.concat(files)); }); }, function(err, files) { Iif (err != null) return cb(err); files = files.filter(function(file) { // No hidden files if (file.match(/(\/|^)\.[^\.\/]/)) return false; // Only supported file types Iif (!(path.extname(file) in helper.fileTypes)) return false; return true; }).sort(); Iif (!files.length) cb(new Error(errorMessages.noFiles + ' in path "' + options['in'] + '"')); cb(null, files); }); }, // Look for a README file. readme: function(cb) { findFile(options.basePath, /^readme\.m(ark)?d(own)?/i, function(err, file) { if (file != null && err == null) return read(file); findFile(process.cwd(), /^readme\.m(ark)?d(own)?/i, function(err, file) { if (err != null) file = resourcesDir + 'README.md'; read(file); }); }); var read = function(file) { fs.readFile(file, 'utf8', function(err, content) { if (err != null) cb(err); cb(null, content); }); }; } }; } |