163 lines · 3.8 KB · JavaScript
RawDownload
 /*! * Connect - compiler * Copyright(c) 2010 Sencha Inc. * Copyright(c) 2011 TJ Holowaychuk * MIT Licensed */ /** * Module dependencies. */ var fs = require('fs')  , path = require('path')  , parse = require('url').parse; /** * Require cache. */ var cache = {}; /** * Setup compiler. * * Options: * *   - `src`     Source directory, defaults to **CWD**. *   - `dest`    Destination directory, defaults `src`. *   - `enable`  Array of enabled compilers. * * Compilers: * *   - `sass`   Compiles sass to css *   - `less`   Compiles less to css *   - `coffeescript`   Compiles coffee to js * * @param {Object} options * @api public */ exports = module.exports = function compiler(options){  options = options || {};   var srcDir = options.src || process.cwd()    , destDir = options.dest || srcDir    , enable = options.enable;   if (!enable || enable.length === 0) {    throw new Error('compiler\'s "enable" option is not set, nothing will be compiled.');  }   return function compiler(req, res, next){    if ('GET' != req.method) return next();    var pathname = parse(req.url).pathname;    for (var i = 0, len = enable.length; i < len; ++i) {      var name = enable[i]        , compiler = compilers[name];      if (compiler.match.test(pathname)) {        var src = (srcDir + pathname).replace(compiler.match, compiler.ext)          , dest = destDir + pathname;         // Compare mtimes        fs.stat(src, function(err, srcStats){          if (err) {            if ('ENOENT' == err.code) {              next();            } else {              next(err);            }          } else {            fs.stat(dest, function(err, destStats){              if (err) {                // Oh snap! it does not exist, compile it                if ('ENOENT' == err.code) {                  compile();                } else {                  next(err);                }              } else {                // Source has changed, compile it                if (srcStats.mtime > destStats.mtime) {                  compile();                } else {                  // Defer file serving                  next();                }              }            });          }        });         // Compile to the destination        function compile() {          fs.readFile(src, 'utf8', function(err, str){            if (err) {              next(err);            } else {              compiler.compile(str, function(err, str){                if (err) {                  next(err);                } else {                  fs.writeFile(dest, str, 'utf8', function(err){                    next(err);                  });                }              });            }          });        }        return;      }    }    next();  };}; /** * Bundled compilers: * *  - [sass](http://github.com/visionmedia/sass.js) to _css_ *  - [less](http://github.com/cloudhead/less.js) to _css_ *  - [coffee](http://github.com/jashkenas/coffee-script) to _js_ */ var compilers = exports.compilers = {  sass: {    match: /\.css$/,    ext: '.sass',    compile: function(str, fn){      var sass = cache.sass || (cache.sass = require('sass'));      try {        fn(null, sass.render(str));      } catch (err) {        fn(err);      }    }  },  less: {    match: /\.css$/,    ext: '.less',    compile: function(str, fn){      var less = cache.less || (cache.less = require('less'));      try {        less.render(str, fn);      } catch (err) {        fn(err);      }    }  },  coffeescript: {    match: /\.js$/,    ext: '.coffee',    compile: function(str, fn){      var coffee = cache.coffee || (cache.coffee = require('coffee-script'));      try {        fn(null, coffee.compile(str));      } catch (err) {        fn(err);      }    }  }};