@@ -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; | |||
} |