diff options
-rw-r--r-- | lib/app.js | 12 | ||||
-rw-r--r-- | lib/serve.js | 53 |
2 files changed, 50 insertions, 15 deletions
@@ -1572,7 +1572,6 @@ App.prototype.saveDraft = function (id, url, form, content, cb) { mkdirp.sync(self.draftsDir) self.madeDraftsDir = true } - if (/[\/:\\]/.test(id)) return cb(new Error('draft id cannot contain path seperators')) var draft = { url: url, form: form, @@ -1587,6 +1586,7 @@ App.prototype.getDraft = function (id, cb) { var self = this var filename = path.join(self.draftsDir, id) fs.readFile(filename, 'utf8', function (err, data) { + if (err && err.code === 'EISDIR') return cb(null, {id: id, isDir: true}) if (err) return cb(err) var draft try { draft = JSON.parse(data) } @@ -1621,19 +1621,21 @@ function statAll(files, dir, cb) { ) } -App.prototype.listDrafts = function () { +App.prototype.listDrafts = function (dir) { var self = this + var draftsDir = dir ? path.join(self.draftsDir, dir) : self.draftsDir return u.readNext(function (cb) { - fs.readdir(self.draftsDir, function (err, files) { + fs.readdir(draftsDir, function (err, files) { if (err && err.code === 'ENOENT') return cb(null, pull.empty()) if (err) return cb(err) - statAll(files, self.draftsDir, function (err, stats) { + statAll(files, draftsDir, function (err, stats) { if (err) return cb(err) stats.sort(compareMtime) cb(null, pull( pull.values(stats), paramap(function (stat, cb) { - self.getDraft(stat.name, cb) + var name = dir ? path.join(dir, stat.name) : stat.name + self.getDraft(name, cb) }, 4) )) }) diff --git a/lib/serve.js b/lib/serve.js index c7065bc..397a148 100644 --- a/lib/serve.js +++ b/lib/serve.js @@ -1781,7 +1781,7 @@ Serve.prototype.block = function (path) { function renderDraftLink(draftId) { return pull.values([ - ph('a', {href: self.app.render.toUrl('/drafts/' + encodeURIComponent(draftId)), + ph('a', {href: self.app.render.toUrl('/drafts/' + encodeURI(draftId)), title: 'draft link'}, u.escapeHTML(draftId)), ph('input', {type: 'hidden', name: 'draft_id', value: u.escapeHTML(draftId)}), ' ', ]) @@ -4364,7 +4364,7 @@ Serve.prototype.composer = function (opts, cb) { var draftLinkContainer function renderDraftLink(draftId) { if (!draftId) return [] - var draftHref = self.app.render.toUrl('/drafts/' + encodeURIComponent(draftId)) + var draftHref = self.app.render.toUrl('/drafts/' + encodeURI(draftId)) return [ h('a', {href: draftHref, title: 'draft link'}, u.escapeHTML(draftId)), h('input', {type: 'hidden', name: 'draft_id', value: u.escapeHTML(draftId)}) @@ -4834,7 +4834,7 @@ Serve.prototype.phMsgActions = function (content) { function renderDraftLink(draftId) { return pull.values([ - ph('a', {href: self.app.render.toUrl('/drafts/' + encodeURIComponent(draftId)), + ph('a', {href: self.app.render.toUrl('/drafts/' + encodeURI(draftId)), title: 'draft link'}, u.escapeHTML(draftId)), ph('input', {type: 'hidden', name: 'draft_id', value: u.escapeHTML(draftId)}), ' ', ]) @@ -5135,18 +5135,37 @@ function hiddenInput(key, value) { }) : ph('input', {type: 'hidden', name: key, value: u.escapeHTML(value)}) } -Serve.prototype.drafts = function (path) { +Serve.prototype.drafts = function (filepath) { var self = this - var id = path && String(path).substr(1) + var id = filepath && String(filepath).substr(1) if (id) try { id = decodeURIComponent(id) } catch(e) {} + var dir + if (id) try { + var draftFile = path.join(self.app.draftsDir, id) + var stat = fs.statSync(draftFile) + if (stat.isDirectory()) { + dir = id + id = null + } + } catch(e) { + return this.respond(404, 'Not found') + } if (id) { + var idHref = '/drafts' return pull( ph('section', [ ph('h3', [ - ph('a', {href: self.app.render.toUrl('/drafts')}, 'Drafts'), ': ', - ph('a', {href: ''}, u.escapeHTML(id)) + ph('a', {href: self.app.render.toUrl('/drafts')}, 'Drafts'), + id.split(/\/+/).map(function (part, i) { + idHref += '/' + part + var href = self.app.render.toUrl(idHref) + return [ + ': ', + ph('a', {href: href}, u.escapeHTML(part)) + ] + }) ]), u.readNext(function (cb) { if (self.data.draft_discard) { @@ -5187,11 +5206,22 @@ Serve.prototype.drafts = function (path) { ) } + var render = self.app.render + var idHref = '/drafts' return pull( ph('section', [ - ph('h3', 'Drafts'), + ph('h3', [ + ph('a', {href: render.toUrl('/drafts')}, 'Drafts'), + dir ? dir.split(/\/+/).map(function (part, i) { + idHref += '/' + part + return [ + ': ', + ph('a', {href: render.toUrl(idHref)}, u.escapeHTML(part)) + ] + }) : '' + ]), ph('ul', pull( - self.app.listDrafts(), + self.app.listDrafts(dir), pull.asyncMap(function (draft, cb) { var form = draft.form || {} var msg = { @@ -5199,7 +5229,10 @@ Serve.prototype.drafts = function (path) { value: { author: self.app.sbot.id, timestamp: Date.now(), - content: draft.content || {type: 'post'} + content: draft.content || ( + draft.isDir ? {type: draft.id + '/'} + : {type: 'post'} + ) } } cb(null, ph('li', self.app.render.phMsgLink(msg))) |