mirror of
https://github.com/TriliumNext/Notes.git
synced 2026-05-04 19:29:52 -05:00
chore(prettier): fix all files
This commit is contained in:
@@ -14,32 +14,32 @@ interface Result {
|
||||
function getContent(note: SNote) {
|
||||
if (note.isProtected) {
|
||||
return {
|
||||
header: '',
|
||||
content: '<p>Protected note cannot be displayed</p>',
|
||||
header: "",
|
||||
content: "<p>Protected note cannot be displayed</p>",
|
||||
isEmpty: false
|
||||
};
|
||||
}
|
||||
|
||||
const result: Result = {
|
||||
content: note.getContent(),
|
||||
header: '',
|
||||
header: "",
|
||||
isEmpty: false
|
||||
};
|
||||
|
||||
if (note.type === 'text') {
|
||||
if (note.type === "text") {
|
||||
renderText(result, note);
|
||||
} else if (note.type === 'code') {
|
||||
} else if (note.type === "code") {
|
||||
renderCode(result);
|
||||
} else if (note.type === 'mermaid') {
|
||||
} else if (note.type === "mermaid") {
|
||||
renderMermaid(result, note);
|
||||
} else if ([ "image", "canvas", "mindMap"].includes(note.type)) {
|
||||
} else if (["image", "canvas", "mindMap"].includes(note.type)) {
|
||||
renderImage(result, note);
|
||||
} else if (note.type === 'file') {
|
||||
} else if (note.type === "file") {
|
||||
renderFile(note, result);
|
||||
} else if (note.type === 'book') {
|
||||
} else if (note.type === "book") {
|
||||
result.isEmpty = true;
|
||||
} else {
|
||||
result.content = '<p>This note type cannot be displayed.</p>';
|
||||
result.content = "<p>This note type cannot be displayed.</p>";
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -57,14 +57,13 @@ function renderIndex(result: Result) {
|
||||
result.content += `<li><a class="${childNote.type}" href="${href}" ${target}>${childNote.escapedTitle}</a></li>`;
|
||||
}
|
||||
|
||||
result.content += '</ul>';
|
||||
result.content += "</ul>";
|
||||
}
|
||||
|
||||
function renderText(result: Result, note: SNote) {
|
||||
const document = new JSDOM(result.content || "").window.document;
|
||||
|
||||
result.isEmpty = document.body.textContent?.trim().length === 0
|
||||
&& document.querySelectorAll("img").length === 0;
|
||||
result.isEmpty = document.body.textContent?.trim().length === 0 && document.querySelectorAll("img").length === 0;
|
||||
|
||||
if (!result.isEmpty) {
|
||||
for (const linkEl of document.querySelectorAll("a")) {
|
||||
@@ -103,8 +102,8 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
function handleAttachmentLink(linkEl: HTMLAnchorElement, href: string) {
|
||||
const linkRegExp = /attachmentId=([a-zA-Z0-9_]+)/g;
|
||||
let attachmentMatch
|
||||
if (attachmentMatch = linkRegExp.exec(href)) {
|
||||
let attachmentMatch;
|
||||
if ((attachmentMatch = linkRegExp.exec(href))) {
|
||||
const attachmentId = attachmentMatch[1];
|
||||
const attachment = shaca.getAttachment(attachmentId);
|
||||
|
||||
@@ -117,7 +116,7 @@ function handleAttachmentLink(linkEl: HTMLAnchorElement, href: string) {
|
||||
linkEl.removeAttribute("href");
|
||||
}
|
||||
} else {
|
||||
const [notePath] = href.split('?');
|
||||
const [notePath] = href.split("?");
|
||||
const notePathSegments = notePath.split("/");
|
||||
const noteId = notePathSegments[notePathSegments.length - 1];
|
||||
const linkedNote = shaca.getNote(noteId);
|
||||
@@ -144,7 +143,7 @@ function renderCode(result: Result) {
|
||||
} else {
|
||||
const document = new JSDOM().window.document;
|
||||
|
||||
const preEl = document.createElement('pre');
|
||||
const preEl = document.createElement("pre");
|
||||
preEl.appendChild(document.createTextNode(result.content));
|
||||
|
||||
result.content = preEl.outerHTML;
|
||||
@@ -162,7 +161,7 @@ function renderMermaid(result: Result, note: SNote) {
|
||||
<details>
|
||||
<summary>Chart source</summary>
|
||||
<pre>${escapeHtml(result.content)}</pre>
|
||||
</details>`
|
||||
</details>`;
|
||||
}
|
||||
|
||||
function renderImage(result: Result, note: SNote) {
|
||||
@@ -170,8 +169,8 @@ function renderImage(result: Result, note: SNote) {
|
||||
}
|
||||
|
||||
function renderFile(note: SNote, result: Result) {
|
||||
if (note.mime === 'application/pdf') {
|
||||
result.content = `<iframe class="pdf-view" src="api/notes/${note.noteId}/view"></iframe>`
|
||||
if (note.mime === "application/pdf") {
|
||||
result.content = `<iframe class="pdf-view" src="api/notes/${note.noteId}/view"></iframe>`;
|
||||
} else {
|
||||
result.content = `<button type="button" onclick="location.href='api/notes/${note.noteId}/download'">Download file</button>`;
|
||||
}
|
||||
|
||||
+51
-61
@@ -38,22 +38,20 @@ function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
|
||||
}
|
||||
|
||||
function addNoIndexHeader(note: SNote, res: Response) {
|
||||
if (note.isLabelTruthy('shareDisallowRobotIndexing')) {
|
||||
res.setHeader('X-Robots-Tag', 'noindex');
|
||||
if (note.isLabelTruthy("shareDisallowRobotIndexing")) {
|
||||
res.setHeader("X-Robots-Tag", "noindex");
|
||||
}
|
||||
}
|
||||
|
||||
function requestCredentials(res: Response) {
|
||||
res.setHeader('WWW-Authenticate', 'Basic realm="User Visible Realm", charset="UTF-8"')
|
||||
.sendStatus(401);
|
||||
res.setHeader("WWW-Authenticate", 'Basic realm="User Visible Realm", charset="UTF-8"').sendStatus(401);
|
||||
}
|
||||
|
||||
function checkAttachmentAccess(attachmentId: string, req: Request, res: Response) {
|
||||
const attachment = shaca.getAttachment(attachmentId);
|
||||
|
||||
if (!attachment) {
|
||||
res.status(404)
|
||||
.json({ message: `Attachment '${attachmentId}' not found.` });
|
||||
res.status(404).json({ message: `Attachment '${attachmentId}' not found.` });
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -68,15 +66,13 @@ function checkNoteAccess(noteId: string, req: Request, res: Response) {
|
||||
const note = shaca.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
res.status(404)
|
||||
.json({ message: `Note '${noteId}' not found.` });
|
||||
res.status(404).json({ message: `Note '${noteId}' not found.` });
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (noteId === '_share' && !shaca.shareIndexEnabled) {
|
||||
res.status(403)
|
||||
.json({ message: `Accessing share index is forbidden.` });
|
||||
if (noteId === "_share" && !shaca.shareIndexEnabled) {
|
||||
res.status(403).json({ message: `Accessing share index is forbidden.` });
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -95,8 +91,8 @@ function checkNoteAccess(noteId: string, req: Request, res: Response) {
|
||||
}
|
||||
|
||||
const base64Str = header.substring("Basic ".length);
|
||||
const buffer = Buffer.from(base64Str, 'base64');
|
||||
const authString = buffer.toString('utf-8');
|
||||
const buffer = Buffer.from(base64Str, "base64");
|
||||
const authString = buffer.toString("utf-8");
|
||||
|
||||
for (const credentialLabel of credentials) {
|
||||
if (safeCompare(authString, credentialLabel.value)) {
|
||||
@@ -108,7 +104,7 @@ function checkNoteAccess(noteId: string, req: Request, res: Response) {
|
||||
}
|
||||
|
||||
function renderImageAttachment(image: SNote, res: Response, attachmentName: string) {
|
||||
let svgString = '<svg/>'
|
||||
let svgString = "<svg/>";
|
||||
const attachment = image.getAttachmentByTitle(attachmentName);
|
||||
if (!attachment) {
|
||||
res.status(404).render("share/404");
|
||||
@@ -126,8 +122,8 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri
|
||||
}
|
||||
}
|
||||
|
||||
const svg = svgString
|
||||
res.set('Content-Type', "image/svg+xml");
|
||||
const svg = svgString;
|
||||
res.set("Content-Type", "image/svg+xml");
|
||||
res.set("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.send(svg);
|
||||
}
|
||||
@@ -147,9 +143,8 @@ function register(router: Router) {
|
||||
|
||||
addNoIndexHeader(note, res);
|
||||
|
||||
if (note.isLabelTruthy('shareRaw')) {
|
||||
res.setHeader('Content-Type', note.mime)
|
||||
.send(note.getContent());
|
||||
if (note.isLabelTruthy("shareRaw")) {
|
||||
res.setHeader("Content-Type", note.mime).send(note.getContent());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -160,19 +155,18 @@ function register(router: Router) {
|
||||
let useDefaultView = true;
|
||||
|
||||
// Check if the user has their own template
|
||||
if (note.hasRelation('shareTemplate')) {
|
||||
if (note.hasRelation("shareTemplate")) {
|
||||
// Get the template note and content
|
||||
const templateId = note.getRelation('shareTemplate')?.value;
|
||||
const templateId = note.getRelation("shareTemplate")?.value;
|
||||
const templateNote = templateId && shaca.getNote(templateId);
|
||||
|
||||
// Make sure the note type is correct
|
||||
if (templateNote && templateNote.type === 'code' && templateNote.mime === 'application/x-ejs') {
|
||||
|
||||
if (templateNote && templateNote.type === "code" && templateNote.mime === "application/x-ejs") {
|
||||
// EJS caches the result of this so we don't need to pre-cache
|
||||
const includer = (path: string) => {
|
||||
const childNote = templateNote.children.find(n => path === n.title);
|
||||
const childNote = templateNote.children.find((n) => path === n.title);
|
||||
if (!childNote) throw new Error("Unable to find child note.");
|
||||
if (childNote.type !== 'code' || childNote.mime !== 'application/x-ejs') throw new Error("Incorrect child note type.");
|
||||
if (childNote.type !== "code" || childNote.mime !== "application/x-ejs") throw new Error("Incorrect child note type.");
|
||||
|
||||
const template = childNote.getContent();
|
||||
if (typeof template !== "string") throw new Error("Invalid template content type.");
|
||||
@@ -188,36 +182,34 @@ function register(router: Router) {
|
||||
res.send(ejsResult);
|
||||
useDefaultView = false; // Rendering went okay, don't use default view
|
||||
}
|
||||
}
|
||||
catch (e: any) {
|
||||
} catch (e: any) {
|
||||
log.error(`Rendering user provided share template (${templateId}) threw exception ${e.message} with stacktrace: ${e.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useDefaultView) {
|
||||
res.render('share/page', opts);
|
||||
res.render("share/page", opts);
|
||||
}
|
||||
}
|
||||
|
||||
router.get('/share/', (req, res, next) => {
|
||||
if (req.path.substr(-1) !== '/') {
|
||||
res.redirect('../share/');
|
||||
router.get("/share/", (req, res, next) => {
|
||||
if (req.path.substr(-1) !== "/") {
|
||||
res.redirect("../share/");
|
||||
return;
|
||||
}
|
||||
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
if (!shaca.shareRootNote) {
|
||||
res.status(404)
|
||||
.json({ message: "Share root note not found" });
|
||||
res.status(404).json({ message: "Share root note not found" });
|
||||
return;
|
||||
}
|
||||
|
||||
renderNote(shaca.shareRootNote, req, res);
|
||||
});
|
||||
|
||||
router.get('/share/:shareId', (req, res, next) => {
|
||||
router.get("/share/:shareId", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const { shareId } = req.params;
|
||||
@@ -227,7 +219,7 @@ function register(router: Router) {
|
||||
renderNote(note, req, res);
|
||||
});
|
||||
|
||||
router.get('/share/api/notes/:noteId', (req, res, next) => {
|
||||
router.get("/share/api/notes/:noteId", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
let note: SNote | boolean;
|
||||
|
||||
@@ -240,7 +232,7 @@ function register(router: Router) {
|
||||
res.json(note.getPojo());
|
||||
});
|
||||
|
||||
router.get('/share/api/notes/:noteId/download', (req, res, next) => {
|
||||
router.get("/share/api/notes/:noteId/download", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
let note: SNote | boolean;
|
||||
@@ -253,16 +245,16 @@ function register(router: Router) {
|
||||
|
||||
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
|
||||
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||
res.setHeader("Content-Disposition", utils.getContentDisposition(filename));
|
||||
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.setHeader('Content-Type', note.mime);
|
||||
res.setHeader("Content-Type", note.mime);
|
||||
|
||||
res.send(note.getContent());
|
||||
});
|
||||
|
||||
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
|
||||
router.get('/share/api/images/:noteId/:filename', (req, res, next) => {
|
||||
router.get("/share/api/images/:noteId/:filename", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
let image: SNote | boolean;
|
||||
@@ -271,25 +263,24 @@ function register(router: Router) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (image.type === 'image') {
|
||||
if (image.type === "image") {
|
||||
// normal image
|
||||
res.set('Content-Type', image.mime);
|
||||
res.set("Content-Type", image.mime);
|
||||
addNoIndexHeader(image, res);
|
||||
res.send(image.getContent());
|
||||
} else if (image.type === "canvas") {
|
||||
renderImageAttachment(image, res, 'canvas-export.svg');
|
||||
} else if (image.type === 'mermaid') {
|
||||
renderImageAttachment(image, res, 'mermaid-export.svg');
|
||||
renderImageAttachment(image, res, "canvas-export.svg");
|
||||
} else if (image.type === "mermaid") {
|
||||
renderImageAttachment(image, res, "mermaid-export.svg");
|
||||
} else if (image.type === "mindMap") {
|
||||
renderImageAttachment(image, res, 'mindmap-export.svg');
|
||||
renderImageAttachment(image, res, "mindmap-export.svg");
|
||||
} else {
|
||||
res.status(400)
|
||||
.json({ message: "Requested note is not a shareable image" });
|
||||
res.status(400).json({ message: "Requested note is not a shareable image" });
|
||||
}
|
||||
});
|
||||
|
||||
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
|
||||
router.get('/share/api/attachments/:attachmentId/image/:filename', (req, res, next) => {
|
||||
router.get("/share/api/attachments/:attachmentId/image/:filename", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
let attachment: SAttachment | boolean;
|
||||
@@ -299,16 +290,15 @@ function register(router: Router) {
|
||||
}
|
||||
|
||||
if (attachment.role === "image") {
|
||||
res.set('Content-Type', attachment.mime);
|
||||
res.set("Content-Type", attachment.mime);
|
||||
addNoIndexHeader(attachment.note, res);
|
||||
res.send(attachment.getContent());
|
||||
} else {
|
||||
res.status(400)
|
||||
.json({ message: "Requested attachment is not a shareable image" });
|
||||
res.status(400).json({ message: "Requested attachment is not a shareable image" });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/share/api/attachments/:attachmentId/download', (req, res, next) => {
|
||||
router.get("/share/api/attachments/:attachmentId/download", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
let attachment: SAttachment | boolean;
|
||||
@@ -321,16 +311,16 @@ function register(router: Router) {
|
||||
|
||||
const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime);
|
||||
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||
res.setHeader("Content-Disposition", utils.getContentDisposition(filename));
|
||||
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.setHeader('Content-Type', attachment.mime);
|
||||
res.setHeader("Content-Type", attachment.mime);
|
||||
|
||||
res.send(attachment.getContent());
|
||||
});
|
||||
|
||||
// used for PDF viewing
|
||||
router.get('/share/api/notes/:noteId/view', (req, res, next) => {
|
||||
router.get("/share/api/notes/:noteId/view", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
let note: SNote | boolean;
|
||||
@@ -342,13 +332,13 @@ function register(router: Router) {
|
||||
addNoIndexHeader(note, res);
|
||||
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
res.setHeader('Content-Type', note.mime);
|
||||
res.setHeader("Content-Type", note.mime);
|
||||
|
||||
res.send(note.getContent());
|
||||
});
|
||||
|
||||
// Used for searching, require noteId so we know the subTreeRoot
|
||||
router.get('/share/api/notes', (req, res, next) => {
|
||||
router.get("/share/api/notes", (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const ancestorNoteId = req.query.ancestorNoteId ?? "_share";
|
||||
@@ -373,11 +363,11 @@ function register(router: Router) {
|
||||
|
||||
const searchContext = new SearchContext({ ancestorNoteId: ancestorNoteId });
|
||||
const searchResults = searchService.findResultsWithQuery(search, searchContext);
|
||||
const filteredResults = searchResults.map(sr => {
|
||||
const filteredResults = searchResults.map((sr) => {
|
||||
const fullNote = shaca.notes[sr.noteId];
|
||||
const startIndex = sr.notePathArray.indexOf(ancestorNoteId);
|
||||
const localPathArray = sr.notePathArray.slice(startIndex + 1).filter(id => shaca.notes[id]);
|
||||
const pathTitle = localPathArray.map(id => shaca.notes[id].title).join(" / ");
|
||||
const localPathArray = sr.notePathArray.slice(startIndex + 1).filter((id) => shaca.notes[id]);
|
||||
const pathTitle = localPathArray.map((id) => shaca.notes[id].title).join(" / ");
|
||||
return { id: fullNote.shareId, title: fullNote.title, score: sr.score, path: pathTitle };
|
||||
});
|
||||
|
||||
@@ -387,4 +377,4 @@ function register(router: Router) {
|
||||
|
||||
export default {
|
||||
register
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type SNoteRow = [ string, string, string, string, string, string, boolean ];
|
||||
export type SBranchRow = [ string, string, string, string, string, boolean ];
|
||||
export type SAttributeRow = [ string, string, string, string, string, boolean, number ];
|
||||
export type SAttachmentRow = [ string, string, string, string, string, string, string ];
|
||||
export type SNoteRow = [string, string, string, string, string, string, boolean];
|
||||
export type SBranchRow = [string, string, string, string, string, boolean];
|
||||
export type SAttributeRow = [string, string, string, string, string, boolean, number];
|
||||
export type SAttachmentRow = [string, string, string, string, string, string, string];
|
||||
|
||||
@@ -4,8 +4,8 @@ import sql from "../../sql.js";
|
||||
import utils from "../../../services/utils.js";
|
||||
import AbstractShacaEntity from "./abstract_shaca_entity.js";
|
||||
import SNote from "./snote.js";
|
||||
import { Blob } from '../../../services/blob-interface.js';
|
||||
import { SAttachmentRow } from './rows.js';
|
||||
import { Blob } from "../../../services/blob-interface.js";
|
||||
import { SAttachmentRow } from "./rows.js";
|
||||
|
||||
class SAttachment extends AbstractShacaEntity {
|
||||
private attachmentId: string;
|
||||
@@ -42,8 +42,7 @@ class SAttachment extends AbstractShacaEntity {
|
||||
if (!row) {
|
||||
if (silentNotFoundError) {
|
||||
return undefined;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw new Error(`Cannot find blob for attachment '${this.attachmentId}', blob '${this.blobId}'`);
|
||||
}
|
||||
}
|
||||
@@ -51,11 +50,8 @@ class SAttachment extends AbstractShacaEntity {
|
||||
let content = row.content;
|
||||
|
||||
if (this.hasStringContent()) {
|
||||
return content === null
|
||||
? ""
|
||||
: content.toString("utf-8");
|
||||
}
|
||||
else {
|
||||
return content === null ? "" : content.toString("utf-8");
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { SAttributeRow } from "./rows.js";
|
||||
import SNote from "./snote.js";
|
||||
|
||||
class SAttribute extends AbstractShacaEntity {
|
||||
|
||||
attributeId: string;
|
||||
private noteId: string;
|
||||
type: string;
|
||||
@@ -34,8 +33,8 @@ class SAttribute extends AbstractShacaEntity {
|
||||
targetNote.targetRelations.push(this);
|
||||
}
|
||||
|
||||
if (this.type === 'relation' && this.name === 'imageLink') {
|
||||
const linkedChildNote = this.note.getChildNotes().find(childNote => childNote.noteId === this.value);
|
||||
if (this.type === "relation" && this.name === "imageLink") {
|
||||
const linkedChildNote = this.note.getChildNotes().find((childNote) => childNote.noteId === this.value);
|
||||
|
||||
if (linkedChildNote) {
|
||||
const branch = this.shaca.getBranchFromChildAndParent(linkedChildNote.noteId, this.noteId);
|
||||
@@ -44,30 +43,30 @@ class SAttribute extends AbstractShacaEntity {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.type === 'label' && this.name === 'shareAlias' && this.value.trim()) {
|
||||
if (this.type === "label" && this.name === "shareAlias" && this.value.trim()) {
|
||||
this.shaca.aliasToNote[this.value.trim()] = this.note;
|
||||
}
|
||||
|
||||
if (this.type === 'label' && this.name === 'shareRoot') {
|
||||
if (this.type === "label" && this.name === "shareRoot") {
|
||||
this.shaca.shareRootNote = this.note;
|
||||
}
|
||||
|
||||
if (this.type === 'label' && this.name === 'shareIndex') {
|
||||
if (this.type === "label" && this.name === "shareIndex") {
|
||||
this.shaca.shareIndexEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
get isAffectingSubtree() {
|
||||
return this.isInheritable
|
||||
|| (this.type === 'relation' && ['template', 'inherit'].includes(this.name));
|
||||
return this.isInheritable || (this.type === "relation" && ["template", "inherit"].includes(this.name));
|
||||
}
|
||||
|
||||
get targetNoteId() { // alias
|
||||
return this.type === 'relation' ? this.value : undefined;
|
||||
get targetNoteId() {
|
||||
// alias
|
||||
return this.type === "relation" ? this.value : undefined;
|
||||
}
|
||||
|
||||
isAutoLink() {
|
||||
return this.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink'].includes(this.name);
|
||||
return this.type === "relation" && ["internalLink", "imageLink", "relationMapLink", "includeNoteLink"].includes(this.name);
|
||||
}
|
||||
|
||||
get note(): SNote {
|
||||
@@ -75,7 +74,7 @@ class SAttribute extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
get targetNote(): SNote | null | undefined {
|
||||
if (this.type === 'relation') {
|
||||
if (this.type === "relation") {
|
||||
return this.shaca.notes[this.value];
|
||||
}
|
||||
}
|
||||
@@ -85,7 +84,7 @@ class SAttribute extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
getTargetNote(): SNote | null {
|
||||
if (this.type !== 'relation') {
|
||||
if (this.type !== "relation") {
|
||||
throw new Error(`Attribute '${this.attributeId}' is not relation`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
import AbstractShacaEntity from "./abstract_shaca_entity.js";
|
||||
import { SBranchRow } from './rows.js';
|
||||
import { SBranchRow } from "./rows.js";
|
||||
import SNote from "./snote.js";
|
||||
|
||||
class SBranch extends AbstractShacaEntity {
|
||||
|
||||
private branchId: string;
|
||||
private noteId: string;
|
||||
parentNoteId: string;
|
||||
|
||||
@@ -4,17 +4,17 @@ import sql from "../../sql.js";
|
||||
import utils from "../../../services/utils.js";
|
||||
import AbstractShacaEntity from "./abstract_shaca_entity.js";
|
||||
import escape from "escape-html";
|
||||
import { Blob } from '../../../services/blob-interface.js';
|
||||
import { Blob } from "../../../services/blob-interface.js";
|
||||
import SAttachment from "./sattachment.js";
|
||||
import SAttribute from "./sattribute.js";
|
||||
import SBranch from "./sbranch.js";
|
||||
import { SNoteRow } from './rows.js';
|
||||
import { SNoteRow } from "./rows.js";
|
||||
|
||||
const LABEL = 'label';
|
||||
const RELATION = 'relation';
|
||||
const CREDENTIALS = 'shareCredentials';
|
||||
const LABEL = "label";
|
||||
const RELATION = "relation";
|
||||
const CREDENTIALS = "shareCredentials";
|
||||
|
||||
const isCredentials = (attr: SAttribute) => attr.type === 'label' && attr.name === CREDENTIALS;
|
||||
const isCredentials = (attr: SAttribute) => attr.type === "label" && attr.name === CREDENTIALS;
|
||||
|
||||
class SNote extends AbstractShacaEntity {
|
||||
noteId: string;
|
||||
@@ -67,13 +67,11 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
getChildBranches(): SBranch[] {
|
||||
return this.children.map(childNote => this.shaca.getBranchFromChildAndParent(childNote.noteId, this.noteId));
|
||||
return this.children.map((childNote) => this.shaca.getBranchFromChildAndParent(childNote.noteId, this.noteId));
|
||||
}
|
||||
|
||||
getVisibleChildBranches() {
|
||||
return this.getChildBranches()
|
||||
.filter(branch => !branch.isHidden
|
||||
&& !branch.getNote().isLabelTruthy('shareHiddenFromTree'));
|
||||
return this.getChildBranches().filter((branch) => !branch.isHidden && !branch.getNote().isLabelTruthy("shareHiddenFromTree"));
|
||||
}
|
||||
|
||||
getParentNotes() {
|
||||
@@ -85,8 +83,7 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
getVisibleChildNotes() {
|
||||
return this.getVisibleChildBranches()
|
||||
.map(branch => branch.getNote());
|
||||
return this.getVisibleChildBranches().map((branch) => branch.getNote());
|
||||
}
|
||||
|
||||
hasChildren() {
|
||||
@@ -103,8 +100,7 @@ class SNote extends AbstractShacaEntity {
|
||||
if (!row) {
|
||||
if (silentNotFoundError) {
|
||||
return undefined;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw new Error(`Cannot find note content for note '${this.noteId}', blob '${this.blobId}'`);
|
||||
}
|
||||
}
|
||||
@@ -112,11 +108,8 @@ class SNote extends AbstractShacaEntity {
|
||||
let content = row.content;
|
||||
|
||||
if (this.hasStringContent()) {
|
||||
return content === null
|
||||
? ""
|
||||
: content.toString("utf-8");
|
||||
}
|
||||
else {
|
||||
return content === null ? "" : content.toString("utf-8");
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -138,16 +131,13 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
if (type && name) {
|
||||
return attributeCache.filter(attr => attr.type === type && attr.name === name && !isCredentials(attr));
|
||||
}
|
||||
else if (type) {
|
||||
return attributeCache.filter(attr => attr.type === type && !isCredentials(attr));
|
||||
}
|
||||
else if (name) {
|
||||
return attributeCache.filter(attr => attr.name === name && !isCredentials(attr));
|
||||
}
|
||||
else {
|
||||
return attributeCache.filter(attr => !isCredentials(attr));
|
||||
return attributeCache.filter((attr) => attr.type === type && attr.name === name && !isCredentials(attr));
|
||||
} else if (type) {
|
||||
return attributeCache.filter((attr) => attr.type === type && !isCredentials(attr));
|
||||
} else if (name) {
|
||||
return attributeCache.filter((attr) => attr.name === name && !isCredentials(attr));
|
||||
} else {
|
||||
return attributeCache.filter((attr) => !isCredentials(attr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +154,7 @@ class SNote extends AbstractShacaEntity {
|
||||
const parentAttributes = this.ownedAttributes.slice();
|
||||
const newPath = [...path, this.noteId];
|
||||
|
||||
if (this.noteId !== 'root') {
|
||||
if (this.noteId !== "root") {
|
||||
for (const parentNote of this.parents) {
|
||||
parentAttributes.push(...parentNote.__getInheritableAttributes(newPath));
|
||||
}
|
||||
@@ -172,8 +162,9 @@ class SNote extends AbstractShacaEntity {
|
||||
|
||||
const templateAttributes: SAttribute[] = [];
|
||||
|
||||
for (const ownedAttr of parentAttributes) { // parentAttributes so we process also inherited templates
|
||||
if (ownedAttr.type === 'relation' && ['template', 'inherit'].includes(ownedAttr.name)) {
|
||||
for (const ownedAttr of parentAttributes) {
|
||||
// parentAttributes so we process also inherited templates
|
||||
if (ownedAttr.type === "relation" && ["template", "inherit"].includes(ownedAttr.name)) {
|
||||
const templateNote = this.shaca.notes[ownedAttr.value];
|
||||
|
||||
if (templateNote) {
|
||||
@@ -235,18 +226,17 @@ class SNote extends AbstractShacaEntity {
|
||||
getJsonContentSafely() {
|
||||
try {
|
||||
return this.getJsonContent();
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
hasAttribute(type: string, name: string) {
|
||||
return !!this.getAttributes().find(attr => attr.type === type && attr.name === name);
|
||||
return !!this.getAttributes().find((attr) => attr.type === type && attr.name === name);
|
||||
}
|
||||
|
||||
getRelationTarget(name: string) {
|
||||
const relation = this.getAttributes().find(attr => attr.type === 'relation' && attr.name === name);
|
||||
const relation = this.getAttributes().find((attr) => attr.type === "relation" && attr.name === name);
|
||||
|
||||
return relation ? relation.targetNote : null;
|
||||
}
|
||||
@@ -255,7 +245,9 @@ class SNote extends AbstractShacaEntity {
|
||||
* @param name - label name
|
||||
* @returns true if label exists (including inherited)
|
||||
*/
|
||||
hasLabel(name: string) { return this.hasAttribute(LABEL, name); }
|
||||
hasLabel(name: string) {
|
||||
return this.hasAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
@@ -268,74 +260,96 @@ class SNote extends AbstractShacaEntity {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!label && label.value !== 'false';
|
||||
return !!label && label.value !== "false";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns true if label exists (excluding inherited)
|
||||
*/
|
||||
hasOwnedLabel(name: string) { return this.hasOwnedAttribute(LABEL, name); }
|
||||
hasOwnedLabel(name: string) {
|
||||
return this.hasOwnedAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns true if relation exists (including inherited)
|
||||
*/
|
||||
hasRelation(name: string) { return this.hasAttribute(RELATION, name); }
|
||||
hasRelation(name: string) {
|
||||
return this.hasAttribute(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns true if relation exists (excluding inherited)
|
||||
*/
|
||||
hasOwnedRelation(name: string) { return this.hasOwnedAttribute(RELATION, name); }
|
||||
hasOwnedRelation(name: string) {
|
||||
return this.hasOwnedAttribute(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns label if it exists, null otherwise
|
||||
*/
|
||||
getLabel(name: string) { return this.getAttribute(LABEL, name); }
|
||||
getLabel(name: string) {
|
||||
return this.getAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns label if it exists, null otherwise
|
||||
*/
|
||||
getOwnedLabel(name: string) { return this.getOwnedAttribute(LABEL, name); }
|
||||
getOwnedLabel(name: string) {
|
||||
return this.getOwnedAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns relation if it exists, null otherwise
|
||||
*/
|
||||
getRelation(name: string) { return this.getAttribute(RELATION, name); }
|
||||
getRelation(name: string) {
|
||||
return this.getAttribute(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns relation if it exists, null otherwise
|
||||
*/
|
||||
getOwnedRelation(name: string) { return this.getOwnedAttribute(RELATION, name); }
|
||||
getOwnedRelation(name: string) {
|
||||
return this.getOwnedAttribute(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns label value if label exists, null otherwise
|
||||
*/
|
||||
getLabelValue(name: string) { return this.getAttributeValue(LABEL, name); }
|
||||
getLabelValue(name: string) {
|
||||
return this.getAttributeValue(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns label value if label exists, null otherwise
|
||||
*/
|
||||
getOwnedLabelValue(name: string) { return this.getOwnedAttributeValue(LABEL, name); }
|
||||
getOwnedLabelValue(name: string) {
|
||||
return this.getOwnedAttributeValue(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns relation value if relation exists, null otherwise
|
||||
*/
|
||||
getRelationValue(name: string) { return this.getAttributeValue(RELATION, name); }
|
||||
getRelationValue(name: string) {
|
||||
return this.getAttributeValue(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - relation name
|
||||
* @returns relation value if relation exists, null otherwise
|
||||
*/
|
||||
getOwnedRelationValue(name: string) { return this.getOwnedAttributeValue(RELATION, name); }
|
||||
getOwnedRelationValue(name: string) {
|
||||
return this.getOwnedAttributeValue(RELATION, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type - attribute type (label, relation, etc.)
|
||||
@@ -355,7 +369,7 @@ class SNote extends AbstractShacaEntity {
|
||||
getAttribute(type: string, name: string) {
|
||||
const attributes = this.getAttributes();
|
||||
|
||||
return attributes.find(attr => attr.type === type && attr.name === name);
|
||||
return attributes.find((attr) => attr.type === type && attr.name === name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +391,7 @@ class SNote extends AbstractShacaEntity {
|
||||
getOwnedAttributeValue(type: string, name: string) {
|
||||
const attr = this.getOwnedAttribute(type, name);
|
||||
|
||||
return attr ? attr.value as string : null; // FIXME
|
||||
return attr ? (attr.value as string) : null; // FIXME
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,7 +407,7 @@ class SNote extends AbstractShacaEntity {
|
||||
* @returns all note's label values, including inherited ones
|
||||
*/
|
||||
getLabelValues(name: string) {
|
||||
return this.getLabels(name).map(l => l.value) as string[]; // FIXME
|
||||
return this.getLabels(name).map((l) => l.value) as string[]; // FIXME
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -409,7 +423,7 @@ class SNote extends AbstractShacaEntity {
|
||||
* @returns all note's label values, excluding inherited ones
|
||||
*/
|
||||
getOwnedLabelValues(name: string) {
|
||||
return this.getOwnedAttributes(LABEL, name).map(l => l.value);
|
||||
return this.getOwnedAttributes(LABEL, name).map((l) => l.value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -440,15 +454,12 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
if (type && name) {
|
||||
return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name);
|
||||
}
|
||||
else if (type) {
|
||||
return this.ownedAttributes.filter(attr => attr.type === type);
|
||||
}
|
||||
else if (name) {
|
||||
return this.ownedAttributes.filter(attr => attr.name === name);
|
||||
}
|
||||
else {
|
||||
return this.ownedAttributes.filter((attr) => attr.type === type && attr.name === name);
|
||||
} else if (type) {
|
||||
return this.ownedAttributes.filter((attr) => attr.type === type);
|
||||
} else if (name) {
|
||||
return this.ownedAttributes.filter((attr) => attr.name === name);
|
||||
} else {
|
||||
return this.ownedAttributes.slice();
|
||||
}
|
||||
}
|
||||
@@ -465,11 +476,11 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
get isArchived() {
|
||||
return this.hasAttribute('label', 'archived');
|
||||
return this.hasAttribute("label", "archived");
|
||||
}
|
||||
|
||||
isInherited() {
|
||||
return !!this.targetRelations.find(rel => rel.name === 'template' || rel.name === 'inherit');
|
||||
return !!this.targetRelations.find((rel) => rel.name === "template" || rel.name === "inherit");
|
||||
}
|
||||
|
||||
getTargetRelations() {
|
||||
@@ -481,11 +492,11 @@ class SNote extends AbstractShacaEntity {
|
||||
}
|
||||
|
||||
getAttachmentByTitle(title: string) {
|
||||
return this.attachments.find(attachment => attachment.title === title);
|
||||
return this.attachments.find((attachment) => attachment.title === title);
|
||||
}
|
||||
|
||||
get shareId() {
|
||||
if (this.hasOwnedLabel('shareRoot')) {
|
||||
if (this.hasOwnedLabel("shareRoot")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -512,12 +523,11 @@ class SNote extends AbstractShacaEntity {
|
||||
attributes: this.getAttributes()
|
||||
// relations could link across shared subtrees which might leak them
|
||||
// individual relations might be whitelisted based on needs #3434
|
||||
.filter(attr => attr.type === 'label')
|
||||
.map(attr => attr.getPojo()),
|
||||
attachments: this.getAttachments()
|
||||
.map(attachment => attachment.getPojo()),
|
||||
parentNoteIds: this.parents.map(parentNote => parentNote.noteId),
|
||||
childNoteIds: this.children.map(child => child.noteId)
|
||||
.filter((attr) => attr.type === "label")
|
||||
.map((attr) => attr.getPojo()),
|
||||
attachments: this.getAttachments().map((attachment) => attachment.getPojo()),
|
||||
parentNoteIds: this.parents.map((parentNote) => parentNote.noteId),
|
||||
childNoteIds: this.children.map((child) => child.noteId)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import SBranch from "./entities/sbranch.js";
|
||||
import SNote from "./entities/snote.js";
|
||||
|
||||
export default class Shaca {
|
||||
|
||||
notes!: Record<string, SNote>;
|
||||
branches!: Record<string, SBranch>;
|
||||
childParentToBranch!: Record<string, SBranch>;
|
||||
@@ -84,12 +83,7 @@ export default class Shaca {
|
||||
return null;
|
||||
}
|
||||
|
||||
const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g,
|
||||
group =>
|
||||
group
|
||||
.toUpperCase()
|
||||
.replace('_', '')
|
||||
);
|
||||
const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g, (group) => group.toUpperCase().replace("_", ""));
|
||||
|
||||
return (this as any)[camelCaseEntityName][entityId];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import SAttribute from "./entities/sattribute.js";
|
||||
import SAttachment from "./entities/sattachment.js";
|
||||
import shareRoot from "../share_root.js";
|
||||
import eventService from "../../services/events.js";
|
||||
import { SAttachmentRow, SAttributeRow, SBranchRow, SNoteRow } from './entities/rows.js';
|
||||
import { SAttachmentRow, SAttributeRow, SBranchRow, SNoteRow } from "./entities/rows.js";
|
||||
|
||||
function load() {
|
||||
const start = Date.now();
|
||||
@@ -17,7 +17,8 @@ function load() {
|
||||
|
||||
// using a raw query and passing arrays to avoid allocating new objects
|
||||
|
||||
const noteIds = sql.getColumn(`
|
||||
const noteIds = sql.getColumn(
|
||||
`
|
||||
WITH RECURSIVE
|
||||
tree(noteId) AS (
|
||||
SELECT ?
|
||||
@@ -26,7 +27,9 @@ function load() {
|
||||
JOIN tree ON branches.parentNoteId = tree.noteId
|
||||
WHERE branches.isDeleted = 0
|
||||
)
|
||||
SELECT noteId FROM tree`, [shareRoot.SHARE_ROOT_NOTE_ID]);
|
||||
SELECT noteId FROM tree`,
|
||||
[shareRoot.SHARE_ROOT_NOTE_ID]
|
||||
);
|
||||
|
||||
if (noteIds.length === 0) {
|
||||
shaca.loaded = true;
|
||||
@@ -34,7 +37,7 @@ function load() {
|
||||
return;
|
||||
}
|
||||
|
||||
const noteIdStr = noteIds.map(noteId => `'${noteId}'`).join(",");
|
||||
const noteIdStr = noteIds.map((noteId) => `'${noteId}'`).join(",");
|
||||
|
||||
const rawNoteRows = sql.getRawRows<SNoteRow>(`
|
||||
SELECT noteId, title, type, mime, blobId, utcDateModified, isProtected
|
||||
@@ -88,9 +91,12 @@ function ensureLoad() {
|
||||
}
|
||||
}
|
||||
|
||||
eventService.subscribe([eventService.ENTITY_CREATED, eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED, eventService.ENTITY_CHANGE_SYNCED, eventService.ENTITY_DELETE_SYNCED], ({ entityName, entity }) => {
|
||||
shaca.reset();
|
||||
});
|
||||
eventService.subscribe(
|
||||
[eventService.ENTITY_CREATED, eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED, eventService.ENTITY_CHANGE_SYNCED, eventService.ENTITY_DELETE_SYNCED],
|
||||
({ entityName, entity }) => {
|
||||
shaca.reset();
|
||||
}
|
||||
);
|
||||
|
||||
export default {
|
||||
load,
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default {
|
||||
SHARE_ROOT_NOTE_ID: '_share'
|
||||
}
|
||||
SHARE_ROOT_NOTE_ID: "_share"
|
||||
};
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ let dbConnection!: Database.Database;
|
||||
sql_init.dbReady.then(() => {
|
||||
dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true });
|
||||
|
||||
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => {
|
||||
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
|
||||
process.on(eventType, () => {
|
||||
if (dbConnection) {
|
||||
// closing connection is especially important to fold -wal file into the main DB file
|
||||
|
||||
Reference in New Issue
Block a user