diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/config.js | 19 | ||||
-rw-r--r-- | lib/history.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160607060246-support-revision.js | 5 | ||||
-rw-r--r-- | lib/models/index.js | 21 | ||||
-rw-r--r-- | lib/models/note.js | 84 | ||||
-rw-r--r-- | lib/models/revision.js | 43 | ||||
-rwxr-xr-x | lib/ot/editor-socketio-server.js | 8 | ||||
-rw-r--r-- | lib/realtime.js | 62 | ||||
-rwxr-xr-x | lib/response.js | 94 | ||||
-rw-r--r-- | lib/workers/dmpWorker.js | 14 |
10 files changed, 193 insertions, 159 deletions
diff --git a/lib/config.js b/lib/config.js index 053d083b..2f6792b7 100644 --- a/lib/config.js +++ b/lib/config.js @@ -19,11 +19,13 @@ var urladdport = process.env.HMD_URL_ADDPORT ? (process.env.HMD_URL_ADDPORT === var usecdn = process.env.HMD_USECDN ? (process.env.HMD_USECDN === 'true') : ((typeof config.usecdn === 'boolean') ? config.usecdn : true); +var allowanonymous = process.env.HMD_ALLOW_ANONYMOUS ? (process.env.HMD_ALLOW_ANONYMOUS === 'true') : ((typeof config.allowanonymous === 'boolean') ? config.allowanonymous : true); + +var allowfreeurl = process.env.HMD_ALLOW_FREEURL ? (process.env.HMD_ALLOW_FREEURL === 'true') : !!config.allowfreeurl; + // db -var db = config.db || { - dialect: 'sqlite', - storage: './db.hackmd.sqlite' -}; +var dburl = config.dburl || process.env.HMD_DB_URL || process.env.DATABASE_URL; +var db = config.db || {}; // ssl path var sslkeypath = config.sslkeypath || ''; @@ -125,7 +127,7 @@ if (process.env.HMD_LDAP_TLS_CA) { ldap.tlsOptions = ldap.tlsOptions ? Object.assign(ldap.tlsOptions, ca) : ca } var imgur = process.env.HMD_IMGUR_CLIENTID || config.imgur || false; -var email = process.env.HMD_EMAIL || config.email || false; +var email = process.env.HMD_EMAIL ? (process.env.HMD_EMAIL === 'true') : !!config.email; function getserverurl() { var url = ''; @@ -140,8 +142,8 @@ function getserverurl() { return url; } -var version = '0.4.5'; -var minimumCompatibleVersion = '0.4.5'; +var version = '0.5.0'; +var minimumCompatibleVersion = '0.5.0'; var maintenance = true; var cwd = path.join(__dirname, '..'); @@ -156,6 +158,9 @@ module.exports = { usessl: usessl, serverurl: getserverurl(), usecdn: usecdn, + allowanonymous: allowanonymous, + allowfreeurl: allowfreeurl, + dburl: dburl, db: db, sslkeypath: path.join(cwd, sslkeypath), sslcertpath: path.join(cwd, sslcertpath), diff --git a/lib/history.js b/lib/history.js index 4a3bbe1e..2723422c 100644 --- a/lib/history.js +++ b/lib/history.js @@ -27,10 +27,10 @@ var updater = setInterval(function () { if (cache.isDirty) { if (config.debug) logger.info("history updater found dirty history: " + key); var history = parseHistoryToArray(cache.history); + cache.isDirty = false; finishUpdateHistory(key, history, function (err, count) { if (err) return callback(err, null); if (!count) return callback(null, null); - cache.isDirty = false; cache.updateAt = Date.now(); return callback(null, null); }); diff --git a/lib/migrations/20160607060246-support-revision.js b/lib/migrations/20160607060246-support-revision.js index 9721d7fc..fa647d93 100644 --- a/lib/migrations/20160607060246-support-revision.js +++ b/lib/migrations/20160607060246-support-revision.js @@ -4,7 +4,10 @@ module.exports = { up: function (queryInterface, Sequelize) { queryInterface.addColumn('Notes', 'savedAt', Sequelize.DATE); queryInterface.createTable('Revisions', { - id: Sequelize.UUID, + id: { + type: Sequelize.UUID, + primaryKey: true + }, noteId: Sequelize.UUID, patch: Sequelize.TEXT, lastContent: Sequelize.TEXT, diff --git a/lib/models/index.js b/lib/models/index.js index d52f5508..e83956e5 100644 --- a/lib/models/index.js +++ b/lib/models/index.js @@ -13,10 +13,25 @@ var dbconfig = config.db; dbconfig.logging = config.debug ? logger.info : false; var sequelize = null; -if (dbconfig.hasOwnProperty('username') || dbconfig.hasOwnProperty('password')) - sequelize = new Sequelize(dbconfig.database, dbconfig.username, dbconfig.password, dbconfig); + +// Heroku specific +if (config.dburl) + sequelize = new Sequelize(config.dburl, dbconfig); else - sequelize = new Sequelize(dbconfig.database, dbconfig); + sequelize = new Sequelize(dbconfig.database, dbconfig.username, dbconfig.password, dbconfig); + +// [Postgres] Handling NULL bytes +// https://github.com/sequelize/sequelize/issues/6485 +function stripNullByte(value) { + return value ? value.replace(/\u0000/g, "") : value; +} +sequelize.stripNullByte = stripNullByte; + +function processData(data, _default, process) { + if (data === undefined) return data; + else return data === null ? _default : (process ? process(data) : data); +} +sequelize.processData = processData; var db = {}; diff --git a/lib/models/note.js b/lib/models/note.js index 5727046c..132f8b1e 100644 --- a/lib/models/note.js +++ b/lib/models/note.js @@ -52,13 +52,31 @@ module.exports = function (sequelize, DataTypes) { defaultValue: 0 }, title: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('title'), ""); + }, + set: function (value) { + this.setDataValue('title', sequelize.stripNullByte(value)); + } }, content: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('content'), ""); + }, + set: function (value) { + this.setDataValue('content', sequelize.stripNullByte(value)); + } }, authorship: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('authorship'), [], JSON.parse); + }, + set: function (value) { + this.setDataValue('authorship', JSON.stringify(value)); + } }, lastchangeAt: { type: DataTypes.DATE @@ -124,8 +142,6 @@ module.exports = function (sequelize, DataTypes) { var body = fs.readFileSync(filePath, 'utf8'); var contentLength = body.length; var title = Note.parseNoteTitle(body); - body = LZString.compressToBase64(body); - title = LZString.compressToBase64(title); if (fsModifiedTime.isAfter(dbModifiedTime) && note.content !== body) { note.update({ title: title, @@ -135,14 +151,14 @@ module.exports = function (sequelize, DataTypes) { sequelize.models.Revision.saveNoteRevision(note, function (err, revision) { if (err) return _callback(err, null); // update authorship on after making revision of docs - var patch = dmp.patch_fromText(LZString.decompressFromBase64(revision.patch)); + var patch = dmp.patch_fromText(revision.patch); var operations = Note.transformPatchToOperations(patch, contentLength); - var authorship = note.authorship ? JSON.parse(LZString.decompressFromBase64(note.authorship)) : []; + var authorship = note.authorship; for (var i = 0; i < operations.length; i++) { authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship); } note.update({ - authorship: LZString.compressToBase64(JSON.stringify(authorship)) + authorship: JSON.stringify(authorship) }).then(function (note) { return callback(null, note.id); }).catch(function (err) { @@ -220,33 +236,17 @@ module.exports = function (sequelize, DataTypes) { }); }, parseNoteInfo: function (body) { - var meta = null; - try { - var obj = metaMarked(body); - body = obj.markdown; - meta = obj.meta; - } catch (err) { - //na - } - if (!meta) meta = {}; - var $ = cheerio.load(md.render(body)); + var parsed = Note.extractMeta(body); + var $ = cheerio.load(md.render(parsed.markdown)); return { - title: Note.extractNoteTitle(meta, $), - tags: Note.extractNoteTags(meta, $) + title: Note.extractNoteTitle(parsed.meta, $), + tags: Note.extractNoteTags(parsed.meta, $) }; }, parseNoteTitle: function (body) { - var meta = null; - try { - var obj = metaMarked(body); - body = obj.markdown; - meta = obj.meta; - } catch (err) { - //na - } - if (!meta) meta = {}; - var $ = cheerio.load(md.render(body)); - return Note.extractNoteTitle(meta, $); + var parsed = Note.extractMeta(body); + var $ = cheerio.load(md.render(parsed.markdown)); + return Note.extractNoteTitle(parsed.meta, $); }, extractNoteTitle: function (meta, $) { var title = ""; @@ -264,10 +264,7 @@ module.exports = function (sequelize, DataTypes) { return markdown.substr(0, 100).replace(/(?:\r\n|\r|\n)/g, ' '); }, decodeTitle: function (title) { - var decodedTitle = LZString.decompressFromBase64(title); - if (decodedTitle) title = decodedTitle; - else title = 'Untitled'; - return title; + return title ? title : 'Untitled'; }, generateWebTitle: function (title) { title = !title || title == "Untitled" ? "HackMD - Collaborative markdown notes" : title + " - HackMD"; @@ -307,6 +304,19 @@ module.exports = function (sequelize, DataTypes) { } return tags; }, + extractMeta: function (content) { + try { + var obj = metaMarked(content); + if (!obj.markdown) obj.markdown = ""; + if (!obj.meta) obj.meta = {}; + } catch (err) { + var obj = { + markdown: content, + meta: {} + }; + } + return obj; + }, parseMeta: function (meta) { var _meta = {}; if (meta) { @@ -496,8 +506,8 @@ module.exports = function (sequelize, DataTypes) { if (Note.checkFileExist(filePath)) { var fsCreatedTime = moment(fs.statSync(filePath).ctime); body = fs.readFileSync(filePath, 'utf8'); - note.title = LZString.compressToBase64(Note.parseNoteTitle(body)); - note.content = LZString.compressToBase64(body); + note.title = Note.parseNoteTitle(body); + note.content = body; if (filePath !== config.defaultnotepath) { note.createdAt = fsCreatedTime; } diff --git a/lib/models/revision.js b/lib/models/revision.js index 8b8eba94..c7360fed 100644 --- a/lib/models/revision.js +++ b/lib/models/revision.js @@ -2,7 +2,6 @@ // external modules var Sequelize = require("sequelize"); -var LZString = require('lz-string'); var async = require('async'); var moment = require('moment'); var childProcess = require('child_process'); @@ -60,19 +59,43 @@ module.exports = function (sequelize, DataTypes) { defaultValue: Sequelize.UUIDV4 }, patch: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('patch'), ""); + }, + set: function (value) { + this.setDataValue('patch', sequelize.stripNullByte(value)); + } }, lastContent: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('lastContent'), ""); + }, + set: function (value) { + this.setDataValue('lastContent', sequelize.stripNullByte(value)); + } }, content: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('content'), ""); + }, + set: function (value) { + this.setDataValue('content', sequelize.stripNullByte(value)); + } }, length: { type: DataTypes.INTEGER }, authorship: { - type: DataTypes.TEXT + type: DataTypes.TEXT, + get: function () { + return sequelize.processData(this.getDataValue('authorship'), [], JSON.parse); + }, + set: function (value) { + this.setDataValue('authorship', value ? JSON.stringify(value) : value); + } } }, { classMethods: { @@ -214,7 +237,7 @@ module.exports = function (sequelize, DataTypes) { Revision.create({ noteId: note.id, lastContent: note.content, - length: LZString.decompressFromBase64(note.content).length, + length: note.content.length, authorship: note.authorship }).then(function (revision) { Revision.finishSaveNoteRevision(note, revision, callback); @@ -223,8 +246,8 @@ module.exports = function (sequelize, DataTypes) { }); } else { var latestRevision = revisions[0]; - var lastContent = LZString.decompressFromBase64(latestRevision.content || latestRevision.lastContent); - var content = LZString.decompressFromBase64(note.content); + var lastContent = latestRevision.content || latestRevision.lastContent; + var content = note.content; sendDmpWorker({ msg: 'create patch', lastDoc: lastContent, @@ -244,9 +267,9 @@ module.exports = function (sequelize, DataTypes) { } else { Revision.create({ noteId: note.id, - patch: LZString.compressToBase64(patch), + patch: patch, content: note.content, - length: LZString.decompressFromBase64(note.content).length, + length: note.content.length, authorship: note.authorship }).then(function (revision) { // clear last revision content to reduce db size diff --git a/lib/ot/editor-socketio-server.js b/lib/ot/editor-socketio-server.js index d062fa19..7b204539 100755 --- a/lib/ot/editor-socketio-server.js +++ b/lib/ot/editor-socketio-server.js @@ -7,7 +7,6 @@ var Server = require('./server'); var Selection = require('./selection'); var util = require('util'); -var LZString = require('lz-string'); var logger = require('../logger'); function EditorSocketIOServer(document, operations, docId, mayWrite, operationCallback) { @@ -40,10 +39,8 @@ EditorSocketIOServer.prototype.addClient = function (socket) { revision: this.operations.length, clients: this.users }; - socket.emit('doc', LZString.compressToUTF16(JSON.stringify(docOut))); + socket.emit('doc', docOut); socket.on('operation', function (revision, operation, selection) { - operation = LZString.decompressFromUTF16(operation); - operation = JSON.parse(operation); socket.origin = 'operation'; self.mayWrite(socket, function (mayWrite) { if (!mayWrite) { @@ -62,7 +59,7 @@ EditorSocketIOServer.prototype.addClient = function (socket) { clients: self.users, force: true }; - socket.emit('doc', LZString.compressToUTF16(JSON.stringify(docOut))); + socket.emit('doc', docOut); }, 100); } }); @@ -129,7 +126,6 @@ EditorSocketIOServer.prototype.onGetOperations = function (socket, base, head) { var operations = this.operations.slice(base, head).map(function (op) { return op.wrapped.toJSON(); }); - operations = LZString.compressToUTF16(JSON.stringify(operations)); socket.emit('operations', head, operations); }; diff --git a/lib/realtime.js b/lib/realtime.js index 73f831f4..a662deeb 100644 --- a/lib/realtime.js +++ b/lib/realtime.js @@ -71,7 +71,6 @@ function emitCheck(note) { authors: note.authors, authorship: note.authorship }; - out = LZString.compressToUTF16(JSON.stringify(out)); realtime.io.to(note.id).emit('check', out); } @@ -84,6 +83,7 @@ var updater = setInterval(function () { var note = notes[key]; if (note.server.isDirty) { if (config.debug) logger.info("updater found dirty note: " + key); + note.server.isDirty = false; updateNote(note, function(err, _note) { // handle when note already been clean up if (!notes[key] || !notes[key].server) return callback(null, null); @@ -104,7 +104,6 @@ var updater = setInterval(function () { } return callback(err, null); } - note.server.isDirty = false; note.updatetime = moment(_note.lastchangeAt).valueOf(); emitCheck(note); return callback(null, null); @@ -153,12 +152,10 @@ function finishUpdateNote(note, _note, callback) { if (!note || !note.server) return callback(null, null); var body = note.server.document; var title = note.title = models.Note.parseNoteTitle(body); - title = LZString.compressToBase64(title); - body = LZString.compressToBase64(body); var values = { title: title, content: body, - authorship: LZString.compressToBase64(JSON.stringify(note.authorship)), + authorship: note.authorship, lastchangeuserId: note.lastchangeuser, lastchangeAt: Date.now() }; @@ -211,6 +208,7 @@ function getStatus(callback) { var distinctregaddresses = []; Object.keys(users).forEach(function (key) { var user = users[key]; + if (!user) return; var found = false; for (var i = 0; i < distinctaddresses.length; i++) { if (user.address == distinctaddresses[i]) { @@ -300,14 +298,14 @@ function emitOnlineUsers(socket) { var out = { users: users }; - out = LZString.compressToUTF16(JSON.stringify(out)); realtime.io.to(noteId).emit('online users', out); } function emitUserStatus(socket) { var noteId = socket.noteId; - if (!noteId || !notes[noteId]) return; - var out = buildUserOutData(users[socket.id]); + var user = users[socket.id]; + if (!noteId || !notes[noteId] || !user) return; + var out = buildUserOutData(user); socket.broadcast.to(noteId).emit('user status', out); } @@ -328,7 +326,6 @@ function emitRefresh(socket) { createtime: note.createtime, updatetime: note.updatetime }; - out = LZString.compressToUTF16(JSON.stringify(out)); socket.emit('refresh', out); } @@ -460,7 +457,7 @@ function startConnection(socket) { var lastchangeuser = note.lastchangeuserId; var lastchangeuserprofile = note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null; - var body = LZString.decompressFromBase64(note.content); + var body = note.content; var createtime = note.createdAt; var updatetime = note.lastchangeAt; var server = new ot.EditorSocketIOServer(body, [], noteId, ifMayEdit, operationCallback); @@ -480,7 +477,7 @@ function startConnection(socket) { notes[noteId] = { id: noteId, alias: note.alias, - title: LZString.decompressFromBase64(note.title), + title: note.title, owner: owner, ownerprofile: ownerprofile, permission: note.permission, @@ -492,7 +489,7 @@ function startConnection(socket) { updatetime: moment(updatetime).valueOf(), server: server, authors: authors, - authorship: note.authorship ? JSON.parse(LZString.decompressFromBase64(note.authorship)) : [] + authorship: note.authorship }; return finishConnection(socket, notes[noteId], users[socket.id]); @@ -532,7 +529,9 @@ function disconnect(socket) { var note = notes[noteId]; if (note) { // delete user in users - delete note.users[socket.id]; + if (note.users[socket.id]) { + delete note.users[socket.id]; + } // remove sockets in the note socks do { var index = note.socks.indexOf(socket); @@ -649,14 +648,14 @@ function operationCallback(socket, operation) { var userId = null; // save authors if (socket.request.user && socket.request.user.logged_in) { - var socketId = socket.id; - var user = users[socketId]; + var user = users[socket.id]; + if (!user) return; userId = socket.request.user.id; if (!note.authors[userId]) { models.Author.create({ noteId: noteId, userId: userId, - color: users[socketId].color + color: user.color }).then(function (author) { note.authors[author.userId] = { userid: author.userId, @@ -743,11 +742,11 @@ function connection(socket) { //received user status socket.on('user status', function (data) { var noteId = socket.noteId; - if (!noteId || !notes[noteId]) return; + var user = users[socket.id]; + if (!noteId || !notes[noteId] || !user) return; if (config.debug) logger.info('SERVER received [' + noteId + '] user status from [' + socket.id + ']: ' + JSON.stringify(data)); if (data) { - var user = users[socket.id]; user.idle = data.idle; user.type = data.type; } @@ -763,6 +762,7 @@ function connection(socket) { var note = notes[noteId]; //Only owner can change permission if (note.owner && note.owner == socket.request.user.id) { + if (permission == 'freely' && !config.allowanonymous) return; note.permission = permission; models.Note.update({ permission: permission @@ -839,7 +839,9 @@ function connection(socket) { logger.info('user changed'); var noteId = socket.noteId; if (!noteId || !notes[noteId]) return; - updateUserData(socket, notes[noteId].users[socket.id]); + var user = notes[noteId].users[socket.id]; + if (!user) return; + updateUserData(socket, user); emitOnlineUsers(socket); }); @@ -856,7 +858,6 @@ function connection(socket) { var out = { users: users }; - out = LZString.compressToUTF16(JSON.stringify(out)); socket.emit('online users', out); }); @@ -871,26 +872,29 @@ function connection(socket) { //received cursor focus socket.on('cursor focus', function (data) { var noteId = socket.noteId; - if (!noteId || !notes[noteId]) return; - users[socket.id].cursor = data; - var out = buildUserOutData(users[socket.id]); + var user = users[socket.id]; + if (!noteId || !notes[noteId] || !user) return; + user.cursor = data; + var out = buildUserOutData(user); socket.broadcast.to(noteId).emit('cursor focus', out); }); //received cursor activity socket.on('cursor activity', function (data) { var noteId = socket.noteId; - if (!noteId || !notes[noteId]) return; - users[socket.id].cursor = data; - var out = buildUserOutData(users[socket.id]); + var user = users[socket.id]; + if (!noteId || !notes[noteId] || !user) return; + user.cursor = data; + var out = buildUserOutData(user); socket.broadcast.to(noteId).emit('cursor activity', out); }); //received cursor blur socket.on('cursor blur', function () { var noteId = socket.noteId; - if (!noteId || !notes[noteId]) return; - users[socket.id].cursor = null; + var user = users[socket.id]; + if (!noteId || !notes[noteId] || !user) return; + user.cursor = null; var out = { id: socket.id }; @@ -905,4 +909,4 @@ function connection(socket) { }); } -module.exports = realtime;
\ No newline at end of file +module.exports = realtime; diff --git a/lib/response.js b/lib/response.js index f0f49181..cedee3de 100755 --- a/lib/response.js +++ b/lib/response.js @@ -6,7 +6,6 @@ var markdownpdf = require("markdown-pdf"); var LZString = require('lz-string'); var S = require('string'); var shortId = require('shortid'); -var metaMarked = require('meta-marked'); var querystring = require('querystring'); var request = require('request'); var moment = require('moment'); @@ -60,6 +59,7 @@ function showIndex(req, res, next) { res.render(config.indexpath, { url: config.serverurl, useCDN: config.usecdn, + allowAnonymous: config.allowanonymous, facebook: config.facebook, twitter: config.twitter, github: config.github, @@ -75,14 +75,9 @@ function showIndex(req, res, next) { } function responseHackMD(res, note) { - var body = LZString.decompressFromBase64(note.content); - var meta = null; - try { - meta = models.Note.parseMeta(metaMarked(body).meta); - } catch(err) { - //na - } - if (!meta) meta = {}; + var body = note.content; + var extracted = models.Note.extractMeta(body); + var meta = models.Note.parseMeta(extracted.meta); var title = models.Note.decodeTitle(note.title); title = models.Note.generateWebTitle(meta.title || title); res.set({ @@ -93,6 +88,7 @@ function responseHackMD(res, note) { url: config.serverurl, title: title, useCDN: config.usecdn, + allowAnonymous: config.allowanonymous, facebook: config.facebook, twitter: config.twitter, github: config.github, @@ -108,9 +104,12 @@ function newNote(req, res, next) { var owner = null; if (req.isAuthenticated()) { owner = req.user.id; + } else if (!config.allowanonymous) { + return response.errorForbidden(res); } models.Note.create({ - ownerId: owner + ownerId: owner, + alias: req.alias ? req.alias : null }).then(function (note) { return res.redirect(config.serverurl + "/" + LZString.compressToBase64(note.id)); }).catch(function (err) { @@ -131,6 +130,7 @@ function checkViewPermission(req, note) { } function findNote(req, res, callback, include) { + var noteId = req.params.noteId; var id = req.params.noteId || req.params.shortid; models.Note.parseNoteId(id, function (err, _id) { models.Note.findOne({ @@ -140,7 +140,12 @@ function findNote(req, res, callback, include) { include: include || null }).then(function (note) { if (!note) { - return response.errorNotFound(res); + if (config.allowfreeurl && noteId) { + req.alias = noteId; + return newNote(req, res); + } else { + return response.errorNotFound(res); + } } if (!checkViewPermission(req, note)) { return response.errorForbidden(res); @@ -182,17 +187,10 @@ function showPublishNote(req, res, next) { if (!note) { return response.errorNotFound(res); } - var body = LZString.decompressFromBase64(note.content); - var meta = null; - var markdown = null; - try { - var obj = metaMarked(body); - markdown = obj.markdown; - meta = models.Note.parseMeta(obj.meta); - } catch(err) { - //na - } - if (!meta) meta = {}; + var body = note.content; + var extracted = models.Note.extractMeta(body); + markdown = extracted.markdown; + meta = models.Note.parseMeta(extracted.meta); var createtime = note.createdAt; var updatetime = note.lastchangeAt; var title = models.Note.decodeTitle(note.title); @@ -200,7 +198,7 @@ function showPublishNote(req, res, next) { var origin = config.serverurl; var data = { title: title, - description: meta.description || markdown ? models.Note.generateDescription(markdown) : null, + description: meta.description || (markdown ? models.Note.generateDescription(markdown) : null), viewcount: note.viewcount, createtime: createtime, updatetime: updatetime, @@ -239,7 +237,7 @@ function actionSlide(req, res, note) { } function actionDownload(req, res, note) { - var body = LZString.decompressFromBase64(note.content); + var body = note.content; var title = models.Note.decodeTitle(note.title); var filename = title; filename = encodeURIComponent(filename); @@ -256,23 +254,16 @@ function actionDownload(req, res, note) { } function actionInfo(req, res, note) { - var body = LZString.decompressFromBase64(note.content); - var meta = null; - var markdown = null; - try { - var obj = metaMarked(body); - markdown = obj.markdown; - meta = models.Note.parseMeta(obj.meta); - } catch(err) { - //na - } - if (!meta) meta = {}; + var body = note.content; + var extracted = models.Note.extractMeta(body); + var markdown = extracted.markdown; + var meta = models.Note.parseMeta(extracted.meta); var createtime = note.createdAt; var updatetime = note.lastchangeAt; var title = models.Note.decodeTitle(note.title); var data = { title: meta.title || title, - description: meta.description || markdown ? models.Note.generateDescription(markdown) : null, + description: meta.description || (markdown ? models.Note.generateDescription(markdown) : null), viewcount: note.viewcount, createtime: createtime, updatetime: updatetime @@ -288,19 +279,15 @@ function actionInfo(req, res, note) { } function actionPDF(req, res, note) { - var body = LZString.decompressFromBase64(note.content); - try { - body = metaMarked(body).markdown; - } catch(err) { - //na - } + var body = note.content; + var extracted = models.Note.extractMeta(body); var title = models.Note.decodeTitle(note.title); if (!fs.existsSync(config.tmppath)) { fs.mkdirSync(config.tmppath); } var path = config.tmppath + '/' + Date.now() + '.pdf'; - markdownpdf().from.string(body).to(path, function () { + markdownpdf().from.string(extracted.markdown).to(path, function () { var stream = fs.createReadStream(path); var filename = title; // Be careful of special characters @@ -470,7 +457,7 @@ function githubActionGist(req, res, note) { if (!error && httpResponse.statusCode == 200) { var access_token = body.access_token; if (access_token) { - var content = LZString.decompressFromBase64(note.content); + var content = note.content; var title = models.Note.decodeTitle(note.title); var filename = title.replace('/', ' ') + '.md'; var gist = { @@ -570,17 +557,10 @@ function showPublishSlide(req, res, next) { if (!note) { return response.errorNotFound(res); } - var body = LZString.decompressFromBase64(note.content); - var meta = null; - var markdown = null; - try { - var obj = metaMarked(body); - markdown = obj.markdown; - meta = models.Note.parseMeta(obj.meta); - } catch(err) { - //na - } - if (!meta) meta = {}; + var body = note.content; + var extracted = models.Note.extractMeta(body); + markdown = extracted.markdown; + meta = models.Note.parseMeta(extracted.meta); var createtime = note.createdAt; var updatetime = note.lastchangeAt; var title = models.Note.decodeTitle(note.title); @@ -588,13 +568,13 @@ function showPublishSlide(req, res, next) { var origin = config.serverurl; var data = { title: title, - description: meta.description || markdown ? models.Note.generateDescription(markdown) : null, + description: meta.description || (markdown ? models.Note.generateDescription(markdown) : null), viewcount: note.viewcount, createtime: createtime, updatetime: updatetime, url: origin, body: markdown, - meta: JSON.stringify(obj.meta || {}), + meta: JSON.stringify(extracted.meta), useCDN: config.usecdn, owner: note.owner ? note.owner.id : null, ownerprofile: note.owner ? models.User.getProfile(note.owner) : null, diff --git a/lib/workers/dmpWorker.js b/lib/workers/dmpWorker.js index fae36191..8e69636e 100644 --- a/lib/workers/dmpWorker.js +++ b/lib/workers/dmpWorker.js @@ -1,5 +1,4 @@ // external modules -var LZString = require('lz-string'); var DiffMatchPatch = require('diff-match-patch'); var dmp = new DiffMatchPatch(); @@ -58,7 +57,6 @@ process.on('message', function(data) { function createPatch(lastDoc, currDoc) { var ms_start = (new Date()).getTime(); var diff = dmp.diff_main(lastDoc, currDoc); - dmp.diff_cleanupSemantic(diff); var patch = dmp.patch_make(lastDoc, diff); patch = dmp.patch_toText(patch); var ms_end = (new Date()).getTime(); @@ -80,10 +78,10 @@ function getRevision(revisions, count) { for (var i = 0; i < count; i++) { var revision = revisions[i]; if (i == 0) { - startContent = LZString.decompressFromBase64(revision.content || revision.lastContent); + startContent = revision.content || revision.lastContent; } if (i != count - 1) { - var patch = dmp.patch_fromText(LZString.decompressFromBase64(revision.patch)); + var patch = dmp.patch_fromText(revision.patch); applyPatches = applyPatches.concat(patch); } lastPatch = revision.patch; @@ -105,11 +103,11 @@ function getRevision(revisions, count) { for (var i = l; i >= count - 1; i--) { var revision = revisions[i]; if (i == l) { - startContent = LZString.decompressFromBase64(revision.lastContent); + startContent = revision.lastContent; authorship = revision.authorship; } if (revision.patch) { - var patch = dmp.patch_fromText(LZString.decompressFromBase64(revision.patch)); + var patch = dmp.patch_fromText(revision.patch); applyPatches = applyPatches.concat(patch); } lastPatch = revision.patch; @@ -123,8 +121,8 @@ function getRevision(revisions, count) { } var data = { content: finalContent, - patch: dmp.patch_fromText(LZString.decompressFromBase64(lastPatch)), - authorship: authorship ? JSON.parse(LZString.decompressFromBase64(authorship)) : null + patch: dmp.patch_fromText(lastPatch), + authorship: authorship }; var ms_end = (new Date()).getTime(); if (config.debug) { |