| @@ -1,6 +1,7 @@ | |||
| var http = require("http"); | |||
| var https = require("https"); | |||
| var fs = require("fs"); | |||
| var loader = require("./lib/loader.js"); | |||
| var Context = require("./lib/context.js"); | |||
| var Db = require("./lib/db.js"); | |||
| @@ -25,56 +26,17 @@ var endpoints = { | |||
| "/viewer/style.css": "viewer/style.css" | |||
| } | |||
| //Prepare endpoints | |||
| var errs = false; | |||
| Object.keys(endpoints).forEach(function(i) { | |||
| try { | |||
| //The endpoint is a function if the file ends with .node.js | |||
| if (/\.node\.js$/.test(endpoints[i])) { | |||
| endpoints[i] = require("./"+conf.webroot+"/"+endpoints[i]); | |||
| //If it doesn't end with .node.js, it's a regular text file and will | |||
| //just be served as is | |||
| } else { | |||
| endpoints[i] = fs.readFileSync(conf.webroot+"/"+endpoints[i]); | |||
| } | |||
| //Errors will usually be because an endpoint doesn't exist | |||
| } catch (err) { | |||
| if (err.code == "ENOENT") { | |||
| console.log(err.toString()); | |||
| errs = true; | |||
| } else { | |||
| throw err; | |||
| } | |||
| } | |||
| }); | |||
| //No need to proceed if some endpoints don't exist | |||
| if (errs) process.exit(); | |||
| //Prepare all templates | |||
| var templates = {}; | |||
| fs.readdirSync("templates").forEach(function(f) { | |||
| templates[f.replace(/\.html$/, "")] = fs.readFileSync("templates/"+f, "utf8"); | |||
| }); | |||
| //Prepare all views | |||
| var views = {}; | |||
| fs.readdirSync("views").forEach(function(f) { | |||
| views[f.replace(/\.html$/, "")] = fs.readFileSync("views/"+f, "utf8"); | |||
| }); | |||
| var loaded = loader.load(endpoints, conf); | |||
| //Function to run on each request | |||
| function onRequest(req, res) { | |||
| console.log("Request for "+req.url); | |||
| var ep = endpoints[req.url]; | |||
| var ep = loaded.endpoints[req.url]; | |||
| //If the file doesn't exist, we 404. | |||
| if (!ep) { | |||
| ep = endpoints["/404"]; | |||
| ep = loaded.endpoints["/404"]; | |||
| res.writeHead(404); | |||
| } | |||
| @@ -83,8 +45,8 @@ function onRequest(req, res) { | |||
| ep(new Context({ | |||
| req: req, | |||
| res: res, | |||
| templates: templates, | |||
| views: views, | |||
| templates: loaded.templates, | |||
| views: loaded.views, | |||
| conf: conf | |||
| })); | |||
| } else { | |||
| @@ -0,0 +1,14 @@ | |||
| var fs = require("fs"); | |||
| var minify = require("./minify"); | |||
| module.exports = function(path, conf) { | |||
| var html = fs.readFileSync(path, "utf8"); | |||
| for (var i in conf) { | |||
| html = html.split("{{conf#"+i+"}}").join(conf[i]); | |||
| } | |||
| html = minify.html(html); | |||
| return html; | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| var fs = require("fs"); | |||
| var minify = require("./minify.js"); | |||
| var includeHtml = require("./includeHtml.js"); | |||
| exports.load = function(endpoints, conf) { | |||
| var res = { | |||
| endpoints: {}, | |||
| templates: {}, | |||
| views: {} | |||
| } | |||
| //Prepare endpoints | |||
| var errs = false; | |||
| Object.keys(endpoints).forEach(function(i) { | |||
| var ep = endpoints[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 it doesn't end with .node.js, it's a regular text file and will | |||
| //just be served as is | |||
| } else { | |||
| res.endpoints[i] = fs.readFileSync(conf.webroot+"/"+ep, "utf8"); | |||
| //If it's an HTML file, we minify it | |||
| if (/\.html$/.test(ep)) { | |||
| res.endpoints[i] = minify.html(res.endpoints[i]); | |||
| } | |||
| } | |||
| //Errors will usually be because an endpoint doesn't exist | |||
| } catch (err) { | |||
| if (err.code == "ENOENT") { | |||
| console.log(err.toString()); | |||
| errs = true; | |||
| } else { | |||
| throw err; | |||
| } | |||
| } | |||
| }); | |||
| //No need to proceed if some endpoints don't exist | |||
| if (errs) process.exit(); | |||
| //Prepare all templates | |||
| var templates = {}; | |||
| fs.readdirSync("templates").forEach(function(f) { | |||
| var name = f.replace(/\.html$/, ""); | |||
| res.templates[name] = includeHtml("templates/"+f, conf.web); | |||
| }); | |||
| //Prepare all views | |||
| var views = {}; | |||
| fs.readdirSync("views").forEach(function(f) { | |||
| var name = f.replace(/\.html$/, ""); | |||
| res.views[name] = includeHtml("views/"+f, conf.web); | |||
| }); | |||
| return res; | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| var minify = require("html-minifier").minify; | |||
| exports.html = function(src) { | |||
| return src; | |||
| return minify(src, { | |||
| removeComments: true, | |||
| collapseWhitespace: true, | |||
| }); | |||
| } | |||
| @@ -14,6 +14,7 @@ | |||
| }, | |||
| "license": "GPLv2", | |||
| "dependencies": { | |||
| "html-minifier": "^0.7.2", | |||
| "pg": "^4.4.0" | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| <div class="navbar navbar-default navbar-fixed-top"> | |||
| <div class="navbar navbar-default"> | |||
| <div class="navbar-inner"> | |||
| <div class="container-fluid"> | |||
| <a class="navbar-brand" href="/">Mimg</a> | |||
| <a class="navbar-brand" href="/">{{conf#title}}</a> | |||
| <ul class="nav navbar-nav navbar-right"> | |||
| {{profile}} | |||
| </ul> | |||
| @@ -1,3 +1,4 @@ | |||
| <title>{{conf#title}}</title> | |||
| <meta charset="utf-8"> | |||
| <meta name="viewport" content="width=device-width"> | |||
| <link rel="stylesheet" href="/global.css"> | |||
| @@ -18,5 +18,6 @@ | |||
| <div class="submit-container"> | |||
| <button type="submit" class="btn btn-default">Log In</button> | |||
| </div> | |||
| </form> | |||
| </li></ul> | |||
| </li> | |||
| @@ -2,9 +2,17 @@ | |||
| <html> | |||
| <head> | |||
| {{head}} | |||
| <link rel="stylesheet" href="/index/style.css"> | |||
| </head> | |||
| <body> | |||
| {{global}} | |||
| <div id="uploader" class="container"> | |||
| <input type="file" id="uploader-input" class="hidden" multiple> | |||
| <button class="btn btn-default" onclick="$('#uploader-input').click()">Select Files</button> | |||
| <button class="btn btn-default" id="uploader-upload">Upload</button> | |||
| <ul class="list-group" id="uploader-list"></ul> | |||
| </div> | |||
| <script src="/index/script.js"></script> | |||
| </body> | |||
| </html> | |||
| @@ -2,8 +2,11 @@ | |||
| <html> | |||
| <head> | |||
| {{head}} | |||
| <link rel="stylesheet" href="/viewer/style.css"> | |||
| </head> | |||
| <body> | |||
| {{global}} | |||
| <script src="/viewer/script.js"></script> | |||
| </body> | |||
| </html> | |||
| @@ -1,3 +1,7 @@ | |||
| .hidden { | |||
| display: none; | |||
| } | |||
| .navbar .navbar-nav { | |||
| margin-bottom: 0px; | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| $(document).ready(function() { | |||
| (function() { | |||
| window.util = {}; | |||
| util.notify = function notify(title, body) { | |||
| @@ -12,13 +12,22 @@ $(document).ready(function() { | |||
| elem.removeClass("active"); | |||
| }, 5000); | |||
| } | |||
| $("#notify-box").on("mouseenter", function() { | |||
| clearTimeout(util.notify.timeout); | |||
| }); | |||
| $(document).ready(function() { | |||
| $("#notify-box").on("mouseenter", function() { | |||
| clearTimeout(util.notify.timeout); | |||
| }); | |||
| $("#login-form").on("submit", function(evt) { | |||
| evt.stopPropagation(); | |||
| evt.preventDefault(); | |||
| util.notify("Feature Not Implemented", "This feature is not implemented."); | |||
| $("#login-form").on("submit", function(evt) { | |||
| evt.stopPropagation(); | |||
| evt.preventDefault(); | |||
| util.notify("Feature Not Implemented", "This feature is not implemented."); | |||
| }); | |||
| }); | |||
| }); | |||
| util.htmlEntities = function(str) { | |||
| return str.replace(/&/g, "&") | |||
| .replace(/</g, "<") | |||
| .replace(/>/g, "<") | |||
| .replace(/"/g, """); | |||
| } | |||
| })(); | |||
| @@ -0,0 +1,40 @@ | |||
| (function() { | |||
| if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { | |||
| notify("Your Browser Sucks."); | |||
| } | |||
| function draw(files) { | |||
| var output = []; | |||
| files.forEach(function(f, i) { | |||
| output.push( | |||
| '<li class="file list-group-item" data-index='+i+'>'+ | |||
| '<span class="name">'+util.htmlEntities(f.name)+'</span>'+ | |||
| '<button class="btn delete" onclick="uploaderDelete(this.parentNode)">X</button>'+ | |||
| '</li>' | |||
| ); | |||
| }); | |||
| $("#uploader-list").html(output.join("")); | |||
| } | |||
| var files = []; | |||
| $("#uploader-input").on("change", function(evt) { | |||
| var inputFiles = evt.target.files; | |||
| for (var i = 0; i < inputFiles.length; ++i) { | |||
| files.push(inputFiles[i]); | |||
| } | |||
| draw(files); | |||
| }); | |||
| window.uploaderDelete = function(elem) { | |||
| var index = elem.getAttribute("data-index"); | |||
| delete files[index]; | |||
| draw(files); | |||
| } | |||
| $("#uploader-upload").on("click", function(evt) { | |||
| console.log(output); | |||
| }); | |||
| })(); | |||
| @@ -0,0 +1,11 @@ | |||
| #uploader-list .file { | |||
| text-align: right !important; | |||
| } | |||
| #uploader-list .file .name { | |||
| float: left; | |||
| margin-top: 6px; | |||
| } | |||
| #uploader-upload { | |||
| float: right; | |||
| } | |||