]> git.cworth.org Git - obsolete/notmuch-web/blob - node_modules/express/node_modules/connect/lib/middleware/compiler.js
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / node_modules / connect / lib / middleware / compiler.js
1
2 /*!
3  * Connect - compiler
4  * Copyright(c) 2010 Sencha Inc.
5  * Copyright(c) 2011 TJ Holowaychuk
6  * MIT Licensed
7  */
8
9 /**
10  * Module dependencies.
11  */
12
13 var fs = require('fs')
14   , path = require('path')
15   , parse = require('url').parse;
16
17 /**
18  * Require cache.
19  */
20
21 var cache = {};
22
23 /**
24  * Setup compiler.
25  *
26  * Options:
27  *
28  *   - `src`     Source directory, defaults to **CWD**.
29  *   - `dest`    Destination directory, defaults `src`.
30  *   - `enable`  Array of enabled compilers.
31  *
32  * Compilers:
33  *
34  *   - `sass`   Compiles cass to css
35  *   - `less`   Compiles less to css
36  *   - `coffeescript`   Compiles coffee to js
37  *
38  * @param {Object} options
39  * @api public
40  */
41
42 exports = module.exports = function compiler(options){
43   options = options || {};
44
45   var srcDir = options.src || process.cwd()
46     , destDir = options.dest || srcDir
47     , enable = options.enable;
48
49   if (!enable || enable.length === 0) {
50     throw new Error('compiler\'s "enable" option is not set, nothing will be compiled.');
51   }
52
53   return function compiler(req, res, next){
54     if ('GET' != req.method) return next();
55     var pathname = parse(req.url).pathname;
56     for (var i = 0, len = enable.length; i < len; ++i) {
57       var name = enable[i]
58         , compiler = compilers[name];
59       if (compiler.match.test(pathname)) {
60         var src = (srcDir + pathname).replace(compiler.match, compiler.ext)
61           , dest = destDir + pathname;
62
63         // Compare mtimes
64         fs.stat(src, function(err, srcStats){
65           if (err) {
66             if ('ENOENT' == err.code) {
67               next();
68             } else {
69               next(err);
70             }
71           } else {
72             fs.stat(dest, function(err, destStats){
73               if (err) {
74                 // Oh snap! it does not exist, compile it
75                 if ('ENOENT' == err.code) {
76                   compile();
77                 } else {
78                   next(err);
79                 }
80               } else {
81                 // Source has changed, compile it
82                 if (srcStats.mtime > destStats.mtime) {
83                   compile();
84                 } else {
85                   // Defer file serving
86                   next();
87                 }
88               }
89             });
90           }
91         });
92
93         // Compile to the destination
94         function compile() {
95           fs.readFile(src, 'utf8', function(err, str){
96             if (err) {
97               next(err);
98             } else {
99               compiler.compile(str, function(err, str){
100                 if (err) {
101                   next(err);
102                 } else {
103                   fs.writeFile(dest, str, 'utf8', function(err){
104                     next(err);
105                   });
106                 }
107               });
108             }
109           });
110         }
111         return;
112       }
113     }
114     next();
115   };
116 };
117
118 /**
119  * Bundled compilers:
120  *
121  *  - [sass](http://github.com/visionmedia/sass.js) to _css_
122  *  - [less](http://github.com/cloudhead/less.js) to _css_
123  *  - [coffee](http://github.com/jashkenas/coffee-script) to _js_
124  */
125
126 var compilers = exports.compilers = {
127   sass: {
128     match: /\.css$/,
129     ext: '.sass',
130     compile: function(str, fn){
131       var sass = cache.sass || (cache.sass = require('sass'));
132       try {
133         fn(null, sass.render(str));
134       } catch (err) {
135         fn(err);
136       }
137     }
138   },
139   less: {
140     match: /\.css$/,
141     ext: '.less',
142     compile: function(str, fn){
143       var less = cache.less || (cache.less = require('less'));
144       try {
145         less.render(str, fn);
146       } catch (err) {
147         fn(err);
148       }
149     }
150   },
151   coffeescript: {
152     match: /\.js$/,
153     ext: '.coffee',
154     compile: function(str, fn){
155       var coffee = cache.coffee || (cache.coffee = require('coffee-script'));
156       try {
157         fn(null, coffee.compile(str));
158       } catch (err) {
159         fn(err);
160       }
161     }
162   }
163 };