UNPKG

tianma-unicorn

Version:

The Pegasus module for Unicorn System.

195 lines (167 loc) 7.81 kB
var util = require('mini-util'), Front = require('./front'), compiler = require('./compiler'), unique = require('./unique'), mime = require('mime-types'); var CONFIG = {}; CONFIG.prod = CONFIG.test = { longExpires: 31536000, normalExpires: 1800, shortExpires: 30 }; CONFIG.dev = { longExpires: 0, normalExpires: 0, shortExpires: 0 }; var GLOBAL_FILE = 'js/5v/lib/ae/debug/global-img-server.js', PATTERN_YUI = /(YAHOO\.register\s*\(\s*['"]event['"][\s\S]*?\))/, FONT_MIME = [ 'application/vnd.ms-fontobject', 'application/x-font-ttf', 'font/opentype', 'application/x-font-woff', 'application/font-woff' ]; var cache = {}, meta = {}; module.exports = function (config) { config = util.mix({ mode: 'dev' }, config); config = util.mix(config, CONFIG[config.mode]); return function (req, res) { var url = new Front().parse(req.path, '/'); if (url && (url.type == '.css' || url.type == '.js')) { var files = [], mtimes = [], mtime, stamp, filtered = [], base = url.base, pathnames = url.pathnames, expires = config.shortExpires; req.url('/unicorn.json?')(function (err) { if (err) { res(err); } else { var options = { alias: {}, modules: [] }, obj, c, data = res.toString(); try { obj = JSON.parse(data); } catch (err) { res(new Error('JSON syntax error in "unicorn.json"')); return; } options.alias = obj.alias; options.modules = obj.modules; c = compiler.generate({ alias: options.alias, modules: options.modules, cache: cache, req: req, res: res, mode: config.mode }); c.compile(GLOBAL_FILE, function (file) { if (file !== null) { meta[file.pathname] = { dataHash: file.meta.dataHash.toString(16), depsHash: file.meta.depsHash.toString(16), nameHash: file.meta.nameHash.toString(16), requires: file.meta.requires }; } (function nextFile(i) { if (i < pathnames.length) { (function nextCandidate(j) { if (j < base.length) { c.compile(base[j] + pathnames[i], function (file) { if (file !== null) { meta[file.pathname] = { dataHash: file.meta.dataHash.toString(16), depsHash: file.meta.depsHash.toString(16), nameHash: file.meta.nameHash.toString(16), requires: file.meta.requires }; filtered.push(file.pathname); nextFile(i + 1); } else { nextCandidate(j + 1); } }); } else { nextFile(i + 1); } }(0)); } else { if (c.errors.length > 0) { res(new Error(c.errors[0])); } var expanded = [], extname = url.type; filtered.forEach(function (pathname) { var data = meta[pathname]; if (data) { expanded = expanded.concat(data.requires, pathname); } }); if (expanded.length > 0 && extname === '.js' && meta[GLOBAL_FILE]) { expanded.unshift(GLOBAL_FILE); } var dataHash = 0, depsHash = 0, data = []; unique(expanded).forEach(function (pathname, index) { files[index] = { pathname: pathname, data: cache[pathname].data }; mtimes.push(cache[pathname].mtime); if (meta[pathname]) { dataHash += parseInt(meta[pathname].dataHash, 16); depsHash += parseInt(meta[pathname].depsHash, 16); } if (config.mode == 'dev'){ data.push(new Buffer('/*** START OF ' + pathname + ' ***/\n'), cache[pathname].data, new Buffer('\n/*** END OF ' + pathname + ' ***/\n')); }else{ data.push(cache[pathname].data); } }); mtime = new Date(Math.max.apply(Math, mtimes)); stamp = dataHash.toString(16) + '_' + depsHash.toString(16); res.head({ 'content-type': mime.contentType(url.type), 'expires': new Date(Date.now() + 1000 * expires).toGMTString(), 'cache-control': 'max-age=' + expires, 'last-modified': mtime.toGMTString(), 'etag': stamp, 'vary': 'Accept-Encoding' }); if(data.length){ res.status(200); }else{ res.status(404); } res.data(data.join('')); res(); } }(0)); }); } }); } else { req(function(err){ //set font file cross domain if (FONT_MIME.indexOf(res.head('content-type')) !== -1) { res.head('access-control-allow-origin','*'); } res(); }); } } };