UNPKG

giles

Version:

a next-gen language watcher/compiler for pre-processed languages

434 lines (399 loc) 12.4 kB
// Generated by CoffeeScript 1.6.1 var Giles, coffee, connect, fs, giles, iced, jade, log, markdown, path, stylus, _ref, _this = this; fs = require('fs'); path = require('path'); log = require('./log'); connect = require('connect'); Giles = (function() { function Giles() { var _this = this; this.connect = function(dir) { return Giles.prototype.connect.apply(_this, arguments); }; this.compilerMap = {}; this.reverseCompilerMap = {}; this.ignored = []; this.locals = {}; this.routes = {}; } Giles.prototype.extendLocals = function(dynLocals) { var key, locals, value, _ref; locals = {}; _ref = this.locals; for (key in _ref) { value = _ref[key]; locals[key] = value; } for (key in dynLocals) { value = dynLocals[key]; locals[key] = value; } return locals; }; Giles.prototype.connect = function(dir) { var _this = this; return function(req, res, next) { var args, dynLocals, file, fullFilePath, locals, route, _ref, _ref1; _ref = req.url.split('?'), route = _ref[0], args = _ref[1]; locals = _this.locals; if (route === '/') { route = '/index.html'; } if (_this.routes[route]) { file = _this.routes[route].source; dynLocals = _this.routes[route].locals; if (dynLocals) { locals = _this.extendLocals(dynLocals); } } else { _ref1 = (dir + route).split("?"), fullFilePath = _ref1[0], args = _ref1[1]; file = _this.reverseLookup(fullFilePath); } if (file) { return _this.compileFile(file, locals, {}, function(result) { var extname, relInput, relOutput; relInput = path.relative(process.cwd(), file); relOutput = path.relative(process.cwd(), result.outputFile); if (result.exists) { log.notice("up to date " + relOutput + " from " + relInput); } else { log.notice("compiled " + relInput + " into " + relOutput); log.encourage(); } extname = path.extname(relOutput); if (extname === '.css') { res.setHeader("Content-Type", "text/css"); } else if (extname === '.html') { res.setHeader("Content-Type", "text/html"); } else if (extname === '.js') { res.setHeader("Content-Type", "application/javascript"); } return res.end(result.content); }); } else { return next(); } }; }; Giles.prototype.quiet = function() { return log.quiet(true); }; Giles.prototype.get = function(endpoint, source, locals) { return this.routes[endpoint] = { source: source, locals: locals }; }; Giles.prototype.server = function(dir, opts) { var port; port = opts['port'] || 2255; this.app = connect().use(this.connect(dir)).use(connect["static"](dir)).listen(port); return log.notice("Giles is watching on port " + port); }; Giles.prototype.reverseLookup = function(file) { var ext, extension, foundFile, name, numberFound, pwd, relativeName, _i, _len, _ref, _ref1; _ref = this.parseFileName(file), name = _ref[0], ext = _ref[1]; pwd = process.cwd(); relativeName = path.relative(pwd, name); numberFound = 0; foundFile = null; if (this.reverseCompilerMap[ext]) { _ref1 = this.reverseCompilerMap[ext]; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { extension = _ref1[_i]; if (fs.existsSync(name + extension)) { foundFile = name + extension; numberFound += 1; } } } if (numberFound > 1) { throw "You can only have one file that can compile into " + file + " - you have " + numberFound + " - " + this.reverseCompilerMap[ext]; } return foundFile; }; Giles.prototype.crawl = function(dir, onFile) { var handlePath, _this = this; handlePath = function(resource) { return function(err, stats) { if (err) { return log.error(err); } else if (stats.isFile()) { return onFile(resource); } else if (stats.isDirectory()) { return _this.crawl(resource, onFile); } else { log.error("Could not determine file " + filename); return log.error(stats); } }; }; return fs.readdir(dir, function(err, files) { var file, resource, _i, _len, _results; if (err) { log.error("cannot read dir"); return log.error(err); } else { _results = []; for (_i = 0, _len = files.length; _i < _len; _i++) { file = files[_i]; resource = dir + '/' + file; _results.push(fs.stat(resource, handlePath(resource))); } return _results; } }); }; Giles.prototype.addCompiler = function(extensions, target, callback) { var compiler, ext, _i, _j, _len, _len1, _results; compiler = { callback: callback, extension: target }; if (typeof extensions === 'object') { for (_i = 0, _len = extensions.length; _i < _len; _i++) { ext = extensions[_i]; this.compilerMap[ext] = compiler; } if (!this.reverseCompilerMap[target]) { this.reverseCompilerMap[target] = []; } _results = []; for (_j = 0, _len1 = extensions.length; _j < _len1; _j++) { ext = extensions[_j]; _results.push(this.reverseCompilerMap[target].push(ext)); } return _results; } else { this.compilerMap[extensions] = compiler; if (!this.reverseCompilerMap[target]) { this.reverseCompilerMap[target] = []; } return this.reverseCompilerMap[target].push(extensions); } }; Giles.prototype.process = function(dir, onFile) { var stats; stats = fs.statSync(dir); if (stats.isDirectory()) { return this.crawl(dir, onFile); } else if (stats.isFile()) { return onFile(dir); } else { return log.error(dir + " is not a directory or file"); } }; Giles.prototype.rmFile = function(file) { return fs.unlink(file, function(err) { if (err) { return log.error("Failed to remove: " + file, err); } }); }; Giles.prototype.clean = function(dir, opts) { var fullPath, route, source, _ref, _this = this; _ref = this.routes; for (route in _ref) { opts = _ref[route]; source = opts.source; fullPath = path.resolve(process.cwd() + route); log.notice("cleaning " + fullPath); this.rmFile(fullPath); } return this.process(dir, function(f) { var sourceFile; sourceFile = _this.reverseLookup(f); if (fs.existsSync(sourceFile)) { log.notice("Cleaning: " + f); return _this.rmFile(f); } }); }; Giles.prototype.build = function(dir, opts) { var fullPath, locals, route, source, _ref, _this = this; _ref = this.routes; for (route in _ref) { opts = _ref[route]; source = opts.source; locals = this.locals; if (opts.locals) { locals = this.extendLocals(opts.locals); } log.notice("building user-defined route " + route); fullPath = path.resolve(process.cwd() + route); this.compile(source, locals, { outputFile: fullPath }); } return this.process(dir, function(f) { return _this.compile(f); }); }; Giles.prototype.ignore = function(types) { return this.ignored = types; }; Giles.prototype.compile = function(file, locals, options) { var result, _this = this; if (this.isIgnored(file)) { return; } locals = locals || this.locals; return result = this.compileFile(file, locals, options, function(result) { var relInput, relOutput; relInput = path.relative(process.cwd(), file); relOutput = path.relative(process.cwd(), result.outputFile); if (result.exists) { log.notice("up to date " + relOutput + " from " + relInput); } else { log.notice("compiled " + relInput + " into " + relOutput); log.encourage(); } if (!result) { return; } return fs.writeFileSync(result.outputFile, result.content, 'utf8'); }); }; Giles.prototype.compileFile = function(file, locals, options, cb) { var compiler, content, cwd, ext, outputContent, outputFile, prefix, _ref; _ref = this.parseFileName(file), prefix = _ref[0], ext = _ref[1]; compiler = this.compilerMap[ext]; if (!compiler) { return; } if (!fs.existsSync(file)) { console.error("Could not find source file " + file); return; } outputFile = prefix + compiler.extension; if (options != null ? options.outputFile : void 0) { outputFile = options.outputFile; } content = fs.readFileSync(file, 'utf8'); outputContent = null; if (fs.existsSync(outputFile)) { outputContent = fs.readFileSync(outputFile, 'utf8'); } cwd = process.cwd(); try { return compiler.callback(content, file, locals, function(output) { if (output === outputContent) { return cb({ content: outputContent, outputFile: outputFile, inputFile: file, originalContent: content, exists: true }); } else { return cb({ outputFile: outputFile, content: output, inputFile: file, originalContent: content }); } }); } catch (error) { log.error(error); log.error("stack trace:"); return log.error(error.stack.replace(cwd, ".")); } }; Giles.prototype.parseFileName = function(file) { var base, ext; ext = path.extname(file); base = file.substr(0, file.length - ext.length); return [base, ext]; }; Giles.prototype.isIgnored = function(name) { var filename, ignore, _i, _len, _ref; filename = name.split('/'); filename = filename[filename.length - 1]; if (/^_/.test(filename)) { return true; } _ref = this.ignored; for (_i = 0, _len = _ref.length; _i < _len; _i++) { ignore = _ref[_i]; if (ignore.test(name)) { return true; } } return false; }; return Giles; })(); _ref = [], stylus = _ref[0], coffee = _ref[1], iced = _ref[2], jade = _ref[3], markdown = _ref[4]; giles = new Giles(); giles.addCompiler([".styl", ".stylus"], '.css', function(contents, filename, options, output) { var key, styl, val, _i, _len; if (!stylus) { stylus = require('stylus'); } styl = stylus(contents); styl.set('filename', filename); styl.include(options.cwd); for (val = _i = 0, _len = options.length; _i < _len; val = ++_i) { key = options[val]; styl.define(key, val); } return stylus.render(contents, { filename: filename }, function(err, css) { if (err) { log.error("Could not render stylus file: " + filename); return log.error(err); } else { return output(css); } }); }); giles.addCompiler(['.coffee', '.cs'], '.js', function(contents, filename, options, output) { if (!coffee) { coffee = require('coffee-script'); } options.header = true; options.bare = false; if (options.scope) { delete options.scope; } return output(coffee.compile(contents, options)); }); giles.addCompiler('.iced', '.js', function(contents, filename, options, output) { var iced_output; if (!iced) { iced = require('iced-coffee-script'); } iced_output = iced.compile(contents, options); return output(iced_output); }); giles.addCompiler('.jade', '.html', function(contents, filename, options, output) { var compileOpts, compiled; if (!jade) { jade = require('jade'); } compileOpts = {}; compileOpts.filename = filename; compileOpts.pretty = true; try { compiled = jade.compile(contents, compileOpts)(options); return output(compiled); } catch (e) { output("<h1>Error compiling " + filename + "</h1><code><pre>" + e.message + e.stack + "</pre></code>"); throw e; } }); giles.addCompiler('.md', '.html', function(contents, filename, options, output) { var html; markdown = require("markdown-js"); html = markdown.encode(contents); return output(html); }); giles.ignore([/node_modules/, /.git/]); module.exports = giles;