| @@ -1,7 +1,6 @@ | |||
| { | |||
| "title": "Spus", | |||
| "base_url": "http://example.com", | |||
| "webroot": "web", | |||
| "port": 8081, | |||
| "db": { | |||
| "host": "localhost", | |||
| @@ -20,7 +19,8 @@ | |||
| "minify": true, | |||
| "session_timeout": 1800000, | |||
| "dir": { | |||
| "imgs": "imgs" | |||
| "imgs": "imgs", | |||
| "web": "web | |||
| }, | |||
| "debug": false, | |||
| "max_runs": 9999, | |||
| @@ -1,5 +1,6 @@ | |||
| var fs = require("fs"); | |||
| var zlib = require("zlib"); | |||
| var browserPrefix = require("browser-prefix"); | |||
| var minify = require("./minify.js"); | |||
| var includeHtml = require("./includeHtml.js"); | |||
| @@ -12,31 +13,38 @@ exports.load = function(endpoints, conf) { | |||
| //Prepare endpoints | |||
| var errs = false; | |||
| Object.keys(endpoints).forEach(function(i) { | |||
| var ep = endpoints[i]; | |||
| var eps = Object.keys(endpoints).map(function(i) { | |||
| var ep = { | |||
| path: endpoints[i], | |||
| url: i | |||
| } | |||
| try { | |||
| //The endpoint is a function if the file ends with .node.js | |||
| if (/\.node\.js$/.test(ep)) { | |||
| res.endpoints[i] = require("../"+conf.webroot+"/"+ep); | |||
| if (/\.node\.js$/.test(ep.path)) { | |||
| ep.func = require("../"+conf.dir.web+"/"+ep.path); | |||
| return ep; | |||
| //If it doesn't end with .node.js, it's a regular text file and will | |||
| //just be served as is | |||
| } else { | |||
| var str = fs.readFileSync(conf.webroot+"/"+ep, "utf8"); | |||
| ep.str = fs.readFileSync(conf.dir.web+"/"+ep.path, "utf8"); | |||
| //If it's an HTML file, we minify it | |||
| if (!conf.minify) { | |||
| //Don't minify unless the conf tells us to | |||
| } else if (/\.html$/.test(ep)) { | |||
| str = minify.html(str); | |||
| } else if (/\.js$/.test(ep)) { | |||
| str = minify.js(str); | |||
| } else if (/\.css$/.test(ep)) { | |||
| str = minify.css(str); | |||
| //Add browser prefixes | |||
| if (/\.css$/.test(ep.path)) { | |||
| ep.str = browserPrefix(ep.str); | |||
| ep.mimeType = "text/css"; | |||
| if (conf.minify) ep.str = minify.css(ep.str); | |||
| } else if (/\.html$/.test(ep.path)) { | |||
| ep.mimeType = "text/html"; | |||
| if (conf.minify) ep.str = minify.html(ep.str); | |||
| } else if (/\.js$/.test(ep.path)) { | |||
| ep.mimeType = "application/javascript"; | |||
| if (conf.minify) ep.str = minify.js(ep.str); | |||
| } | |||
| res.endpoints[i] = str; | |||
| return ep; | |||
| } | |||
| //Errors will usually be because an endpoint doesn't exist | |||
| @@ -53,6 +61,11 @@ exports.load = function(endpoints, conf) { | |||
| //No need to proceed if some endpoints don't exist | |||
| if (errs) process.exit(); | |||
| eps.forEach(function(ep) { | |||
| res.endpoints[ep.url] = ep; | |||
| }); | |||
| //Prepare all templates | |||
| var templates = {}; | |||
| fs.readdirSync("templates").forEach(function(f) { | |||
| @@ -16,6 +16,7 @@ | |||
| }, | |||
| "license": "GPLv2", | |||
| "dependencies": { | |||
| "browser-prefix": "^0.1.0", | |||
| "formidable": "^1.0.17", | |||
| "html-minifier": "^0.7.2", | |||
| "pg": "^4.4.0", | |||
| @@ -99,23 +99,27 @@ function onRequest(req, res) { | |||
| } | |||
| //Execute if it's a .node.js, or just respond with the contents of the file | |||
| if (typeof ep == "function") { | |||
| ep(ctx); | |||
| if (ep.func) { | |||
| ep.func(ctx); | |||
| } else { | |||
| //Cache content for a while | |||
| ctx.setHeader("Cache-Control", "public, max-age="+conf.cache_max_age); | |||
| //Set appropriate content-type headers | |||
| if (ep.mimeType) | |||
| ctx.setHeader("Content-Type", ep.mimeType); | |||
| //Gzip and such | |||
| if (ctx.shouldGzip && gzipCache[req.url]) { | |||
| ctx.end(gzipCache[req.url], true); | |||
| } else if (ctx.shouldGzip) { | |||
| zlib.gzip(ep, function(err, res) { | |||
| zlib.gzip(ep.str, function(err, res) { | |||
| gzipCache[req.url] = res; | |||
| ctx.end(res, true); | |||
| }); | |||
| } else { | |||
| ctx.end(ep); | |||
| ctx.end(ep.str); | |||
| } | |||
| } | |||
| } | |||
| @@ -6,7 +6,7 @@ | |||
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> | |||
| <link rel="stylesheet" href="/{{env#view}}/style.css?{{conf#current_run}}"> | |||
| <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> | |||
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> | |||
| <script src="/global.js?{{conf#current_run}}"></script> | |||
| <script src="/{{env#view}}/script.js?{{conf#current_run}}"></script> | |||
| <script src="https://code.jquery.com/jquery-2.1.4.min.js" defer></script> | |||
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" defer></script> | |||
| <script src="/global.js?{{conf#current_run}}" defer></script> | |||
| <script src="/{{env#view}}/script.js?{{conf#current_run}}" defer></script> | |||
| @@ -1,13 +1,29 @@ | |||
| var fs = require("fs"); | |||
| var zlib = require("zlib"); | |||
| var gzipped; | |||
| var favicon = fs.readFileSync("favicon.ico"); | |||
| zlib.gzip(favicon, function(err, res) { | |||
| gzipped = res; | |||
| }); | |||
| module.exports = function(ctx) { | |||
| var readStream = fs.createReadStream("favicon.ico"); | |||
| readStream.pipe(ctx.res); | |||
| readStream.on("error", function(err) { | |||
| if (err.code === "ENOENT") | |||
| ctx.end(ctx.view("404")); | |||
| else | |||
| ctx.end(err.toString()); | |||
| }); | |||
| if (favicon) { | |||
| ctx.res.setHeader( | |||
| "Cache-Control", | |||
| "public, max-age="+ctx.conf.cache_max_age | |||
| ); | |||
| } | |||
| if (gzipped && ctx.shouldGzip) { | |||
| ctx.res.setHeader("Content-Encoding", "gzip"); | |||
| ctx.res.end(gzipped); | |||
| } else if (favicon) { | |||
| ctx.res.end(favicon); | |||
| } else { | |||
| ctx.res.writeHead(404); | |||
| ctx.end(ctx.view("404")); | |||
| } | |||
| } | |||
| @@ -60,7 +60,7 @@ form.container { | |||
| } | |||
| #notify-box { | |||
| transition: max-height 0.2s; | |||
| @prefix transition: max-height 0.2s; | |||
| max-height: 0px; | |||
| background-color: #F8F8F8; | |||
| @@ -70,7 +70,7 @@ form.container { | |||
| position: fixed; | |||
| bottom: 0px; | |||
| width: 100%; | |||
| box-sizing: content-box; | |||
| @prefix box-sizing: content-box; | |||
| } | |||
| #notify-box .close { | |||
| @@ -100,6 +100,6 @@ form.container { | |||
| max-height: 48px; | |||
| } | |||
| #notify-box.active:hover { | |||
| transition: max-height 0.6s; | |||
| @prefix transition: max-height 0.6s; | |||
| max-height: 200px; | |||
| } | |||
| @@ -36,3 +36,6 @@ | |||
| border-radius: 4px; | |||
| padding: 6px 12px; | |||
| } | |||
| #uploader-select-files, #uploader-collection-name, #uploader-upload { | |||
| height: 34px; | |||
| } | |||