From 91e5c745c10a2a3a26952d8279efa2609e4281b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=BCller?= Date: Sun, 26 Feb 2017 22:13:18 +0100 Subject: [PATCH] jshinted all files --- .jshintrc | 1 + .tern-project | 10 +++ api_spec.js | 68 +++++++-------- resources/public/js/publishing.js | 104 +++++++++++------------ server.js | 132 +++++++++++++++--------------- storage.js | 8 +- view.js | 62 +++++++------- 7 files changed, 198 insertions(+), 187 deletions(-) create mode 100644 .jshintrc create mode 100644 .tern-project diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..7b4964b --- /dev/null +++ b/.jshintrc @@ -0,0 +1 @@ +{ "esnext": true } diff --git a/.tern-project b/.tern-project new file mode 100644 index 0000000..20090cb --- /dev/null +++ b/.tern-project @@ -0,0 +1,10 @@ +{ + "plugins": { + "es_modules": {} + }, + "libs": [ + "ecma5", + "ecma6" + ], + "ecmaVersion": 6 +} diff --git a/api_spec.js b/api_spec.js index 14a8536..a5a7f2d 100644 --- a/api_spec.js +++ b/api_spec.js @@ -50,8 +50,8 @@ frisby.create('Invalid posting 2') frisby.create('Invalid posting 3') .post('http://localhost:3000/note', { action: 'POST', - session: md5("new"), - signature: "assdss", + session: md5('new'), + signature: 'assdss', note: testNote }) .expectStatus(400) @@ -62,8 +62,8 @@ frisby.create('Invalid posting 3') frisby.create('Valid posting') .post('http://localhost:3000/note', { action: 'POST', - session: md5("new"), - signature: md5(md5("new") + testNote), + session: md5('new'), + signature: md5(md5('new') + testNote), password: '', note: testNote }) @@ -81,39 +81,39 @@ frisby.create('Valid posting') .post('http://localhost:3000/note', { id: noteId, action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + testNote+'!!!'), + session: md5('new'), + signature: md5(md5('new') + testNote+'!!!'), note: testNote + '!!!', password: '' }) .expectStatus(400) .expectBodyContains('Password is wrong') - .toss() + .toss(); }) .after((err, res, body) => { frisby.create('Illegal note editing attempt') .post('http://localhost:3000/note', { id: noteId, action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + testNote+'!!!'), + session: md5('new'), + signature: md5(md5('new') + testNote+'!!!'), note: testNote + '!!!', - password: "aaabbb" + password: 'aaabbb' }) .expectStatus(400) .expectBodyContains('Password is wrong') - .toss() + .toss(); }) - .toss() + .toss(); }) .toss(); frisby.create('Valid posting, editing and removal') .post('http://localhost:3000/note', { action: 'POST', - session: md5("new"), - signature: md5(md5("new") + testNote), + session: md5('new'), + signature: md5(md5('new') + testNote), password: 'aabbcc', note: testNote }) @@ -123,7 +123,7 @@ frisby.create('Valid posting, editing and removal') .after(function(err, res, body) { var noteId = body.replace('Found. Redirecting to /', ''); frisby.create('Export posted note') - .get('http://localhost:3000/' + noteId + "/export") + .get('http://localhost:3000/' + noteId + '/export') .expectStatus(200) .expectHeaderContains('content-type', 'text/plain; charset=utf-8') .expectBodyContains(testNote) @@ -138,24 +138,24 @@ frisby.create('Valid posting, editing and removal') .post('http://localhost:3000/note', { id: noteId, action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + testNote+'!!!'), + session: md5('new'), + signature: md5(md5('new') + testNote+'!!!'), note: testNote + '!!!', - password: "abbcc" + password: 'abbcc' }) .expectStatus(400) .expectBodyContains('Password is wrong') - .toss() + .toss(); }) .after((err, res, body) => { frisby.create('Valid note editing attempt') .post('http://localhost:3000/note', { id: noteId, action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + 'Changed!'), + session: md5('new'), + signature: md5(md5('new') + 'Changed!'), note: 'Changed!', - password: "aabbcc" + password: 'aabbcc' }) .expectStatus(302) .after((err, res, body) => { @@ -171,27 +171,27 @@ frisby.create('Valid posting, editing and removal') id: noteId, button: 'Delete', action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + 'Changed!'), + session: md5('new'), + signature: md5(md5('new') + 'Changed!'), note: 'Changed!', - password: "aabbcc" + password: 'aabbcc' }) .expectStatus(200) .expectBodyContains('Note deleted') .toss(); }) - .toss() + .toss(); }) - .toss() + .toss(); frisby.create('Read stats of posted note') .expectStatus(200) - .get('http://localhost:3000/' + noteId).toss() + .get('http://localhost:3000/' + noteId).toss(); frisby.create('Read stats of posted note') .expectStatus(200) - .get('http://localhost:3000/' + noteId).toss() + .get('http://localhost:3000/' + noteId).toss(); frisby.create('Read stats of posted note') .expectStatus(200) - .get('http://localhost:3000/' + noteId).toss() + .get('http://localhost:3000/' + noteId).toss(); frisby.create('Read stats of posted note') .get('http://localhost:3000/' + noteId + '/stats') .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') .post('http://localhost:3000/note', { action: 'POST', - session: md5("new"), - signature: md5(md5("new") + testNote), + session: md5('new'), + signature: md5(md5('new') + testNote), password: 'aabbcc', note: tooLongNote }) @@ -222,8 +222,8 @@ frisby.create('Invalid posting of too long note') frisby.create('Invalid update without id') .post('http://localhost:3000/note', { action: 'UPDATE', - session: md5("new"), - signature: md5(md5("new") + 'Any note'), + session: md5('new'), + signature: md5(md5('new') + 'Any note'), password: 'aabbcc', note: 'Any note' }) diff --git a/resources/public/js/publishing.js b/resources/public/js/publishing.js index 3faa8e7..663fbaf 100644 --- a/resources/public/js/publishing.js +++ b/resources/public/js/publishing.js @@ -1,73 +1,73 @@ var $ = function(id) { - return document.getElementById(id); -} -var iosDetected = navigator.userAgent.match("(iPad|iPod|iPhone)"); + return document.getElementById(id); +}; +var iosDetected = navigator.userAgent.match('(iPad|iPod|iPhone)'); var timer = null; var timerDelay = iosDetected ? 800 : 400; var $note, $action, $preview, $plain_password, $tableau; var backendTimer; document.addEventListener('DOMContentLoaded', function () { - marked.setOptions({ - langPrefix: 'hljs lang-', - highlight: function (code) { - return hljs.highlightAuto(code).value; - }, - }); + marked.setOptions({ + langPrefix: 'hljs lang-', + highlight: function (code) { + return hljs.highlightAuto(code).value; + }, + }); }); function md2html(input) { - return marked(input); + return marked(input); } function saveDraft() { - if ($action == "UPDATE") return; - console.log("draft autosave..."); - $tableau.innerHTML = "Draft autosaved." - localStorage.setItem("draft", $note.value); + if ($action == 'UPDATE') return; + console.log('draft autosave...'); + $tableau.innerHTML = 'Draft autosaved.'; + localStorage.setItem('draft', $note.value); } function enableButton() { - var checkbox = $('tos'); - var button = $('publish-button'); - button.disabled = !checkbox.checked; + var checkbox = $('tos'); + var button = $('publish-button'); + button.disabled = !checkbox.checked; } function onLoad() { - $note = $("note"); - $action = $("action").value; - $preview = $("draft"); - $tableau = $("tableau"); - $plain_password = $("plain-password"); - var updatePreview = function() { - clearTimeout(timer); - var content = $note.value; - var delay = Math.min(timerDelay, timerDelay * (content.length / 400)); - timer = setTimeout(function() { - $preview.innerHTML = md2html(content); - $tableau.innerHTML = content.split(/\s+/).length + " words"; - }, delay); - }; - if ($action == "UPDATE") updatePreview(); - else { - $("delete-button").style.display = "none"; - $note.value = ""; - var draft = localStorage.getItem("draft"); - if (draft) { - $note.value = draft; - updatePreview(); + $note = $('note'); + $action = $('action').value; + $preview = $('draft'); + $tableau = $('tableau'); + $plain_password = $('plain-password'); + var updatePreview = function() { + clearTimeout(timer); + var content = $note.value; + var delay = Math.min(timerDelay, timerDelay * (content.length / 400)); + timer = setTimeout(function() { + $preview.innerHTML = md2html(content); + $tableau.innerHTML = content.split(/\s+/).length + ' words'; + }, delay); + }; + if ($action == 'UPDATE') updatePreview(); + else { + $('delete-button').style.display = 'none'; + $note.value = ''; + var draft = localStorage.getItem('draft'); + if (draft) { + $note.value = draft; + updatePreview(); + } } - } - $note.onkeyup = updatePreview; - $("delete-button").onclick = $("publish-button").onclick = function(e) { - localStorage.removeItem("draft"); - self.onbeforeunload = null; - if ($plain_password.value != "") $("password").value = md5($plain_password.value); - $plain_password.value = null; - $("signature").value = md5($("session").value + $note.value.replace(/[\n\r]/g, "")); - }; - if (iosDetected) $note.className += " ui-border"; - else $note.focus(); - self.onbeforeunload = saveDraft; - setInterval(saveDraft, 60 * 1000) + $note.onkeyup = updatePreview; + $('delete-button').onclick = $('publish-button').onclick = function(e) { + localStorage.removeItem('draft'); + self.onbeforeunload = null; + if ($plain_password.value !== '') $('password').value = md5($plain_password.value); + $plain_password.value = null; + $('signature').value = md5($('session').value + $note.value.replace(/[\n\r]/g, '')); + }; + if (iosDetected) $note.className += ' ui-border'; + else $note.focus(); + self.onbeforeunload = saveDraft; + setInterval(saveDraft, 60 * 1000); } diff --git a/server.js b/server.js index 0dd2c67..9c9bcb0 100644 --- a/server.js +++ b/server.js @@ -2,7 +2,7 @@ var express = require('express'); var view = require('./view'); var storage = require('./storage'); var md5 = require('md5'); -var LRU = require("lru-cache") +var LRU = require('lru-cache'); var bodyParser = require('body-parser'); var fs = require('fs'); var blackList; @@ -13,8 +13,8 @@ app.use(bodyParser.urlencoded({ extended: true, limit: '200kb' })); app.use(express.static(__dirname + '/resources/public')); app.use(function (error, req, res, next) { if (error) { - sendResponse(res, 400, "Bad request", error.message); - log("REQUEST ERROR:", error); + sendResponse(res, 400, 'Bad request', error.message); + log('REQUEST ERROR:', error); } else { next(); } @@ -24,28 +24,28 @@ var MODELS = {}; var CACHE = new LRU({ max: 50, dispose: key => { - log("disposing", key, "from cache"); + log('disposing', key, 'from cache'); var model = MODELS[key]; - model && model.save(); + if (model) model.save(); delete MODELS[key]; } }); var log = function() { var date = new Date(); - var timestamp = date.getDate() + "/" + date.getMonth() + " " + date.getHours() + ":" + - date.getMinutes() + ":" + date.getSeconds() + "." + date.getMilliseconds(); + var timestamp = date.getDate() + '/' + date.getMonth() + ' ' + date.getHours() + ':' + + date.getMinutes() + ':' + date.getSeconds() + '.' + date.getMilliseconds(); var message = Array.prototype.slice.call(arguments); - message.unshift("--"); + message.unshift('--'); message.unshift(timestamp); console.log.apply(console, message); -} +}; app.get('/TOS', (req, res) => res.send(view.renderTOS())); app.get('/new', (req, res) => { - log(req.ip, "opens /new"); - res.send(view.newNotePage(md5("new"))); + log(req.ip, 'opens /new'); + res.send(view.newNotePage(md5('new'))); }); app.post('/note', (req, res) => { @@ -55,43 +55,43 @@ app.post('/note', (req, res) => { password = body.password, action = body.action, id = body.id; - log(req.ip, "calls /note to", action, id); - var goToNote = note => res.redirect("/" + note.id); - if (!note || !session || session.indexOf(md5('edit/' + id)) != 0 && session.indexOf(md5('new')) != 0) + log(req.ip, 'calls /note to', action, id); + var goToNote = note => res.redirect('/' + note.id); + if (!note || !session || session.indexOf(md5('edit/' + id)) !== 0 && session.indexOf(md5('new')) !== 0) return sendResponse(res, 400, 'Bad request'); - if (body.signature != md5(session + note.replace(/[\n\r]/g, ""))) - return sendResponse(res, 400, "Signature mismatch"); - if (action == "POST") + if (body.signature != md5(session + note.replace(/[\n\r]/g, ''))) + return sendResponse(res, 400, 'Signature mismatch'); + if (action == 'POST') storage.addNote(note, password).then(goToNote); else { - if (!id) return sendResponse(res, 400, "Wrong note ID"); + if (!id) return sendResponse(res, 400, 'Wrong note ID'); CACHE.del(id); - if (body.button == "Delete") { - log("deleting note", id); + if (body.button == 'Delete') { + log('deleting note', id); storage.deleteNote(id, password).then( - () => sendResponse(res, 200, "Note deleted"), - error => sendResponse(res, 400, "Bad request", error.message)); + () => sendResponse(res, 200, 'Note deleted'), + error => sendResponse(res, 400, 'Bad request', error.message)); } else { - log("updating note", id); + log('updating note', id); 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) => { - var P = req.params, url = P.year + "/" + P.month + "/" + P.day + "/" + P.title; - log(req.ip, "resolves deprecated id", url); +app.get('/:year/:month/:day/:title', (req, res) => { + var P = req.params, url = P.year + '/' + P.month + '/' + P.day + '/' + P.title; + log(req.ip, 'resolves deprecated id', url); if (CACHE.has(url)) { - log(url, "is cached!"); + log(url, 'is cached!'); var id = CACHE.get(url); - if (id) res.redirect("/" + id); + if (id) res.redirect('/' + id); else notFound(res); } else storage.getNoteId(url).then(note => { - log(url, "is not cached, resolving..."); + log(url, 'is not cached, resolving...'); if (note) { CACHE.set(url, note.id); - res.redirect("/" + note.id) + res.redirect('/' + note.id); } else { CACHE.set(url, null); notFound(res); @@ -100,44 +100,44 @@ app.get("/:year/:month/:day/:title", (req, res) => { }); app.get(/\/([a-z0-9]+)\/edit/, (req, res) => { - var id = req.params["0"]; - log(req.ip, "calls /edit on", id); - storage.getNote(id).then(note => res.send(note - ? view.editNotePage(md5('edit/' + id), note) - : notFound(res))); + var id = req.params['0']; + log(req.ip, 'calls /edit on', id); + storage.getNote(id).then(note => res.send(note ? + view.editNotePage(md5('edit/' + id), note) : + notFound(res))); }); app.get(/\/([a-z0-9]+)\/export/, (req, res) => { - var id = req.params["0"]; - log(req.ip, "calls /export on", id); + var id = req.params['0']; + log(req.ip, 'calls /export on', id); res.set({ 'Content-Type': 'text/plain', 'Charset': 'utf-8' }); - storage.getNote(id).then(note => note - ? res.send(note.text) - : notFound(res)); + storage.getNote(id).then(note => note ? + res.send(note.text) : + notFound(res)); }); app.get(/\/([a-z0-9]+)\/stats/, (req, res) => { - var id = req.params["0"]; - log(req.ip, "calls /stats on", id); - var promise = id in MODELS - ? new Promise(resolve => resolve(MODELS[id])) - : storage.getNote(id); - promise.then(note => note - ? res.send(view.renderStats(note)) - : notFound(res)); + var id = req.params['0']; + log(req.ip, 'calls /stats on', id); + var promise = id in MODELS ? + new Promise(resolve => resolve(MODELS[id])) : + storage.getNote(id); + promise.then(note => note ? + res.send(view.renderStats(note)) : + notFound(res)); }); app.get(/\/([a-z0-9]+)/, (req, res) => { - var id = req.params["0"]; - log(req.ip, "open note", id, "from", req.get("Referer")); + var id = req.params['0']; + log(req.ip, 'open note', id, 'from', req.get('Referer')); if (CACHE.has(id)) { - log(id, "is cached!"); - var note = MODELS[id]; - if (!note) return notFound(res); - note.views++; + log(id, 'is cached!'); + var obj = MODELS[id]; + if (!obj) return notFound(res); + obj.views++; res.send(CACHE.get(id)); } else storage.getNote(id).then(note => { - log(id, "is not cached, resolving..."); + log(id, 'is not cached, resolving...'); if (!note) { CACHE.set(id, null); return notFound(res); @@ -151,31 +151,31 @@ app.get(/\/([a-z0-9]+)/, (req, res) => { }); var sendResponse = (res, code, message, details) => { - log("sending response", code, message); + log('sending response', code, message); res.status(code).send(view.renderPage(null, message, `

${message}


` + - `
${details || "¯\\_(ツ)_/¯"}
`, "")); -} + `
${details || '¯\\_(ツ)_/¯'}
`, '')); +}; -var notFound = res => sendResponse(res, 404, "Not found"); +var notFound = res => sendResponse(res, 404, 'Not found'); var server = app.listen(process.env.PORT || 3000, () => log('NoteHub server listening on port', server.address().port)); setInterval(() => { var keys = Object.keys(MODELS); - log("saving stats for", keys.length, "models..."); - keys.forEach(id => MODELS[id].save()) + log('saving stats for', keys.length, 'models...'); + keys.forEach(id => MODELS[id].save()); }, 5 * 60 * 1000); var updateBlackList = () => { - var ids = fs.readFileSync(process.env.BLACK_LIST || "/dev/null", "utf-8").split(/\n+/).filter(Boolean); - ids.forEach(id => CACHE.del(id)) + var ids = fs.readFileSync(process.env.BLACK_LIST || '/dev/null', 'utf-8').split(/\n+/).filter(Boolean); + ids.forEach(id => CACHE.del(id)); 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(); diff --git a/storage.js b/storage.js index 85c14c7..bc73204 100644 --- a/storage.js +++ b/storage.js @@ -32,7 +32,7 @@ var generateId = () => [1, 1, 1, 1, 1] var code = Math.floor(Math.random() * 36); return String.fromCharCode(code + (code < 10 ? 48 : 87)); }) - .join(""); + .join(''); var getFreeId = () => { var id = generateId(); @@ -46,9 +46,9 @@ module.exports.addNote = (note, password) => getFreeId().then(id => Note.create( })); var passwordCheck = (note, password, callback) => - (!note || note.password.length == 0 || note.password !== password) - ? new Promise((resolve, reject) => reject({ message: "Password is wrong" })) - : callback(); + (!note || note.password.length === 0 || note.password !== password) ? + new Promise((resolve, reject) => reject({ message: 'Password is wrong' })) : + callback(); module.exports.updateNote = (id, password, text) => Note.findById(id).then(note => diff --git a/view.js b/view.js index a9c5a99..3dde677 100644 --- a/view.js +++ b/view.js @@ -1,55 +1,55 @@ -var marked = require("marked"); -var fs = require("fs"); -var hljs = require("highlight.js"); +var marked = require('marked'); +var fs = require('fs'); +var hljs = require('highlight.js'); -var TOS = fs.readFileSync("resources/TOS.md", "utf-8"); -var pageTemplate = fs.readFileSync("resources/template.html", "utf-8"); -var footerTemplate = fs.readFileSync("resources/footer.html", "utf-8"); -var editTemplate = fs.readFileSync("resources/edit.html", "utf-8"); -var header = fs.readFileSync(process.env.HEADER || "/dev/null", "utf-8"); +var TOS = fs.readFileSync('resources/TOS.md', 'utf-8'); +var pageTemplate = fs.readFileSync('resources/template.html', 'utf-8'); +var footerTemplate = fs.readFileSync('resources/footer.html', 'utf-8'); +var editTemplate = fs.readFileSync('resources/edit.html', 'utf-8'); +var header = fs.readFileSync(process.env.HEADER || '/dev/null', 'utf-8'); var deriveTitle = text => text - .split(/[\n\r]/)[0].slice(0,25) - .replace(/[`~!@#\$%^&\*_|\+=\?;:'",.<>\{\}\\\/]/g, ""); + .split(/[\n\r]/)[0].slice(0,25) + .replace(/[`~!@#\$%^&\*_|\+=\?;:'",.<>\{\}\\\/]/g, ''); var renderPage = (id, title, content, footer, blackList) => pageTemplate - .replace("%HEADER%", blackList && blackList.has(id) ? header : "") - .replace("%TITLE%", title) - .replace("%CONTENT%", content.replace(//gi, "").replace(//gi, "")) - .replace("%FOOTER%", footer || ""); + .replace('%HEADER%', blackList && blackList.has(id) ? header : '') + .replace('%TITLE%', title) + .replace('%CONTENT%', content.replace(//gi, '').replace(//gi, '')) + .replace('%FOOTER%', footer || ''); marked.setOptions({ - langPrefix: "hljs lang-", - highlight: code => hljs.highlightAuto(code).value, + langPrefix: 'hljs lang-', + highlight: code => hljs.highlightAuto(code).value, }); module.exports.renderPage = renderPage; module.exports.renderStats = note => renderPage(note.id, deriveTitle(note.text), - `

Statistics

+ `

Statistics

- +
Published${note.published}
Edited${note.edited || "N/A"}
Edited${note.edited || 'N/A'}
Views${note.views}
`); -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, - deriveTitle(note.text), - marked(note.text), - footerTemplate.replace(/%LINK%/g, note.id), - blackList); + deriveTitle(note.text), + marked(note.text), + footerTemplate.replace(/%LINK%/g, note.id), + blackList); module.exports.newNotePage = session => editTemplate - .replace("%ACTION%", "POST") - .replace("%SESSION%", session) - .replace("%CONTENT%", "Loading..."); + .replace('%ACTION%', 'POST') + .replace('%SESSION%', session) + .replace('%CONTENT%', 'Loading...'); module.exports.editNotePage = (session, note) => editTemplate - .replace("%ACTION%", "UPDATE") - .replace("%SESSION%", session) - .replace("%ID%", note.id) - .replace("%CONTENT%", escape$(note.text)); + .replace('%ACTION%', 'UPDATE') + .replace('%SESSION%', session) + .replace('%ID%', note.id) + .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('');