diff --git a/src/public/stylesheets/share.css b/src/public/stylesheets/share.css index 22d2ce1c0..8dfedce57 100644 --- a/src/public/stylesheets/share.css +++ b/src/public/stylesheets/share.css @@ -1,8 +1,3 @@ -#title { - margin: 0; - padding-bottom: 0; -} - #layout { max-width: 1200px; margin: 0 auto; @@ -32,10 +27,24 @@ background-color:#eee; } -#title, #content { +#title { + margin: 0; + padding: 20px 20px 0 20px; +} + +#content { padding: 20px; } +.type-image img { + max-width: 100%; +} + +pre { + white-space: pre-wrap; + word-wrap: anywhere; +} + #menuLink { position: fixed; display: block; diff --git a/src/share/routes.js b/src/share/routes.js index 7ac3c5bb7..e1db87f33 100644 --- a/src/share/routes.js +++ b/src/share/routes.js @@ -1,7 +1,6 @@ const shaca = require("./shaca/shaca"); const shacaLoader = require("./shaca/shaca_loader"); const shareRoot = require("./share_root"); -const utils = require("../services/utils"); const {JSDOM} = require("jsdom"); function getSubRoot(note) { @@ -47,16 +46,27 @@ function getContent(note) { let content = note.getContent(); if (note.type === 'text') { - const isEmpty = !content?.trim() || (function() { - const document = new JSDOM(content).window.document; + const document = new JSDOM(content || "").window.document; - return document.body.textContent.trim().length === 0 + const isEmpty = document.body.textContent.trim().length === 0 && document.querySelectorAll("img").length === 0; - })(); if (isEmpty) { content = NO_CONTENT + getChildrenList(note); } + else { + for (const linkEl of document.querySelectorAll("a")) { + const href = linkEl.getAttribute("href"); + + if (href?.startsWith("#")) { + const notePathSegments = href.split("/"); + + linkEl.setAttribute("href", notePathSegments[notePathSegments.length - 1]); + } + } + + content = document.body.innerHTML; + } } else if (note.type === 'code') { if (!content?.trim()) { @@ -66,11 +76,17 @@ function getContent(note) { const document = new JSDOM().window.document; const preEl = document.createElement('pre'); - preEl.innerText = content; + preEl.appendChild(document.createTextNode(content)); content = preEl.outerHTML; } } + else if (note.type === 'image') { + content = ``; + } + else if (note.type === 'file') { + content = ``; + } else if (note.type === 'book') { content = getChildrenList(note); } @@ -78,7 +94,7 @@ function getContent(note) { content = '

This note type cannot be displayed.

' + getChildrenList(note); } - return content; + return `
${content}`; } function register(router) { @@ -119,6 +135,26 @@ function register(router) { res.send(image.getContent()); }); + + router.get('/share/api/notes/:noteId/:download', (req, res, next) => { + const {noteId} = req.params; + const note = shaca.getNote(noteId); + + if (!note) { + return res.status(404).send(`Note ${noteId} doesn't exist.`); + } + + const utils = require("../services/utils"); + + const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); + + res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); + + res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + res.setHeader('Content-Type', note.mime); + + res.send(note.getContent()); + }); } module.exports = { diff --git a/src/share/shaca/entities/branch.js b/src/share/shaca/entities/branch.js index bf4ed2070..47067410d 100644 --- a/src/share/shaca/entities/branch.js +++ b/src/share/shaca/entities/branch.js @@ -4,7 +4,7 @@ const AbstractEntity = require('./abstract_entity'); const shareRoot = require("../../share_root"); class Branch extends AbstractEntity { - constructor([branchId, noteId, parentNoteId, prefix, notePosition, isExpanded]) { + constructor([branchId, noteId, parentNoteId, prefix, isExpanded]) { super(); /** @param {string} */ @@ -15,8 +15,6 @@ class Branch extends AbstractEntity { this.parentNoteId = parentNoteId; /** @param {string} */ this.prefix = prefix; - /** @param {int} */ - this.notePosition = notePosition; /** @param {boolean} */ this.isExpanded = !!isExpanded; @@ -35,10 +33,6 @@ class Branch extends AbstractEntity { childNote.parentBranches.push(this); } - if (!parentNote) { - console.log(this); - } - if (!parentNote.children.includes(childNote)) { parentNote.children.push(childNote); } diff --git a/src/share/shaca/entities/note.js b/src/share/shaca/entities/note.js index 91268dcee..46cfdedc1 100644 --- a/src/share/shaca/entities/note.js +++ b/src/share/shaca/entities/note.js @@ -8,7 +8,7 @@ const LABEL = 'label'; const RELATION = 'relation'; class Note extends AbstractEntity { - constructor([noteId, title, type, mime]) { + constructor([noteId, title, type, mime, utcDateModified]) { super(); /** @param {string} */ @@ -19,6 +19,8 @@ class Note extends AbstractEntity { this.type = type; /** @param {string} */ this.mime = mime; + /** @param {string} */ + this.utcDateModified = utcDateModified; // used for caching of images /** @param {Branch[]} */ this.parentBranches = []; @@ -438,16 +440,6 @@ class Note extends AbstractEntity { return !!this.ownedAttributes.find(attr => attr.type === 'label' && attr.name === 'archived' && attr.isInheritable); } - // will sort the parents so that non-search & non-archived are first and archived at the end - // this is done so that non-search & non-archived paths are always explored as first when looking for note path - resortParents() { - this.parentBranches.sort((a, b) => - a.branchId.startsWith('virt-') - || a.parentNote.hasInheritableOwnedArchivedLabel() ? 1 : -1); - - this.parents = this.parentBranches.map(branch => branch.parentNote); - } - isTemplate() { return !!this.targetRelations.find(rel => rel.name === 'template'); } diff --git a/src/share/shaca/shaca_loader.js b/src/share/shaca/shaca_loader.js index 8cbb91abb..0cc5819a1 100644 --- a/src/share/shaca/shaca_loader.js +++ b/src/share/shaca/shaca_loader.js @@ -33,11 +33,11 @@ function load() { const noteIdStr = noteIds.map(noteId => `'${noteId}'`).join(","); - for (const row of sql.getRawRows(`SELECT noteId, title, type, mime FROM notes WHERE isDeleted = 0 AND noteId IN (${noteIdStr})`)) { + for (const row of sql.getRawRows(`SELECT noteId, title, type, mime, utcDateModified FROM notes WHERE isDeleted = 0 AND noteId IN (${noteIdStr})`)) { new Note(row); } - for (const row of sql.getRawRows(`SELECT branchId, noteId, parentNoteId, prefix, notePosition, isExpanded, utcDateModified FROM branches WHERE isDeleted = 0 AND noteId IN (${noteIdStr})`)) { + for (const row of sql.getRawRows(`SELECT branchId, noteId, parentNoteId, prefix, isExpanded, utcDateModified FROM branches WHERE isDeleted = 0 AND noteId IN (${noteIdStr}) ORDER BY notePosition`)) { new Branch(row); }