2022-04-11 21:38:05 +02:00
|
|
|
const excalidrawToSvg = require("excalidraw-to-svg");
|
|
|
|
|
2021-10-17 14:44:59 +02:00
|
|
|
const shaca = require("./shaca/shaca");
|
|
|
|
const shacaLoader = require("./shaca/shaca_loader");
|
2021-10-19 22:48:38 +02:00
|
|
|
const shareRoot = require("./share_root");
|
2022-01-10 17:09:20 +01:00
|
|
|
const contentRenderer = require("./content_renderer");
|
2021-10-19 22:48:38 +02:00
|
|
|
|
2021-12-23 20:54:48 +01:00
|
|
|
function getSharedSubTreeRoot(note) {
|
2021-10-19 22:48:38 +02:00
|
|
|
if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
2021-12-23 20:54:48 +01:00
|
|
|
// share root itself is not shared
|
2021-10-19 22:48:38 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-12-23 20:54:48 +01:00
|
|
|
// every path leads to share root, but which one to choose?
|
|
|
|
// for sake of simplicity URLs are not note paths
|
2021-10-19 22:48:38 +02:00
|
|
|
const parentNote = note.getParentNotes()[0];
|
|
|
|
|
|
|
|
if (parentNote.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
|
|
|
return note;
|
|
|
|
}
|
|
|
|
|
2021-12-23 20:54:48 +01:00
|
|
|
return getSharedSubTreeRoot(parentNote);
|
2021-10-19 22:48:38 +02:00
|
|
|
}
|
2021-10-17 14:44:59 +02:00
|
|
|
|
2022-03-22 23:17:47 +01:00
|
|
|
function addNoIndexHeader(note, res) {
|
|
|
|
if (note.hasLabel('shareDisallowRobotIndexing')) {
|
|
|
|
res.setHeader('X-Robots-Tag', 'noindex');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-17 14:44:59 +02:00
|
|
|
function register(router) {
|
2022-01-17 23:13:56 +01:00
|
|
|
function renderNote(note, res) {
|
2022-03-22 23:17:47 +01:00
|
|
|
if (!note) {
|
2021-12-22 09:10:38 +01:00
|
|
|
res.status(404).render("share/404");
|
2022-03-22 23:17:47 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
addNoIndexHeader(note, res);
|
|
|
|
|
|
|
|
if (note.hasLabel('shareRaw') || ['image', 'file'].includes(note.type)) {
|
|
|
|
res.setHeader('Content-Type', note.mime);
|
|
|
|
|
|
|
|
res.send(note.getContent());
|
|
|
|
return;
|
2021-10-17 14:44:59 +02:00
|
|
|
}
|
2022-03-22 23:17:47 +01:00
|
|
|
|
|
|
|
const {header, content, isEmpty} = contentRenderer.getContent(note);
|
|
|
|
|
|
|
|
const subRoot = getSharedSubTreeRoot(note);
|
|
|
|
|
|
|
|
res.render("share/page", {
|
|
|
|
note,
|
|
|
|
header,
|
|
|
|
content,
|
|
|
|
isEmpty,
|
|
|
|
subRoot
|
|
|
|
});
|
2022-01-17 23:13:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
router.get(['/share', '/share/'], (req, res, next) => {
|
|
|
|
shacaLoader.ensureLoad();
|
|
|
|
|
|
|
|
renderNote(shaca.shareRootNote, res);
|
|
|
|
});
|
|
|
|
|
|
|
|
router.get('/share/:shareId', (req, res, next) => {
|
|
|
|
const {shareId} = req.params;
|
|
|
|
|
|
|
|
shacaLoader.ensureLoad();
|
|
|
|
|
|
|
|
const note = shaca.aliasToNote[shareId] || shaca.notes[shareId];
|
|
|
|
|
|
|
|
renderNote(note, res);
|
2021-10-17 14:44:59 +02:00
|
|
|
});
|
2021-10-19 22:48:38 +02:00
|
|
|
|
2022-01-01 13:23:09 +01:00
|
|
|
router.get('/share/api/notes/:noteId', (req, res, next) => {
|
|
|
|
const {noteId} = req.params;
|
|
|
|
const note = shaca.getNote(noteId);
|
2021-10-19 22:48:38 +02:00
|
|
|
|
2022-01-01 13:23:09 +01:00
|
|
|
if (!note) {
|
|
|
|
return res.status(404).send(`Note ${noteId} not found`);
|
2021-10-19 22:48:38 +02:00
|
|
|
}
|
|
|
|
|
2022-03-22 23:17:47 +01:00
|
|
|
addNoIndexHeader(note, res);
|
|
|
|
|
2022-01-01 13:23:09 +01:00
|
|
|
res.json(note.getPojoWithAttributes());
|
2021-10-19 22:48:38 +02:00
|
|
|
});
|
2021-12-06 22:53:17 +01:00
|
|
|
|
2021-12-22 09:36:38 +01:00
|
|
|
router.get('/share/api/notes/:noteId/download', (req, res, next) => {
|
2021-12-06 22:53:17 +01:00
|
|
|
const {noteId} = req.params;
|
|
|
|
const note = shaca.getNote(noteId);
|
|
|
|
|
|
|
|
if (!note) {
|
2022-01-01 13:23:09 +01:00
|
|
|
return res.status(404).send(`Note ${noteId} not found`);
|
2021-12-06 22:53:17 +01:00
|
|
|
}
|
|
|
|
|
2022-03-22 23:17:47 +01:00
|
|
|
addNoIndexHeader(note, res);
|
|
|
|
|
2021-12-06 22:53:17 +01:00
|
|
|
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());
|
|
|
|
});
|
2021-12-27 20:48:14 +01:00
|
|
|
|
2022-04-11 21:50:10 +02:00
|
|
|
router.get(['/share/api/images/:noteId/:filename', '/share/api/images/:noteId'], (req, res, next) => {
|
2022-01-01 13:23:09 +01:00
|
|
|
const image = shaca.getNote(req.params.noteId);
|
|
|
|
|
|
|
|
if (!image) {
|
|
|
|
return res.status(404).send(`Note ${noteId} not found`);
|
|
|
|
}
|
2022-04-11 21:38:05 +02:00
|
|
|
else if (!["image", "canvas-note"].includes(image.type)) {
|
|
|
|
return res.status(400).send("Requested note is not a shareable image");
|
|
|
|
} else if (image.type === "canvas-note") {
|
|
|
|
/**
|
|
|
|
* FIXME: deduplicate the code from api/image.js
|
|
|
|
*/
|
|
|
|
// render the svg in node.js using excalidraw and jsdom
|
|
|
|
const content = image.getContent();
|
|
|
|
try {
|
|
|
|
const data = JSON.parse(content)
|
|
|
|
const excalidrawData = {
|
|
|
|
type: "excalidraw",
|
|
|
|
version: 2,
|
|
|
|
source: "trilium",
|
|
|
|
elements: data.elements,
|
|
|
|
appState: data.appState,
|
|
|
|
files: data.files,
|
|
|
|
}
|
|
|
|
excalidrawToSvg(excalidrawData)
|
|
|
|
.then(svg => {
|
|
|
|
const svgHtml = svg.outerHTML;
|
|
|
|
res.set('Content-Type', "image/svg+xml");
|
|
|
|
res.set("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
|
|
res.send(svgHtml);
|
|
|
|
});
|
|
|
|
} catch(err) {
|
|
|
|
res.status(500).send("there was an error parsing excalidraw to svg");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// normal image
|
|
|
|
res.set('Content-Type', image.mime);
|
|
|
|
|
|
|
|
res.send(image.getContent());
|
2022-01-01 13:23:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
// used for PDF viewing
|
2021-12-24 21:36:31 +00:00
|
|
|
router.get('/share/api/notes/:noteId/view', (req, res, next) => {
|
|
|
|
const {noteId} = req.params;
|
|
|
|
const note = shaca.getNote(noteId);
|
|
|
|
|
|
|
|
if (!note) {
|
2022-01-01 13:23:09 +01:00
|
|
|
return res.status(404).send(`Note ${noteId} not found`);
|
2021-12-24 21:36:31 +00:00
|
|
|
}
|
|
|
|
|
2022-03-22 23:17:47 +01:00
|
|
|
addNoIndexHeader(note, res);
|
|
|
|
|
2021-12-24 21:36:31 +00:00
|
|
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
|
|
res.setHeader('Content-Type', note.mime);
|
|
|
|
|
|
|
|
res.send(note.getContent());
|
|
|
|
});
|
2021-10-17 14:44:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
register
|
|
|
|
}
|