| { | { | ||||
| "title": "Spus", | "title": "Spus", | ||||
| "base_url": "http://example.com", | "base_url": "http://example.com", | ||||
| "webroot": "web", | |||||
| "port": 8081, | "port": 8081, | ||||
| "db": { | "db": { | ||||
| "host": "localhost", | "host": "localhost", | ||||
| "minify": true, | "minify": true, | ||||
| "session_timeout": 1800000, | "session_timeout": 1800000, | ||||
| "dir": { | "dir": { | ||||
| "imgs": "imgs" | |||||
| "imgs": "imgs", | |||||
| "web": "web | |||||
| }, | }, | ||||
| "debug": false, | "debug": false, | ||||
| "max_runs": 9999, | "max_runs": 9999, |
| var fs = require("fs"); | var fs = require("fs"); | ||||
| var zlib = require("zlib"); | var zlib = require("zlib"); | ||||
| var browserPrefix = require("browser-prefix"); | |||||
| var minify = require("./minify.js"); | var minify = require("./minify.js"); | ||||
| var includeHtml = require("./includeHtml.js"); | var includeHtml = require("./includeHtml.js"); | ||||
| //Prepare endpoints | //Prepare endpoints | ||||
| var errs = false; | 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 { | try { | ||||
| //The endpoint is a function if the file ends with .node.js | //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 | //If it doesn't end with .node.js, it's a regular text file and will | ||||
| //just be served as is | //just be served as is | ||||
| } else { | } 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 | //Errors will usually be because an endpoint doesn't exist | ||||
| //No need to proceed if some endpoints don't exist | //No need to proceed if some endpoints don't exist | ||||
| if (errs) process.exit(); | if (errs) process.exit(); | ||||
| eps.forEach(function(ep) { | |||||
| res.endpoints[ep.url] = ep; | |||||
| }); | |||||
| //Prepare all templates | //Prepare all templates | ||||
| var templates = {}; | var templates = {}; | ||||
| fs.readdirSync("templates").forEach(function(f) { | fs.readdirSync("templates").forEach(function(f) { |
| }, | }, | ||||
| "license": "GPLv2", | "license": "GPLv2", | ||||
| "dependencies": { | "dependencies": { | ||||
| "browser-prefix": "^0.1.0", | |||||
| "formidable": "^1.0.17", | "formidable": "^1.0.17", | ||||
| "html-minifier": "^0.7.2", | "html-minifier": "^0.7.2", | ||||
| "pg": "^4.4.0", | "pg": "^4.4.0", |
| } | } | ||||
| //Execute if it's a .node.js, or just respond with the contents of the file | //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 { | } else { | ||||
| //Cache content for a while | //Cache content for a while | ||||
| ctx.setHeader("Cache-Control", "public, max-age="+conf.cache_max_age); | 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 | //Gzip and such | ||||
| if (ctx.shouldGzip && gzipCache[req.url]) { | if (ctx.shouldGzip && gzipCache[req.url]) { | ||||
| ctx.end(gzipCache[req.url], true); | ctx.end(gzipCache[req.url], true); | ||||
| } else if (ctx.shouldGzip) { | } else if (ctx.shouldGzip) { | ||||
| zlib.gzip(ep, function(err, res) { | |||||
| zlib.gzip(ep.str, function(err, res) { | |||||
| gzipCache[req.url] = res; | gzipCache[req.url] = res; | ||||
| ctx.end(res, true); | ctx.end(res, true); | ||||
| }); | }); | ||||
| } else { | } else { | ||||
| ctx.end(ep); | |||||
| ctx.end(ep.str); | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> | <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}}"> | <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> |
| var fs = require("fs"); | 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) { | 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")); | |||||
| } | |||||
| } | } |
| } | } | ||||
| #notify-box { | #notify-box { | ||||
| transition: max-height 0.2s; | |||||
| @prefix transition: max-height 0.2s; | |||||
| max-height: 0px; | max-height: 0px; | ||||
| background-color: #F8F8F8; | background-color: #F8F8F8; | ||||
| position: fixed; | position: fixed; | ||||
| bottom: 0px; | bottom: 0px; | ||||
| width: 100%; | width: 100%; | ||||
| box-sizing: content-box; | |||||
| @prefix box-sizing: content-box; | |||||
| } | } | ||||
| #notify-box .close { | #notify-box .close { | ||||
| max-height: 48px; | max-height: 48px; | ||||
| } | } | ||||
| #notify-box.active:hover { | #notify-box.active:hover { | ||||
| transition: max-height 0.6s; | |||||
| @prefix transition: max-height 0.6s; | |||||
| max-height: 200px; | max-height: 200px; | ||||
| } | } |
| border-radius: 4px; | border-radius: 4px; | ||||
| padding: 6px 12px; | padding: 6px 12px; | ||||
| } | } | ||||
| #uploader-select-files, #uploader-collection-name, #uploader-upload { | |||||
| height: 34px; | |||||
| } |