From 4e64583a0b6175d2c9a6729ffde1472dd55d389c Mon Sep 17 00:00:00 2001 From: Wu Cheng-Han Date: Fri, 15 May 2015 12:58:13 +0800 Subject: Marked as 0.2.8 --- README.md | 19 +- app.js | 126 +- config.js | 55 +- lib/auth.js | 8 +- lib/db.js | 25 +- lib/realtime.js | 15 +- lib/response.js | 8 +- lib/temp.js | 83 + lib/user.js | 4 +- package.json | 10 +- public/css/cover.css | 61 +- public/css/github-extract.css | 3 +- public/css/index.css | 6 +- public/css/site.css | 1 + public/index.html | 73 +- public/js/common.js | 53 + public/js/cover.js | 245 +- public/js/extra.js | 6 +- public/js/fb.js | 8 + public/js/ga.js | 14 - public/js/history.js | 187 +- public/js/index.js | 419 +- public/js/pretty.js | 9 + public/js/syncscroll.js | 327 ++ public/vendor/codemirror/addon/dialog/dialog.css | 4 + .../codemirror/addon/scroll/annotatescrollbar.js | 2 +- .../codemirror/addon/scroll/simplescrollbars.css | 3 +- .../codemirror/addon/scroll/simplescrollbars.js | 3 +- public/vendor/codemirror/addon/search/search.js | 8 +- public/vendor/codemirror/codemirror.min.js | 18 +- public/vendor/codemirror/compress.sh | 12 +- public/vendor/codemirror/keymap/sublime.js | 12 +- public/vendor/gist-embed.js | 6 +- .../codemirror.inline-attachment.js | 95 + .../vendor/inlineAttachment/inline-attachment.js | 435 ++ public/vendor/jquery.cookie-1.4.1.min.js | 2 - public/vendor/js.cookie.js | 137 + public/vendor/select2/css/select2.css | 421 -- public/vendor/select2/css/select2.min.css | 1 - public/vendor/select2/js/i18n/az.js | 1 - public/vendor/select2/js/i18n/bg.js | 1 - public/vendor/select2/js/i18n/ca.js | 1 - public/vendor/select2/js/i18n/cs.js | 1 - public/vendor/select2/js/i18n/da.js | 1 - public/vendor/select2/js/i18n/de.js | 1 - public/vendor/select2/js/i18n/en.js | 1 - public/vendor/select2/js/i18n/es.js | 1 - public/vendor/select2/js/i18n/et.js | 1 - public/vendor/select2/js/i18n/eu.js | 1 - public/vendor/select2/js/i18n/fi.js | 1 - public/vendor/select2/js/i18n/fr.js | 1 - public/vendor/select2/js/i18n/gl.js | 1 - public/vendor/select2/js/i18n/hi.js | 1 - public/vendor/select2/js/i18n/hr.js | 1 - public/vendor/select2/js/i18n/hu.js | 1 - public/vendor/select2/js/i18n/id.js | 1 - public/vendor/select2/js/i18n/is.js | 1 - public/vendor/select2/js/i18n/it.js | 1 - public/vendor/select2/js/i18n/lt.js | 1 - public/vendor/select2/js/i18n/lv.js | 1 - public/vendor/select2/js/i18n/mk.js | 1 - public/vendor/select2/js/i18n/nb.js | 1 - public/vendor/select2/js/i18n/nl.js | 1 - public/vendor/select2/js/i18n/pl.js | 1 - public/vendor/select2/js/i18n/pt-BR.js | 1 - public/vendor/select2/js/i18n/pt.js | 1 - public/vendor/select2/js/i18n/ro.js | 1 - public/vendor/select2/js/i18n/ru.js | 1 - public/vendor/select2/js/i18n/sk.js | 1 - public/vendor/select2/js/i18n/sr.js | 1 - public/vendor/select2/js/i18n/sv.js | 1 - public/vendor/select2/js/i18n/th.js | 1 - public/vendor/select2/js/i18n/tr.js | 1 - public/vendor/select2/js/i18n/uk.js | 1 - public/vendor/select2/js/i18n/vi.js | 1 - public/vendor/select2/js/i18n/zh-CN.js | 1 - public/vendor/select2/js/i18n/zh-TW.js | 1 - public/vendor/select2/js/select2.amd.full.js | 5326 ------------------ public/vendor/select2/js/select2.amd.js | 4766 ---------------- public/vendor/select2/js/select2.full.js | 5765 -------------------- public/vendor/select2/js/select2.full.min.js | 3 - public/vendor/select2/js/select2.js | 5205 ------------------ public/vendor/select2/js/select2.min.js | 2 - public/vendor/select2/select2-bootstrap.css | 495 ++ public/vendor/select2/select2-spinner.gif | Bin 0 -> 1849 bytes public/vendor/select2/select2.css | 704 +++ public/vendor/select2/select2.min.js | 23 + public/vendor/select2/select2.png | Bin 0 -> 613 bytes public/vendor/select2/select2x2.png | Bin 0 -> 845 bytes public/vendor/store.min.js | 2 + public/vendor/url.min.js | 1 + public/views/foot.ejs | 53 +- public/views/head.ejs | 16 +- public/views/header.ejs | 4 +- public/views/pretty.ejs | 43 +- run.sh | 7 + 96 files changed, 3278 insertions(+), 22099 deletions(-) create mode 100644 lib/temp.js create mode 100644 public/js/common.js create mode 100644 public/js/fb.js delete mode 100644 public/js/ga.js create mode 100644 public/js/pretty.js create mode 100644 public/js/syncscroll.js create mode 100755 public/vendor/inlineAttachment/codemirror.inline-attachment.js create mode 100755 public/vendor/inlineAttachment/inline-attachment.js delete mode 100644 public/vendor/jquery.cookie-1.4.1.min.js create mode 100755 public/vendor/js.cookie.js delete mode 100755 public/vendor/select2/css/select2.css delete mode 100755 public/vendor/select2/css/select2.min.css delete mode 100755 public/vendor/select2/js/i18n/az.js delete mode 100755 public/vendor/select2/js/i18n/bg.js delete mode 100755 public/vendor/select2/js/i18n/ca.js delete mode 100755 public/vendor/select2/js/i18n/cs.js delete mode 100755 public/vendor/select2/js/i18n/da.js delete mode 100755 public/vendor/select2/js/i18n/de.js delete mode 100755 public/vendor/select2/js/i18n/en.js delete mode 100755 public/vendor/select2/js/i18n/es.js delete mode 100755 public/vendor/select2/js/i18n/et.js delete mode 100755 public/vendor/select2/js/i18n/eu.js delete mode 100755 public/vendor/select2/js/i18n/fi.js delete mode 100755 public/vendor/select2/js/i18n/fr.js delete mode 100755 public/vendor/select2/js/i18n/gl.js delete mode 100755 public/vendor/select2/js/i18n/hi.js delete mode 100755 public/vendor/select2/js/i18n/hr.js delete mode 100755 public/vendor/select2/js/i18n/hu.js delete mode 100755 public/vendor/select2/js/i18n/id.js delete mode 100755 public/vendor/select2/js/i18n/is.js delete mode 100755 public/vendor/select2/js/i18n/it.js delete mode 100755 public/vendor/select2/js/i18n/lt.js delete mode 100755 public/vendor/select2/js/i18n/lv.js delete mode 100755 public/vendor/select2/js/i18n/mk.js delete mode 100755 public/vendor/select2/js/i18n/nb.js delete mode 100755 public/vendor/select2/js/i18n/nl.js delete mode 100755 public/vendor/select2/js/i18n/pl.js delete mode 100755 public/vendor/select2/js/i18n/pt-BR.js delete mode 100755 public/vendor/select2/js/i18n/pt.js delete mode 100755 public/vendor/select2/js/i18n/ro.js delete mode 100755 public/vendor/select2/js/i18n/ru.js delete mode 100755 public/vendor/select2/js/i18n/sk.js delete mode 100755 public/vendor/select2/js/i18n/sr.js delete mode 100755 public/vendor/select2/js/i18n/sv.js delete mode 100755 public/vendor/select2/js/i18n/th.js delete mode 100755 public/vendor/select2/js/i18n/tr.js delete mode 100755 public/vendor/select2/js/i18n/uk.js delete mode 100755 public/vendor/select2/js/i18n/vi.js delete mode 100755 public/vendor/select2/js/i18n/zh-CN.js delete mode 100755 public/vendor/select2/js/i18n/zh-TW.js delete mode 100755 public/vendor/select2/js/select2.amd.full.js delete mode 100755 public/vendor/select2/js/select2.amd.js delete mode 100755 public/vendor/select2/js/select2.full.js delete mode 100755 public/vendor/select2/js/select2.full.min.js delete mode 100755 public/vendor/select2/js/select2.js delete mode 100755 public/vendor/select2/js/select2.min.js create mode 100644 public/vendor/select2/select2-bootstrap.css create mode 100755 public/vendor/select2/select2-spinner.gif create mode 100755 public/vendor/select2/select2.css create mode 100755 public/vendor/select2/select2.min.js create mode 100755 public/vendor/select2/select2.png create mode 100755 public/vendor/select2/select2x2.png create mode 100644 public/vendor/store.min.js create mode 100755 public/vendor/url.min.js create mode 100644 run.sh diff --git a/README.md b/README.md index e687ed91..8accba9f 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,25 @@ -HackMD 0.2.7 +HackMD 0.2.8 === This is a realtime collaborative markdown notes on all platforms. But still in early stage, feel free to fork or contribute to it. -Thanks for your using. +Thanks for your using! + +There are some config you need to change in below files +``` +./run.sh +./config.js +./public/js/common.js +``` + +You can use SSL to encrypt your site by passing certificate path in the `config.js` and set `usessl=true`. + +And there is a script called `run.sh`, it's for someone like me to run the server via npm package `forever`, and can passing environment variable to the server, like heroku does. + +To install `forever`, just type `npm install forever -g` The notes are store in PostgreSQL, and I provided the schema in the `hackmd_schema.sql`. The users and sessions are store in mongoDB, which don't need schema, so just connect it directly. -License under MIT. +**License under MIT.** \ No newline at end of file diff --git a/app.js b/app.js index 3f66b32c..d3984882 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,5 @@ //app //external modules -var connect = require('connect'); var express = require('express'); var toobusy = require('toobusy-js'); var ejs = require('ejs'); @@ -11,24 +10,45 @@ var mongoose = require('mongoose'); var compression = require('compression') var session = require('express-session'); var MongoStore = require('connect-mongo')(session); +var fs = require('fs'); +var shortid = require('shortid'); +var imgur = require('imgur'); +var formidable = require('formidable'); //core var config = require("./config.js"); var User = require("./lib/user.js"); +var Temp = require("./lib/temp.js"); var auth = require("./lib/auth.js"); var response = require("./lib/response.js"); //server setup -var app = express(); -var server = require('http').createServer(app); +if (config.usessl) { + var ca = (function () { + var i, len, results; + results = []; + for (i = 0, len = config.sslcapath.length; i < len; i++) { + results.push(fs.readFileSync(config.sslcapath[i], 'utf8')); + } + return results; + })(); + var options = { + key: fs.readFileSync(config.sslkeypath, 'utf8'), + cert: fs.readFileSync(config.sslcertpath, 'utf8'), + ca: ca, + requestCert: false, + rejectUnauthorized: false + }; + var app = express(); + var server = require('https').createServer(options, app); +} else { + var app = express(); + var server = require('http').createServer(app); +} var io = require('socket.io').listen(server); -var port = process.env.PORT || config.testport; // connect to the mongodb -if (config.debug) - mongoose.connect(config.mongodbstring); -else - mongoose.connect(process.env.MONGOLAB_URI); +mongoose.connect(process.env.MONGOLAB_URI || config.mongodbstring); //others var db = require("./lib/db.js"); @@ -53,7 +73,7 @@ app.use(session({ name: config.sessionname, secret: config.sessionsecret, resave: false, //don't save session if unmodified - saveUninitialized: true, //don't create session until something stored + saveUninitialized: false, //don't create session until something stored cookie: { maxAge: new Date(Date.now() + config.sessionlife), expires: new Date(Date.now() + config.sessionlife), @@ -111,6 +131,59 @@ app.get("/status", function (req, res, next) { res.end(JSON.stringify(data)); }); }); +//get status +app.get("/temp", function (req, res) { + var host = req.get('host'); + if (config.alloworigin.indexOf(host) == -1) + response.errorForbidden(res); + else { + var tempid = req.query.tempid; + if (!tempid) + response.errorForbidden(res); + else { + Temp.findTemp(tempid, function (err, temp) { + if (err || !temp) + response.errorForbidden(res); + else { + res.header("Access-Control-Allow-Origin", "*"); + res.send({ + temp: temp.data + }); + temp.remove(function (err) { + if (err) + console.log('remove temp failed: ' + err); + }); + } + }); + } + } +}); +//post status +app.post("/temp", urlencodedParser, function (req, res) { + var host = req.get('host'); + if (config.alloworigin.indexOf(host) == -1) + response.errorForbidden(res); + else { + var id = shortid.generate(); + var data = req.body.data; + if (!id || !data) + response.errorForbidden(res); + else { + if (config.debug) + console.log('SERVER received temp from [' + host + ']: ' + req.body.data); + Temp.newTemp(id, data, function (err, temp) { + if (!err && temp) { + res.header("Access-Control-Allow-Origin", "*"); + res.send({ + status: 'ok', + id: temp.id + }); + } else + response.errorInternalError(res); + }); + } + } +}); //facebook auth app.get('/auth/facebook', passport.authenticate('facebook'), @@ -230,6 +303,29 @@ app.get('/me', function (req, res) { }); } }); +//upload to imgur +app.post('/uploadimage', function (req, res) { + var form = new formidable.IncomingForm(); + form.parse(req, function (err, fields, files) { + if (err || !files.image || !files.image.path) { + response.errorForbidden(res); + } else { + if (config.debug) + console.log('SERVER received uploadimage: ' + JSON.stringify(files.image)); + imgur.setClientId(config.imgur.clientID); + imgur.uploadFile(files.image.path) + .then(function (json) { + if (config.debug) + console.log('SERVER uploadimage success: ' + JSON.stringify(json)); + res.send({link:json.data.link}); + }) + .catch(function (err) { + console.error(err); + res.send(err.message); + }); + } + }); +}); //get new note app.get("/new", response.newNote); //get features @@ -248,6 +344,12 @@ io.set('heartbeat timeout', config.heartbeattimeout); io.sockets.on('connection', realtime.connection); //listen -server.listen(port, function () { - console.log('Server listening at port %d', port); -}); \ No newline at end of file +if (config.usessl) { + server.listen(config.sslport, function () { + console.log('HTTPS Server listening at sslport %d', config.sslport); + }); +} else { + server.listen(config.port, function () { + console.log('HTTP Server listening at port %d', config.port); + }); +} \ No newline at end of file diff --git a/config.js b/config.js index 3a5c764c..03764fef 100644 --- a/config.js +++ b/config.js @@ -1,11 +1,33 @@ //config var path = require('path'); +var domain = process.env.DOMAIN; +var testport = '3000'; +var testsslport = '3001'; +var port = process.env.PORT || testport; +var sslport = process.env.SSLPORT || testsslport; +var usessl = false; +var urladdport = true; //add port on getserverurl + var config = { debug: true, - version: '0.2.7', - domain: 'http://localhost:3000', - testport: '3000', + version: '0.2.8', + domain: domain, + alloworigin: ['add here to allow origin to cross'], + testport: testport, + testsslport: testsslport, + port: port, + sslport: sslport, + sslkeypath: 'change this', + sslcertpath: 'change this', + sslcapath: ['change this'], + usessl: usessl, + getserverurl: function() { + if(usessl) + return 'https://' + domain + (sslport == 443 || !urladdport ? '' : ':' + sslport); + else + return 'http://' + domain + (port == 80 || !urladdport ? '' : ':' + port); + }, //path tmppath: "./tmp/", defaultnotepath: path.join(__dirname, '/public', "default.md"), @@ -14,36 +36,39 @@ var config = { errorpath: path.join(__dirname, '/public/views', "error.ejs"), prettypath: path.join(__dirname, '/public/views', 'pretty.ejs'), //db string - postgresqlstring: "postgresql://localhost:5432/hackmd", - mongodbstring: "mongodb://localhost/hackmd", + postgresqlstring: "change this", + mongodbstring: "change this", //constants featuresnotename: "features", - sessionname: 'please set this', - sessionsecret: 'please set this', + sessionname: 'change this', + sessionsecret: 'change this', sessionlife: 14 * 24 * 60 * 60 * 1000, //14 days sessiontouch: 1 * 3600, //1 hour heartbeatinterval: 5000, heartbeattimeout: 10000, //auth facebook: { - clientID: 'get yourself one', - clientSecret: 'get yourself one', + clientID: 'change this', + clientSecret: 'change this', callbackPath: '/auth/facebook/callback' }, twitter: { - consumerKey: 'get yourself one', - consumerSecret: 'get yourself one', + consumerKey: 'change this', + consumerSecret: 'change this', callbackPath: '/auth/twitter/callback' }, github: { - clientID: 'get yourself one', - clientSecret: 'get yourself one', + clientID: 'change this', + clientSecret: 'change this', callbackPath: '/auth/github/callback' }, dropbox: { - clientID: 'get yourself one', - clientSecret: 'get yourself one', + clientID: 'change this', + clientSecret: 'change this', callbackPath: '/auth/dropbox/callback' + }, + imgur: { + clientID: 'change this' } }; diff --git a/lib/auth.js b/lib/auth.js index e7b0dc7c..456c9dff 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -27,23 +27,23 @@ function callback(accessToken, refreshToken, profile, done) { module.exports = passport.use(new FacebookStrategy({ clientID: config.facebook.clientID, clientSecret: config.facebook.clientSecret, - callbackURL: config.domain + config.facebook.callbackPath + callbackURL: config.getserverurl() + config.facebook.callbackPath }, callback)); //twitter passport.use(new TwitterStrategy({ consumerKey: config.twitter.consumerKey, consumerSecret: config.twitter.consumerSecret, - callbackURL: config.domain + config.twitter.callbackPath + callbackURL: config.getserverurl() + config.twitter.callbackPath }, callback)); //github passport.use(new GithubStrategy({ clientID: config.github.clientID, clientSecret: config.github.clientSecret, - callbackURL: config.domain + config.github.callbackPath + callbackURL: config.getserverurl() + config.github.callbackPath }, callback)); //dropbox passport.use(new DropboxStrategy({ clientID: config.dropbox.clientID, clientSecret: config.dropbox.clientSecret, - callbackURL: config.domain + config.dropbox.callbackPath + callbackURL: config.getserverurl() + config.dropbox.callbackPath }, callback)); \ No newline at end of file diff --git a/lib/db.js b/lib/db.js index d763eb83..d924cdf8 100644 --- a/lib/db.js +++ b/lib/db.js @@ -18,10 +18,7 @@ var db = { }; function getDBClient() { - if (config.debug) - return new pg.Client(config.postgresqlstring); - else - return new pg.Client(process.env.DATABASE_URL); + return new pg.Client(process.env.DATABASE_URL || config.postgresqlstring); } function readFromFile(callback) { @@ -49,12 +46,14 @@ function newToDB(id, owner, body, callback) { var client = getDBClient(); client.connect(function (err) { if (err) { + client.end(); callback(err, null); return console.error('could not connect to postgres', err); } var newnotequery = util.format(insertquery, id, owner, body); //console.log(newnotequery); client.query(newnotequery, function (err, result) { + client.end(); if (err) { callback(err, null); return console.error("new note to db failed: " + err); @@ -62,7 +61,6 @@ function newToDB(id, owner, body, callback) { if (config.debug) console.log("new note to db success"); callback(null, result); - client.end(); } }); }); @@ -72,23 +70,25 @@ function readFromDB(id, callback) { var client = getDBClient(); client.connect(function (err) { if (err) { + client.end(); callback(err, null); return console.error('could not connect to postgres', err); } var readquery = util.format(selectquery, id); //console.log(readquery); client.query(readquery, function (err, result) { + client.end(); if (err) { callback(err, null); return console.error("read from db failed: " + err); } else { //console.log(result.rows); if (result.rows.length <= 0) { - callback("not found note in db", null); + callback("not found note in db: " + id, null); } else { - console.log("read from db success"); + if(config.debug) + console.log("read from db success"); callback(null, result); - client.end(); } } }); @@ -99,12 +99,14 @@ function saveToDB(id, title, data, callback) { var client = getDBClient(); client.connect(function (err) { if (err) { + client.end(); callback(err, null); return console.error('could not connect to postgres', err); } var savequery = util.format(updatequery, title, data, id); //console.log(savequery); client.query(savequery, function (err, result) { + client.end(); if (err) { callback(err, null); return console.error("save to db failed: " + err); @@ -112,7 +114,6 @@ function saveToDB(id, title, data, callback) { if (config.debug) console.log("save to db success"); callback(null, result); - client.end(); } }); }); @@ -122,10 +123,12 @@ function countFromDB(callback) { var client = getDBClient(); client.connect(function (err) { if (err) { + client.end(); callback(err, null); return console.error('could not connect to postgres', err); } client.query(countquery, function (err, result) { + client.end(); if (err) { callback(err, null); return console.error("count from db failed: " + err); @@ -134,9 +137,9 @@ function countFromDB(callback) { if (result.rows.length <= 0) { callback("not found note in db", null); } else { - console.log("count from db success"); + if(config.debug) + console.log("count from db success"); callback(null, result); - client.end(); } } }); diff --git a/lib/realtime.js b/lib/realtime.js index 303eb6a6..e3800275 100644 --- a/lib/realtime.js +++ b/lib/realtime.js @@ -81,10 +81,11 @@ function getStatus(callback) { break; } } - if (!found) + if (!found) { distinctaddresses.push(value.address); - if(!found && value.login) - distinctregusers++; + if(value.login) + distinctregusers++; + } }); User.getUserCount(function (err, regcount) { if (err) { @@ -372,11 +373,19 @@ function connection(socket) { switch (op.origin) { case '+input': case '+delete': + case '+transpose': case 'paste': case 'cut': case 'undo': case 'redo': case 'drag': + case '*compose': + case 'case': + case '+insertLine': + case '+swapLine': + case '+joinLines': + case '+duplicateLine': + case '+sortLines': notes[notename].socks.forEach(function (sock) { if (sock != socket) { if (config.debug) diff --git a/lib/response.js b/lib/response.js index 458ed01f..a7dcc023 100644 --- a/lib/response.js +++ b/lib/response.js @@ -17,16 +17,16 @@ var Note = require("./note.js"); //public var response = { errorForbidden: function (res) { - res.status(403).send("Forbidden, oh no.") + res.status(403).send("Forbidden, oh no."); }, errorNotFound: function (res) { - responseError(res, "404", "Not Found", "oops.") + responseError(res, "404", "Not Found", "oops."); }, errorInternalError: function (res) { - responseError(res, "500", "Internal Error", "wtf.") + responseError(res, "500", "Internal Error", "wtf."); }, errorServiceUnavailable: function (res) { - res.status(503).send("I'm busy right now, try again later.") + res.status(503).send("I'm busy right now, try again later."); }, newNote: newNote, showFeatures: showFeatures, diff --git a/lib/temp.js b/lib/temp.js new file mode 100644 index 00000000..90d9343f --- /dev/null +++ b/lib/temp.js @@ -0,0 +1,83 @@ +//temp +//external modules +var mongoose = require('mongoose'); + +//core +var config = require("../config.js"); + +// create a temp model +var model = mongoose.model('temp', { + id: String, + data: String, + created: Date +}); + +//public +var temp = { + model: model, + findTemp: findTemp, + newTemp: newTemp, + removeTemp: removeTemp, + getTempCount: getTempCount +}; + +function getTempCount(callback) { + model.count(function(err, count){ + if(err) callback(err, null); + else callback(null, count); + }); +} + +function findTemp(id, callback) { + model.findOne({ + id: id + }, function (err, temp) { + if (err) { + console.log('find temp failed: ' + err); + callback(err, null); + } + if (!err && temp) { + callback(null, temp); + } else { + console.log('find temp failed: ' + err); + callback(err, null); + }; + }); +} + +function newTemp(id, data, callback) { + var temp = new model({ + id: id, + data: data, + created: Date.now() + }); + temp.save(function (err) { + if (err) { + console.log('new temp failed: ' + err); + callback(err, null); + } else { + console.log("new temp success: " + temp.id); + callback(null, temp); + }; + }); +} + +function removeTemp(id, callback) { + findTemp(id, function(err, temp) { + if(!err && temp) { + temp.remove(function(err) { + if(err) { + console.log('remove temp failed: ' + err); + callback(err, null); + } else { + callback(null, null); + } + }); + } else { + console.log('remove temp failed: ' + err); + callback(err, null); + } + }); +} + +module.exports = temp; \ No newline at end of file diff --git a/lib/user.js b/lib/user.js index 1d7f11d2..11064506 100644 --- a/lib/user.js +++ b/lib/user.js @@ -37,7 +37,7 @@ function findUser(id, callback) { console.log('find user failed: ' + err); callback(err, null); } - if (!err && user != null) { + if (!err && user) { callback(null, user); } else { console.log('find user failed: ' + err); @@ -65,7 +65,7 @@ function newUser(id, profile, callback) { function findOrNewUser(id, profile, callback) { findUser(id, function(err, user) { - if(err || user == null) { + if(err || !user) { newUser(id, profile, function(err, user) { if(err) { console.log('find or new user failed: ' + err); diff --git a/package.json b/package.json index 7c38fec6..2d2d4625 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "hackmd", - "version": "0.2.7", + "version": "0.2.8", "description": "Realtime collaborative markdown notes on all platforms.", - "main": "server.js", - "author": "jackymaxj", + "main": "app.js", + "author": "jackycute", "private": true, "license": "MIT", "dependencies": { @@ -11,7 +11,6 @@ "body-parser": "^1.12.3", "cheerio": "^0.19.0", "compression": "^1.4.3", - "connect": "3.x", "connect-mongo": "^0.8.1", "cookie": "0.1.2", "cookie-parser": "1.3.3", @@ -19,8 +18,9 @@ "emojify.js": "^1.0.1", "express": "4.x", "express-session": "^1.11.1", + "formidable": "^1.0.17", "highlight.js": "^8.4.0", - "html": "0.0.7", + "imgur": "^0.1.5", "jsdom-nogyp": "^0.8.3", "lz-string": "1.3.6", "markdown-pdf": "^5.2.0", diff --git a/public/css/cover.css b/public/css/cover.css index da4207b8..30d54d34 100644 --- a/public/css/cover.css +++ b/public/css/cover.css @@ -23,13 +23,15 @@ a:hover { /* * Base structure */ - +html { + height: 100%; +} html, body { - height: 100%; background-color: #333; } body { + min-height: 100%; color: #fff; text-align: center; text-shadow: 0 1px 3px rgba(0, 0, 0, .5); @@ -40,7 +42,7 @@ body { padding: 10px; display: table; width: 100%; - height: 100%; + height: 100vh; /* For at least Firefox */ min-height: 100%; -webkit-box-shadow: inset 0 0 100px rgba(0, 0, 0, .5); @@ -156,7 +158,7 @@ body { .masthead, .mastfoot, .cover-container { - width: 700px; + width: 1000px; } } .section ul { @@ -168,41 +170,14 @@ html, body { overflow-x: hidden; } -.select2-selection, -.select2-search__field { - outline: 0; -} -.select2-search__field:hover { - border: 1px solid #b9b9b9 !important; - border-top-color: #a0a0a0 !important; -} -.select2-search__field:focus { - border: 1px solid #4d90fe !important; -} input { color: black; } .mastfoot { position: relative; } -.select2 { - width: 100% !important; - max-width: 400px; -} -.select2-selection { - height: 32px !important; -} -.select2-selection__rendered { - line-height: 32px !important; -} -.select2-selection__arrow { - height: 30px !important; -} -.select2-selection__rendered, -.select2-selection__placeholder, -.select2-results__option { - color: #000; - text-shadow: none; +.select2-container { + margin: 0 auto !important; } .list { width: 100%; @@ -275,4 +250,24 @@ input { .modal-title { text-align: left; color: black; +} + +.btn-file { + position: relative; + overflow: hidden; +} +.btn-file input[type=file] { + position: absolute; + top: 0; + right: 0; + min-width: 100%; + min-height: 100%; + font-size: 100px; + text-align: right; + filter: alpha(opacity=0); + opacity: 0; + outline: none; + background: white; + cursor: inherit; + display: block; } \ No newline at end of file diff --git a/public/css/github-extract.css b/public/css/github-extract.css index 201aebc6..67ceb418 100644 --- a/public/css/github-extract.css +++ b/public/css/github-extract.css @@ -1,6 +1,5 @@ .markdown-body { overflow: hidden; - font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; font-size: 16px; line-height: 1.6; word-wrap: break-word; @@ -339,7 +338,7 @@ } .task-list-item-checkbox { float: left; - margin: 0.4em 0 0.2em -1.3em !important; + margin: 0.31em 0 0.2em -1.3em !important; vertical-align: middle; cursor: default !important; } \ No newline at end of file diff --git a/public/css/index.css b/public/css/index.css index 6cfbeab0..b3a6bae5 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -20,7 +20,7 @@ form, font-family: 'Source Code Pro', Consolas, monaco, monospace; line-height: 18px; font-size: 16px; - height: auto; + /*height: auto;*/ min-height: 100%; overflow-y: hidden !important; -webkit-overflow-scrolling: touch; @@ -30,7 +30,7 @@ form, overflow-y: auto !important; } .CodeMirror-code { - padding-bottom: 100px; + /*padding-bottom: 72px;*/ } .CodeMirror-linenumber { opacity: 0.5; @@ -43,7 +43,7 @@ form, .CodeMirror-foldmarker { color: #d0d0d0; text-shadow: none; - font-family: arial; + font-family: Arial; line-height: .3; cursor: pointer; margin: 2px; diff --git a/public/css/site.css b/public/css/site.css index b50a1f9b..eed8b950 100644 --- a/public/css/site.css +++ b/public/css/site.css @@ -6,6 +6,7 @@ body { text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004); /*text-rendering: optimizeLegibility;*/ -webkit-overflow-scrolling: touch; + font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft JhengHei", sans-serif !important; } :focus { outline: none !important; diff --git a/public/index.html b/public/index.html index ab844ab8..c52b8ec3 100644 --- a/public/index.html +++ b/public/index.html @@ -10,13 +10,6 @@ - - - - - - -
- Realtime collaborate notes.
-
Using markdown syntax.
-
On all platforms.
+ Realtime collaborative markdown notes on all platforms.
Below are history from cookie
+Below are history from browser