Browse Source

jshinted all files

master
Christian Müller 9 years ago
parent
commit
91e5c745c1
  1. 1
      .jshintrc
  2. 10
      .tern-project
  3. 68
      api_spec.js
  4. 104
      resources/public/js/publishing.js
  5. 132
      server.js
  6. 8
      storage.js
  7. 62
      view.js

1
.jshintrc

@ -0,0 +1 @@
{ "esnext": true }

10
.tern-project

@ -0,0 +1,10 @@
{
"plugins": {
"es_modules": {}
},
"libs": [
"ecma5",
"ecma6"
],
"ecmaVersion": 6
}

68
api_spec.js

@ -50,8 +50,8 @@ frisby.create('Invalid posting 2')
frisby.create('Invalid posting 3') frisby.create('Invalid posting 3')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
action: 'POST', action: 'POST',
session: md5("new"), session: md5('new'),
signature: "assdss", signature: 'assdss',
note: testNote note: testNote
}) })
.expectStatus(400) .expectStatus(400)
@ -62,8 +62,8 @@ frisby.create('Invalid posting 3')
frisby.create('Valid posting') frisby.create('Valid posting')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
action: 'POST', action: 'POST',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote), signature: md5(md5('new') + testNote),
password: '', password: '',
note: testNote note: testNote
}) })
@ -81,39 +81,39 @@ frisby.create('Valid posting')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
id: noteId, id: noteId,
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote+'!!!'), signature: md5(md5('new') + testNote+'!!!'),
note: testNote + '!!!', note: testNote + '!!!',
password: '' password: ''
}) })
.expectStatus(400) .expectStatus(400)
.expectBodyContains('Password is wrong') .expectBodyContains('Password is wrong')
.toss() .toss();
}) })
.after((err, res, body) => { .after((err, res, body) => {
frisby.create('Illegal note editing attempt') frisby.create('Illegal note editing attempt')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
id: noteId, id: noteId,
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote+'!!!'), signature: md5(md5('new') + testNote+'!!!'),
note: testNote + '!!!', note: testNote + '!!!',
password: "aaabbb" password: 'aaabbb'
}) })
.expectStatus(400) .expectStatus(400)
.expectBodyContains('Password is wrong') .expectBodyContains('Password is wrong')
.toss() .toss();
}) })
.toss() .toss();
}) })
.toss(); .toss();
frisby.create('Valid posting, editing and removal') frisby.create('Valid posting, editing and removal')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
action: 'POST', action: 'POST',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote), signature: md5(md5('new') + testNote),
password: 'aabbcc', password: 'aabbcc',
note: testNote note: testNote
}) })
@ -123,7 +123,7 @@ frisby.create('Valid posting, editing and removal')
.after(function(err, res, body) { .after(function(err, res, body) {
var noteId = body.replace('Found. Redirecting to /', ''); var noteId = body.replace('Found. Redirecting to /', '');
frisby.create('Export posted note') frisby.create('Export posted note')
.get('http://localhost:3000/' + noteId + "/export") .get('http://localhost:3000/' + noteId + '/export')
.expectStatus(200) .expectStatus(200)
.expectHeaderContains('content-type', 'text/plain; charset=utf-8') .expectHeaderContains('content-type', 'text/plain; charset=utf-8')
.expectBodyContains(testNote) .expectBodyContains(testNote)
@ -138,24 +138,24 @@ frisby.create('Valid posting, editing and removal')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
id: noteId, id: noteId,
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote+'!!!'), signature: md5(md5('new') + testNote+'!!!'),
note: testNote + '!!!', note: testNote + '!!!',
password: "abbcc" password: 'abbcc'
}) })
.expectStatus(400) .expectStatus(400)
.expectBodyContains('Password is wrong') .expectBodyContains('Password is wrong')
.toss() .toss();
}) })
.after((err, res, body) => { .after((err, res, body) => {
frisby.create('Valid note editing attempt') frisby.create('Valid note editing attempt')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
id: noteId, id: noteId,
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + 'Changed!'), signature: md5(md5('new') + 'Changed!'),
note: 'Changed!', note: 'Changed!',
password: "aabbcc" password: 'aabbcc'
}) })
.expectStatus(302) .expectStatus(302)
.after((err, res, body) => { .after((err, res, body) => {
@ -171,27 +171,27 @@ frisby.create('Valid posting, editing and removal')
id: noteId, id: noteId,
button: 'Delete', button: 'Delete',
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + 'Changed!'), signature: md5(md5('new') + 'Changed!'),
note: 'Changed!', note: 'Changed!',
password: "aabbcc" password: 'aabbcc'
}) })
.expectStatus(200) .expectStatus(200)
.expectBodyContains('Note deleted') .expectBodyContains('Note deleted')
.toss(); .toss();
}) })
.toss() .toss();
}) })
.toss() .toss();
frisby.create('Read stats of posted note') frisby.create('Read stats of posted note')
.expectStatus(200) .expectStatus(200)
.get('http://localhost:3000/' + noteId).toss() .get('http://localhost:3000/' + noteId).toss();
frisby.create('Read stats of posted note') frisby.create('Read stats of posted note')
.expectStatus(200) .expectStatus(200)
.get('http://localhost:3000/' + noteId).toss() .get('http://localhost:3000/' + noteId).toss();
frisby.create('Read stats of posted note') frisby.create('Read stats of posted note')
.expectStatus(200) .expectStatus(200)
.get('http://localhost:3000/' + noteId).toss() .get('http://localhost:3000/' + noteId).toss();
frisby.create('Read stats of posted note') frisby.create('Read stats of posted note')
.get('http://localhost:3000/' + noteId + '/stats') .get('http://localhost:3000/' + noteId + '/stats')
.expectHeaderContains('content-type', 'text/html; charset=utf-8') .expectHeaderContains('content-type', 'text/html; charset=utf-8')
@ -209,8 +209,8 @@ while (tooLongNote.length < 1024*200) tooLongNote += tooLongNote;
frisby.create('Invalid posting of too long note') frisby.create('Invalid posting of too long note')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
action: 'POST', action: 'POST',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + testNote), signature: md5(md5('new') + testNote),
password: 'aabbcc', password: 'aabbcc',
note: tooLongNote note: tooLongNote
}) })
@ -222,8 +222,8 @@ frisby.create('Invalid posting of too long note')
frisby.create('Invalid update without id') frisby.create('Invalid update without id')
.post('http://localhost:3000/note', { .post('http://localhost:3000/note', {
action: 'UPDATE', action: 'UPDATE',
session: md5("new"), session: md5('new'),
signature: md5(md5("new") + 'Any note'), signature: md5(md5('new') + 'Any note'),
password: 'aabbcc', password: 'aabbcc',
note: 'Any note' note: 'Any note'
}) })

104
resources/public/js/publishing.js

@ -1,73 +1,73 @@
var $ = function(id) { var $ = function(id) {
return document.getElementById(id); return document.getElementById(id);
} };
var iosDetected = navigator.userAgent.match("(iPad|iPod|iPhone)"); var iosDetected = navigator.userAgent.match('(iPad|iPod|iPhone)');
var timer = null; var timer = null;
var timerDelay = iosDetected ? 800 : 400; var timerDelay = iosDetected ? 800 : 400;
var $note, $action, $preview, $plain_password, $tableau; var $note, $action, $preview, $plain_password, $tableau;
var backendTimer; var backendTimer;
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
marked.setOptions({ marked.setOptions({
langPrefix: 'hljs lang-', langPrefix: 'hljs lang-',
highlight: function (code) { highlight: function (code) {
return hljs.highlightAuto(code).value; return hljs.highlightAuto(code).value;
}, },
}); });
}); });
function md2html(input) { function md2html(input) {
return marked(input); return marked(input);
} }
function saveDraft() { function saveDraft() {
if ($action == "UPDATE") return; if ($action == 'UPDATE') return;
console.log("draft autosave..."); console.log('draft autosave...');
$tableau.innerHTML = "Draft autosaved." $tableau.innerHTML = 'Draft autosaved.';
localStorage.setItem("draft", $note.value); localStorage.setItem('draft', $note.value);
} }
function enableButton() { function enableButton() {
var checkbox = $('tos'); var checkbox = $('tos');
var button = $('publish-button'); var button = $('publish-button');
button.disabled = !checkbox.checked; button.disabled = !checkbox.checked;
} }
function onLoad() { function onLoad() {
$note = $("note"); $note = $('note');
$action = $("action").value; $action = $('action').value;
$preview = $("draft"); $preview = $('draft');
$tableau = $("tableau"); $tableau = $('tableau');
$plain_password = $("plain-password"); $plain_password = $('plain-password');
var updatePreview = function() { var updatePreview = function() {
clearTimeout(timer); clearTimeout(timer);
var content = $note.value; var content = $note.value;
var delay = Math.min(timerDelay, timerDelay * (content.length / 400)); var delay = Math.min(timerDelay, timerDelay * (content.length / 400));
timer = setTimeout(function() { timer = setTimeout(function() {
$preview.innerHTML = md2html(content); $preview.innerHTML = md2html(content);
$tableau.innerHTML = content.split(/\s+/).length + " words"; $tableau.innerHTML = content.split(/\s+/).length + ' words';
}, delay); }, delay);
}; };
if ($action == "UPDATE") updatePreview(); if ($action == 'UPDATE') updatePreview();
else { else {
$("delete-button").style.display = "none"; $('delete-button').style.display = 'none';
$note.value = ""; $note.value = '';
var draft = localStorage.getItem("draft"); var draft = localStorage.getItem('draft');
if (draft) { if (draft) {
$note.value = draft; $note.value = draft;
updatePreview(); updatePreview();
}
} }
} $note.onkeyup = updatePreview;
$note.onkeyup = updatePreview; $('delete-button').onclick = $('publish-button').onclick = function(e) {
$("delete-button").onclick = $("publish-button").onclick = function(e) { localStorage.removeItem('draft');
localStorage.removeItem("draft"); self.onbeforeunload = null;
self.onbeforeunload = null; if ($plain_password.value !== '') $('password').value = md5($plain_password.value);
if ($plain_password.value != "") $("password").value = md5($plain_password.value); $plain_password.value = null;
$plain_password.value = null; $('signature').value = md5($('session').value + $note.value.replace(/[\n\r]/g, ''));
$("signature").value = md5($("session").value + $note.value.replace(/[\n\r]/g, "")); };
}; if (iosDetected) $note.className += ' ui-border';
if (iosDetected) $note.className += " ui-border"; else $note.focus();
else $note.focus(); self.onbeforeunload = saveDraft;
self.onbeforeunload = saveDraft; setInterval(saveDraft, 60 * 1000);
setInterval(saveDraft, 60 * 1000)
} }

132
server.js

@ -2,7 +2,7 @@ var express = require('express');
var view = require('./view'); var view = require('./view');
var storage = require('./storage'); var storage = require('./storage');
var md5 = require('md5'); var md5 = require('md5');
var LRU = require("lru-cache") var LRU = require('lru-cache');
var bodyParser = require('body-parser'); var bodyParser = require('body-parser');
var fs = require('fs'); var fs = require('fs');
var blackList; var blackList;
@ -13,8 +13,8 @@ app.use(bodyParser.urlencoded({ extended: true, limit: '200kb' }));
app.use(express.static(__dirname + '/resources/public')); app.use(express.static(__dirname + '/resources/public'));
app.use(function (error, req, res, next) { app.use(function (error, req, res, next) {
if (error) { if (error) {
sendResponse(res, 400, "Bad request", error.message); sendResponse(res, 400, 'Bad request', error.message);
log("REQUEST ERROR:", error); log('REQUEST ERROR:', error);
} else { } else {
next(); next();
} }
@ -24,28 +24,28 @@ var MODELS = {};
var CACHE = new LRU({ var CACHE = new LRU({
max: 50, max: 50,
dispose: key => { dispose: key => {
log("disposing", key, "from cache"); log('disposing', key, 'from cache');
var model = MODELS[key]; var model = MODELS[key];
model && model.save(); if (model) model.save();
delete MODELS[key]; delete MODELS[key];
} }
}); });
var log = function() { var log = function() {
var date = new Date(); var date = new Date();
var timestamp = date.getDate() + "/" + date.getMonth() + " " + date.getHours() + ":" + var timestamp = date.getDate() + '/' + date.getMonth() + ' ' + date.getHours() + ':' +
date.getMinutes() + ":" + date.getSeconds() + "." + date.getMilliseconds(); date.getMinutes() + ':' + date.getSeconds() + '.' + date.getMilliseconds();
var message = Array.prototype.slice.call(arguments); var message = Array.prototype.slice.call(arguments);
message.unshift("--"); message.unshift('--');
message.unshift(timestamp); message.unshift(timestamp);
console.log.apply(console, message); console.log.apply(console, message);
} };
app.get('/TOS', (req, res) => res.send(view.renderTOS())); app.get('/TOS', (req, res) => res.send(view.renderTOS()));
app.get('/new', (req, res) => { app.get('/new', (req, res) => {
log(req.ip, "opens /new"); log(req.ip, 'opens /new');
res.send(view.newNotePage(md5("new"))); res.send(view.newNotePage(md5('new')));
}); });
app.post('/note', (req, res) => { app.post('/note', (req, res) => {
@ -55,43 +55,43 @@ app.post('/note', (req, res) => {
password = body.password, password = body.password,
action = body.action, action = body.action,
id = body.id; id = body.id;
log(req.ip, "calls /note to", action, id); log(req.ip, 'calls /note to', action, id);
var goToNote = note => res.redirect("/" + note.id); var goToNote = note => res.redirect('/' + note.id);
if (!note || !session || session.indexOf(md5('edit/' + id)) != 0 && session.indexOf(md5('new')) != 0) if (!note || !session || session.indexOf(md5('edit/' + id)) !== 0 && session.indexOf(md5('new')) !== 0)
return sendResponse(res, 400, 'Bad request'); return sendResponse(res, 400, 'Bad request');
if (body.signature != md5(session + note.replace(/[\n\r]/g, ""))) if (body.signature != md5(session + note.replace(/[\n\r]/g, '')))
return sendResponse(res, 400, "Signature mismatch"); return sendResponse(res, 400, 'Signature mismatch');
if (action == "POST") if (action == 'POST')
storage.addNote(note, password).then(goToNote); storage.addNote(note, password).then(goToNote);
else { else {
if (!id) return sendResponse(res, 400, "Wrong note ID"); if (!id) return sendResponse(res, 400, 'Wrong note ID');
CACHE.del(id); CACHE.del(id);
if (body.button == "Delete") { if (body.button == 'Delete') {
log("deleting note", id); log('deleting note', id);
storage.deleteNote(id, password).then( storage.deleteNote(id, password).then(
() => sendResponse(res, 200, "Note deleted"), () => sendResponse(res, 200, 'Note deleted'),
error => sendResponse(res, 400, "Bad request", error.message)); error => sendResponse(res, 400, 'Bad request', error.message));
} else { } else {
log("updating note", id); log('updating note', id);
storage.updateNote(id, password, note).then(goToNote, storage.updateNote(id, password, note).then(goToNote,
error => sendResponse(res, 400, "Bad request", error.message)); error => sendResponse(res, 400, 'Bad request', error.message));
} }
} }
}); });
app.get("/:year/:month/:day/:title", (req, res) => { app.get('/:year/:month/:day/:title', (req, res) => {
var P = req.params, url = P.year + "/" + P.month + "/" + P.day + "/" + P.title; var P = req.params, url = P.year + '/' + P.month + '/' + P.day + '/' + P.title;
log(req.ip, "resolves deprecated id", url); log(req.ip, 'resolves deprecated id', url);
if (CACHE.has(url)) { if (CACHE.has(url)) {
log(url, "is cached!"); log(url, 'is cached!');
var id = CACHE.get(url); var id = CACHE.get(url);
if (id) res.redirect("/" + id); if (id) res.redirect('/' + id);
else notFound(res); else notFound(res);
} else storage.getNoteId(url).then(note => { } else storage.getNoteId(url).then(note => {
log(url, "is not cached, resolving..."); log(url, 'is not cached, resolving...');
if (note) { if (note) {
CACHE.set(url, note.id); CACHE.set(url, note.id);
res.redirect("/" + note.id) res.redirect('/' + note.id);
} else { } else {
CACHE.set(url, null); CACHE.set(url, null);
notFound(res); notFound(res);
@ -100,44 +100,44 @@ app.get("/:year/:month/:day/:title", (req, res) => {
}); });
app.get(/\/([a-z0-9]+)\/edit/, (req, res) => { app.get(/\/([a-z0-9]+)\/edit/, (req, res) => {
var id = req.params["0"]; var id = req.params['0'];
log(req.ip, "calls /edit on", id); log(req.ip, 'calls /edit on', id);
storage.getNote(id).then(note => res.send(note storage.getNote(id).then(note => res.send(note ?
? view.editNotePage(md5('edit/' + id), note) view.editNotePage(md5('edit/' + id), note) :
: notFound(res))); notFound(res)));
}); });
app.get(/\/([a-z0-9]+)\/export/, (req, res) => { app.get(/\/([a-z0-9]+)\/export/, (req, res) => {
var id = req.params["0"]; var id = req.params['0'];
log(req.ip, "calls /export on", id); log(req.ip, 'calls /export on', id);
res.set({ 'Content-Type': 'text/plain', 'Charset': 'utf-8' }); res.set({ 'Content-Type': 'text/plain', 'Charset': 'utf-8' });
storage.getNote(id).then(note => note storage.getNote(id).then(note => note ?
? res.send(note.text) res.send(note.text) :
: notFound(res)); notFound(res));
}); });
app.get(/\/([a-z0-9]+)\/stats/, (req, res) => { app.get(/\/([a-z0-9]+)\/stats/, (req, res) => {
var id = req.params["0"]; var id = req.params['0'];
log(req.ip, "calls /stats on", id); log(req.ip, 'calls /stats on', id);
var promise = id in MODELS var promise = id in MODELS ?
? new Promise(resolve => resolve(MODELS[id])) new Promise(resolve => resolve(MODELS[id])) :
: storage.getNote(id); storage.getNote(id);
promise.then(note => note promise.then(note => note ?
? res.send(view.renderStats(note)) res.send(view.renderStats(note)) :
: notFound(res)); notFound(res));
}); });
app.get(/\/([a-z0-9]+)/, (req, res) => { app.get(/\/([a-z0-9]+)/, (req, res) => {
var id = req.params["0"]; var id = req.params['0'];
log(req.ip, "open note", id, "from", req.get("Referer")); log(req.ip, 'open note', id, 'from', req.get('Referer'));
if (CACHE.has(id)) { if (CACHE.has(id)) {
log(id, "is cached!"); log(id, 'is cached!');
var note = MODELS[id]; var obj = MODELS[id];
if (!note) return notFound(res); if (!obj) return notFound(res);
note.views++; obj.views++;
res.send(CACHE.get(id)); res.send(CACHE.get(id));
} else storage.getNote(id).then(note => { } else storage.getNote(id).then(note => {
log(id, "is not cached, resolving..."); log(id, 'is not cached, resolving...');
if (!note) { if (!note) {
CACHE.set(id, null); CACHE.set(id, null);
return notFound(res); return notFound(res);
@ -151,31 +151,31 @@ app.get(/\/([a-z0-9]+)/, (req, res) => {
}); });
var sendResponse = (res, code, message, details) => { var sendResponse = (res, code, message, details) => {
log("sending response", code, message); log('sending response', code, message);
res.status(code).send(view.renderPage(null, message, res.status(code).send(view.renderPage(null, message,
`<h1>${message}</h1><br/>` + `<h1>${message}</h1><br/>` +
`<center>${details || "¯\\_(ツ)_/¯"}</center>`, "")); `<center>${details || '¯\\_(ツ)_/¯'}</center>`, ''));
} };
var notFound = res => sendResponse(res, 404, "Not found"); var notFound = res => sendResponse(res, 404, 'Not found');
var server = app.listen(process.env.PORT || 3000, var server = app.listen(process.env.PORT || 3000,
() => log('NoteHub server listening on port', server.address().port)); () => log('NoteHub server listening on port', server.address().port));
setInterval(() => { setInterval(() => {
var keys = Object.keys(MODELS); var keys = Object.keys(MODELS);
log("saving stats for", keys.length, "models..."); log('saving stats for', keys.length, 'models...');
keys.forEach(id => MODELS[id].save()) keys.forEach(id => MODELS[id].save());
}, 5 * 60 * 1000); }, 5 * 60 * 1000);
var updateBlackList = () => { var updateBlackList = () => {
var ids = fs.readFileSync(process.env.BLACK_LIST || "/dev/null", "utf-8").split(/\n+/).filter(Boolean); var ids = fs.readFileSync(process.env.BLACK_LIST || '/dev/null', 'utf-8').split(/\n+/).filter(Boolean);
ids.forEach(id => CACHE.del(id)) ids.forEach(id => CACHE.del(id));
blackList = new Set(ids); blackList = new Set(ids);
log("black list updated, entries:", blackList.size); log('black list updated, entries:', blackList.size);
}; };
setInterval(updateBlackList, 60 * 60 * 1000) setInterval(updateBlackList, 60 * 60 * 1000);
updateBlackList(); updateBlackList();

8
storage.js

@ -32,7 +32,7 @@ var generateId = () => [1, 1, 1, 1, 1]
var code = Math.floor(Math.random() * 36); var code = Math.floor(Math.random() * 36);
return String.fromCharCode(code + (code < 10 ? 48 : 87)); return String.fromCharCode(code + (code < 10 ? 48 : 87));
}) })
.join(""); .join('');
var getFreeId = () => { var getFreeId = () => {
var id = generateId(); var id = generateId();
@ -46,9 +46,9 @@ module.exports.addNote = (note, password) => getFreeId().then(id => Note.create(
})); }));
var passwordCheck = (note, password, callback) => var passwordCheck = (note, password, callback) =>
(!note || note.password.length == 0 || note.password !== password) (!note || note.password.length === 0 || note.password !== password) ?
? new Promise((resolve, reject) => reject({ message: "Password is wrong" })) new Promise((resolve, reject) => reject({ message: 'Password is wrong' })) :
: callback(); callback();
module.exports.updateNote = (id, password, text) => module.exports.updateNote = (id, password, text) =>
Note.findById(id).then(note => Note.findById(id).then(note =>

62
view.js

@ -1,55 +1,55 @@
var marked = require("marked"); var marked = require('marked');
var fs = require("fs"); var fs = require('fs');
var hljs = require("highlight.js"); var hljs = require('highlight.js');
var TOS = fs.readFileSync("resources/TOS.md", "utf-8"); var TOS = fs.readFileSync('resources/TOS.md', 'utf-8');
var pageTemplate = fs.readFileSync("resources/template.html", "utf-8"); var pageTemplate = fs.readFileSync('resources/template.html', 'utf-8');
var footerTemplate = fs.readFileSync("resources/footer.html", "utf-8"); var footerTemplate = fs.readFileSync('resources/footer.html', 'utf-8');
var editTemplate = fs.readFileSync("resources/edit.html", "utf-8"); var editTemplate = fs.readFileSync('resources/edit.html', 'utf-8');
var header = fs.readFileSync(process.env.HEADER || "/dev/null", "utf-8"); var header = fs.readFileSync(process.env.HEADER || '/dev/null', 'utf-8');
var deriveTitle = text => text var deriveTitle = text => text
.split(/[\n\r]/)[0].slice(0,25) .split(/[\n\r]/)[0].slice(0,25)
.replace(/[`~!@#\$%^&\*_|\+=\?;:'",.<>\{\}\\\/]/g, ""); .replace(/[`~!@#\$%^&\*_|\+=\?;:'",.<>\{\}\\\/]/g, '');
var renderPage = (id, title, content, footer, blackList) => pageTemplate var renderPage = (id, title, content, footer, blackList) => pageTemplate
.replace("%HEADER%", blackList && blackList.has(id) ? header : "") .replace('%HEADER%', blackList && blackList.has(id) ? header : '')
.replace("%TITLE%", title) .replace('%TITLE%', title)
.replace("%CONTENT%", content.replace(/<meta.*?>/gi, "").replace(/<script[\s\S.]*?\/script>/gi, "")) .replace('%CONTENT%', content.replace(/<meta.*?>/gi, '').replace(/<script[\s\S.]*?\/script>/gi, ''))
.replace("%FOOTER%", footer || ""); .replace('%FOOTER%', footer || '');
marked.setOptions({ marked.setOptions({
langPrefix: "hljs lang-", langPrefix: 'hljs lang-',
highlight: code => hljs.highlightAuto(code).value, highlight: code => hljs.highlightAuto(code).value,
}); });
module.exports.renderPage = renderPage; module.exports.renderPage = renderPage;
module.exports.renderStats = note => renderPage(note.id, deriveTitle(note.text), module.exports.renderStats = note => renderPage(note.id, deriveTitle(note.text),
`<h2>Statistics</h2> `<h2>Statistics</h2>
<table> <table>
<tr><td>Published</td><td>${note.published}</td></tr> <tr><td>Published</td><td>${note.published}</td></tr>
<tr><td>Edited</td><td>${note.edited || "N/A"}</td></tr> <tr><td>Edited</td><td>${note.edited || 'N/A'}</td></tr>
<tr><td>Views</td><td>${note.views}</td></tr> <tr><td>Views</td><td>${note.views}</td></tr>
</table>`); </table>`);
module.exports.renderTOS = () => renderPage("tos", "Terms of Service", marked(TOS)); module.exports.renderTOS = () => renderPage('tos', 'Terms of Service', marked(TOS));
module.exports.renderNote = (note, blackList) => renderPage(note.id, module.exports.renderNote = (note, blackList) => renderPage(note.id,
deriveTitle(note.text), deriveTitle(note.text),
marked(note.text), marked(note.text),
footerTemplate.replace(/%LINK%/g, note.id), footerTemplate.replace(/%LINK%/g, note.id),
blackList); blackList);
module.exports.newNotePage = session => editTemplate module.exports.newNotePage = session => editTemplate
.replace("%ACTION%", "POST") .replace('%ACTION%', 'POST')
.replace("%SESSION%", session) .replace('%SESSION%', session)
.replace("%CONTENT%", "Loading..."); .replace('%CONTENT%', 'Loading...');
module.exports.editNotePage = (session, note) => editTemplate module.exports.editNotePage = (session, note) => editTemplate
.replace("%ACTION%", "UPDATE") .replace('%ACTION%', 'UPDATE')
.replace("%SESSION%", session) .replace('%SESSION%', session)
.replace("%ID%", note.id) .replace('%ID%', note.id)
.replace("%CONTENT%", escape$(note.text)); .replace('%CONTENT%', escape$(note.text));
var escape$ = s => s.split("").map(chr => chr == "$" ? "$$" : chr).join(""); var escape$ = s => s.split('').map(chr => chr == '$' ? '$$' : chr).join('');

Loading…
Cancel
Save