diff --git a/src/becca/becca.js b/src/becca/becca.js index 85ba000c1..8b1a3fcb9 100644 --- a/src/becca/becca.js +++ b/src/becca/becca.js @@ -5,7 +5,8 @@ const NoteSet = require("../services/search/note_set"); const NotFoundError = require("../errors/not_found_error"); /** - * Becca is a backend cache of all notes, branches and attributes. There's a similar frontend cache Froca. + * Becca is a backend cache of all notes, branches, and attributes. + * There's a similar frontend cache Froca, and share cache Shaca. */ class Becca { constructor() { diff --git a/src/becca/becca_loader.js b/src/becca/becca_loader.js index 2b2aba663..a580266e9 100644 --- a/src/becca/becca_loader.js +++ b/src/becca/becca_loader.js @@ -28,7 +28,7 @@ function load() { becca.reset(); // using a raw query and passing arrays to avoid allocating new objects, - // this is worth it for becca load since it happens every run and blocks the app until finished + // this is worth it for the becca load since it happens every run and blocks the app until finished for (const row of sql.getRawRows(`SELECT noteId, title, type, mime, isProtected, blobId, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes WHERE isDeleted = 0`)) { new BNote().update(row).init(); diff --git a/src/becca/entities/battachment.js b/src/becca/entities/battachment.js index e59e13a03..fcf3169d8 100644 --- a/src/becca/entities/battachment.js +++ b/src/becca/entities/battachment.js @@ -46,7 +46,7 @@ class BAttachment extends AbstractBeccaEntity { this.mime = row.mime; /** @type {string} */ this.title = row.title; - /** @type {integer} */ + /** @type {int} */ this.position = row.position; /** @type {string} */ this.blobId = row.blobId; @@ -59,7 +59,7 @@ class BAttachment extends AbstractBeccaEntity { /** @type {string} */ this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince; - /** @type {integer} optionally added to the entity */ + /** @type {int} optionally added to the entity */ this.contentLength = row.contentLength; this.decrypt(); diff --git a/src/becca/entities/battribute.js b/src/becca/entities/battribute.js index bc5fd4cdf..41046b7e1 100644 --- a/src/becca/entities/battribute.js +++ b/src/becca/entities/battribute.js @@ -51,7 +51,7 @@ class BAttribute extends AbstractBeccaEntity { this.type = type; /** @type {string} */ this.name = name; - /** @type {integer} */ + /** @type {int} */ this.position = position; /** @type {string} */ this.value = value || ""; diff --git a/src/becca/entities/bblob.js b/src/becca/entities/bblob.js index 74395450c..def5888ee 100644 --- a/src/becca/entities/bblob.js +++ b/src/becca/entities/bblob.js @@ -8,7 +8,7 @@ class BBlob { this.blobId = row.blobId; /** @type {string|Buffer} */ this.content = row.content; - /** @type {integer} */ + /** @type {int} */ this.contentLength = row.contentLength; /** @type {string} */ this.dateModified = row.dateModified; diff --git a/src/becca/entities/bbranch.js b/src/becca/entities/bbranch.js index f0edc6a35..cbb08ff8a 100644 --- a/src/becca/entities/bbranch.js +++ b/src/becca/entities/bbranch.js @@ -55,7 +55,7 @@ class BBranch extends AbstractBeccaEntity { this.parentNoteId = parentNoteId; /** @type {string|null} */ this.prefix = prefix; - /** @type {integer} */ + /** @type {int} */ this.notePosition = notePosition; /** @type {boolean} */ this.isExpanded = !!isExpanded; diff --git a/src/becca/entities/brevision.js b/src/becca/entities/brevision.js index 8a856713c..45cece586 100644 --- a/src/becca/entities/brevision.js +++ b/src/becca/entities/brevision.js @@ -47,7 +47,7 @@ class BRevision extends AbstractBeccaEntity { this.utcDateCreated = row.utcDateCreated; /** @type {string} */ this.utcDateModified = row.utcDateModified; - /** @type {integer} */ + /** @type {int} */ this.contentLength = row.contentLength; if (this.isProtected && !titleDecrypted) { diff --git a/src/becca/similarity.js b/src/becca/similarity.js index e189fcc99..6f3983ca1 100644 --- a/src/becca/similarity.js +++ b/src/becca/similarity.js @@ -134,7 +134,7 @@ function buildRewardMap(note) { // title is the top with weight 1 so smaller headings will have lower weight - // technically H1 is not supported but for the case it's present let's weigh it just as H2 + // technically H1 is not supported, but for the case it's present let's weigh it just as H2 addHeadingsToRewardMap("h1", 0.9); addHeadingsToRewardMap("h2", 0.9); addHeadingsToRewardMap("h3", 0.8); @@ -447,7 +447,7 @@ async function findSimilarNotes(noteId) { } /** - * Point of this is to break up long-running sync process to avoid blocking + * The point of this is to break up the long-running sync process to avoid blocking * see https://snyk.io/blog/nodejs-how-even-quick-async-functions-can-block-the-event-loop-starve-io/ */ function setImmediatePromise() { diff --git a/src/etapi/attachments.js b/src/etapi/attachments.js index 8fcd10a15..722463897 100644 --- a/src/etapi/attachments.js +++ b/src/etapi/attachments.js @@ -63,7 +63,7 @@ function register(router) { throw new eu.EtapiError(400, "ATTACHMENT_IS_PROTECTED", `Attachment '${req.params.attachmentId}' is protected and content cannot be read through ETAPI.`); } - const filename = utils.formatDownloadTitle(attachment.title, attachment.type, attachment.mime); + const filename = utils.formatDownloadTitle(attachment.title, attachment.role, attachment.mime); res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); diff --git a/src/public/app/components/app_context.js b/src/public/app/components/app_context.js index 4433322fa..cea2c5d42 100644 --- a/src/public/app/components/app_context.js +++ b/src/public/app/components/app_context.js @@ -6,7 +6,6 @@ import options from "../services/options.js"; import utils from "../services/utils.js"; import zoomComponent from "./zoom.js"; import TabManager from "./tab_manager.js"; -import treeService from "../services/tree.js"; import Component from "./component.js"; import keyboardActionsService from "../services/keyboard_actions.js"; import linkService from "../services/link.js"; diff --git a/src/public/app/entities/fattachment.js b/src/public/app/entities/fattachment.js index e565efcb3..3ef6433d4 100644 --- a/src/public/app/entities/fattachment.js +++ b/src/public/app/entities/fattachment.js @@ -23,7 +23,7 @@ class FAttachment { /** @type {string} */ this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince; - /** @type {integer} optionally added to the entity */ + /** @type {int} optionally added to the entity */ this.contentLength = row.contentLength; this.froca.attachments[this.attachmentId] = this; diff --git a/src/public/app/entities/fattribute.js b/src/public/app/entities/fattribute.js index bfc488f6d..ce166e038 100644 --- a/src/public/app/entities/fattribute.js +++ b/src/public/app/entities/fattribute.js @@ -22,7 +22,7 @@ class FAttribute { this.name = row.name; /** @type {string} */ this.value = row.value; - /** @type {integer} */ + /** @type {int} */ this.position = row.position; /** @type {boolean} */ this.isInheritable = !!row.isInheritable; diff --git a/src/public/app/entities/fbranch.js b/src/public/app/entities/fbranch.js index 805d27f17..b1746c361 100644 --- a/src/public/app/entities/fbranch.js +++ b/src/public/app/entities/fbranch.js @@ -19,7 +19,7 @@ class FBranch { this.noteId = row.noteId; /** @type {string} */ this.parentNoteId = row.parentNoteId; - /** @type {integer} */ + /** @type {int} */ this.notePosition = row.notePosition; /** @type {string} */ this.prefix = row.prefix; diff --git a/src/public/app/entities/fnote.js b/src/public/app/entities/fnote.js index 7d243d2bd..b6f0e5ef2 100644 --- a/src/public/app/entities/fnote.js +++ b/src/public/app/entities/fnote.js @@ -4,7 +4,6 @@ import ws from "../services/ws.js"; import froca from "../services/froca.js"; import protectedSessionHolder from "../services/protected_session_holder.js"; import cssClassManager from "../services/css_class_manager.js"; -import FAttachment from "./fattachment.js"; const LABEL = 'label'; const RELATION = 'relation'; @@ -371,7 +370,7 @@ class FNote { /** * @param {string} [hoistedNoteId='root'] - * @return {Array<{isArchived: boolean, isInHoistedSubTree: boolean, notePath: Array, isHidden: boolean}>} + * @return {Array<{isArchived: boolean, isInHoistedSubTree: boolean, isSearch: boolean, notePath: Array, isHidden: boolean}>} */ getSortedNotePathRecords(hoistedNoteId = 'root') { const isHoistedRoot = hoistedNoteId === 'root'; @@ -380,6 +379,7 @@ class FNote { notePath: path, isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId), isArchived: path.some(noteId => froca.notes[noteId].isArchived), + isSearch: path.find(noteId => froca.notes[noteId].type === 'search'), isHidden: path.includes('_hidden') })); @@ -390,6 +390,8 @@ class FNote { return a.isArchived ? 1 : -1; } else if (a.isHidden !== b.isHidden) { return a.isHidden ? 1 : -1; + } else if (a.isSearch !== b.isSearch) { + return a.isSearch ? 1 : -1; } else { return a.notePath.length - b.notePath.length; } diff --git a/src/public/app/services/content_renderer.js b/src/public/app/services/content_renderer.js index 50b3e1f81..d1ad0d20a 100644 --- a/src/public/app/services/content_renderer.js +++ b/src/public/app/services/content_renderer.js @@ -158,7 +158,7 @@ function renderFile(entity, type, $renderedContent) { $content.append($pdfPreview); } else if (type === 'audio') { const $audioPreview = $('') - .attr("src", openService.getUrlForStreaming(`api/${entityType}/${entityId}/open-partial`)) + .attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open-partial`)) .attr("type", entity.mime) .css("width", "100%"); diff --git a/src/public/app/services/frontend_script_api.js b/src/public/app/services/frontend_script_api.js index 56b5aca50..ba9aed487 100644 --- a/src/public/app/services/frontend_script_api.js +++ b/src/public/app/services/frontend_script_api.js @@ -478,7 +478,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain * Return randomly generated string of given length. This random string generation is NOT cryptographically secure. * * @method - * @param {integer} length of the string + * @param {int} length of the string * @returns {string} random string */ this.randomString = utils.randomString; @@ -488,7 +488,15 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain * @param {int} size in bytes * @return {string} formatted string */ - this.formatNoteSize = utils.formatNoteSize; + this.formatSize = utils.formatSize; + + /** + * @method + * @param {int} size in bytes + * @return {string} formatted string + * @deprecated - use api.formatSize() + */ + this.formatNoteSize = utils.formatSize; this.logMessages = {}; this.logSpacedUpdates = {}; diff --git a/src/public/app/services/link.js b/src/public/app/services/link.js index 583f49b1c..c96a5ad7b 100644 --- a/src/public/app/services/link.js +++ b/src/public/app/services/link.js @@ -93,7 +93,7 @@ async function createLink(notePath, options = {}) { if (showNotePath) { const resolvedNotePathSegments = await treeService.resolveNotePathToSegments(notePath); - if (notePath) { + if (resolvedNotePathSegments) { resolvedNotePathSegments.pop(); // remove last element const parentNotePath = resolvedNotePathSegments.join("/").trim(); diff --git a/src/public/app/services/open.js b/src/public/app/services/open.js index 2a43ed093..43a5c9fa3 100644 --- a/src/public/app/services/open.js +++ b/src/public/app/services/open.js @@ -117,7 +117,7 @@ function getUrlForDownload(url) { return `${getHost()}/${url}`; } else { - // web server can be deployed on subdomain, so we need to use relative path + // web server can be deployed on subdomain, so we need to use a relative path return url; } } diff --git a/src/public/app/services/tree.js b/src/public/app/services/tree.js index 0c8968920..099f367f9 100644 --- a/src/public/app/services/tree.js +++ b/src/public/app/services/tree.js @@ -16,7 +16,7 @@ async function resolveNotePath(notePath, hoistedNoteId = 'root') { /** * Accepts notePath which might or might not be valid and returns an existing path as close to the original * notePath as possible. Part of the path might not be valid because of note moving (which causes - * path change) or other corruption, in that case this will try to get some other valid path to the correct note. + * path change) or other corruption, in that case, this will try to get some other valid path to the correct note. * * @returns {Promise} */ @@ -27,7 +27,7 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr notePath = notePath.split("?")[0].trim(); if (notePath.length === 0) { - return; + return null; } const path = notePath.split("/").reverse(); @@ -55,7 +55,7 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr ws.logError(`Can't find note ${childNoteId}`); } - return; + return null; } child.sortParents(); @@ -67,7 +67,7 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr ws.logError(`No parents found for note ${childNoteId} (${child.title}) for path ${notePath}`); } - return; + return null; } if (!parents.some(p => p.noteId === parentNoteId)) { diff --git a/src/public/app/services/utils.js b/src/public/app/services/utils.js index de1b05378..4d913cd8b 100644 --- a/src/public/app/services/utils.js +++ b/src/public/app/services/utils.js @@ -121,32 +121,6 @@ function escapeHtml(str) { return str.replace(/[&<>"'`=\/]/g, s => entityMap[s]); } -async function stopWatch(what, func) { - const start = new Date(); - - const ret = await func(); - - const tookMs = Date.now() - start.getTime(); - - console.log(`${what} took ${tookMs}ms`); - - return ret; -} - -function formatValueWithWhitespace(val) { - return /[^\w-]/.test(val) ? `"${val}"` : val; -} - -function formatLabel(label) { - let str = `#${formatValueWithWhitespace(label.name)}`; - - if (label.value !== "") { - str += `=${formatValueWithWhitespace(label.value)}`; - } - - return str; -} - function formatSize(size) { size = Math.max(Math.round(size / 1024), 1); @@ -203,15 +177,6 @@ function setCookie(name, value) { document.cookie = `${name}=${value || ""}${expires};`; } -function setSessionCookie(name, value) { - document.cookie = `${name}=${value || ""}; SameSite=Strict`; -} - -function getCookie(name) { - const valueMatch = document.cookie.match(`(^|;) ?${name}=([^;]*)(;|$)`); - return valueMatch ? valueMatch[2] : null; -} - function getNoteTypeClass(type) { return `type-${type}`; } @@ -372,7 +337,7 @@ function openHelp(e) { } function initHelpButtons($el) { - // for some reason the .on(event, listener, handler) does not work here (e.g. Options -> Sync -> Help button) + // for some reason, the .on(event, listener, handler) does not work here (e.g. Options -> Sync -> Help button) // so we do it manually $el.on("click", e => { if ($(e.target).attr("data-help-page")) { @@ -525,24 +490,9 @@ function copyHtmlToClipboard(content) { navigator.clipboard.write([clipboardItem]); } -function formatNoteSize(size) { - size = Math.max(Math.round(size / 1024), 1); - - if (size < 1024) { - return `${size} KiB`; - } - else { - return `${Math.round(size / 102.4) / 10} MiB`; - } -} - export default { reloadFrontendApp, parseDate, - padNum, - formatTime, - formatTimeWithSeconds, - formatDate, formatDateISO, formatDateTime, formatTimeInterval, @@ -554,15 +504,11 @@ export default { isCtrlKey, assertArguments, escapeHtml, - stopWatch, - formatLabel, toObject, randomString, isMobile, isDesktop, setCookie, - setSessionCookie, - getCookie, getNoteTypeClass, getMimeTypeClass, closeActiveDialog, @@ -581,7 +527,6 @@ export default { isValidAttributeName, sleep, escapeRegExp, - formatNoteSize, areObjectsEqual, copyHtmlToClipboard }; diff --git a/src/public/app/widgets/dialogs/revisions.js b/src/public/app/widgets/dialogs/revisions.js index f8e7aae72..19b3aa9df 100644 --- a/src/public/app/widgets/dialogs/revisions.js +++ b/src/public/app/widgets/dialogs/revisions.js @@ -147,7 +147,7 @@ export default class RevisionsDialog extends BasicWidget { for (const item of this.revisionItems) { this.$list.append( $('') - .text(`${item.dateLastEdited.substr(0, 16)} (${item.contentLength} bytes)`) + .text(`${item.dateLastEdited.substr(0, 16)} (${utils.formatSize(item.contentLength)})`) .attr('data-revision-id', item.revisionId) .attr('title', `This revision was last edited on ${item.dateLastEdited}`) ); @@ -259,7 +259,7 @@ export default class RevisionsDialog extends BasicWidget { )) .append($("").append( $("").text("File size:"), - $("").text(`${revisionItem.contentLength} bytes`) + $("").text(utils.formatSize(revisionItem.contentLength)) )); if (fullRevision.content) { diff --git a/src/public/app/widgets/find_in_code.js b/src/public/app/widgets/find_in_code.js index d1188b3cf..0d4d4ec64 100644 --- a/src/public/app/widgets/find_in_code.js +++ b/src/public/app/widgets/find_in_code.js @@ -42,7 +42,7 @@ export default class FindInCode { // Find and highlight matches // Find and highlight matches // XXX Using \\b and not using the unicode flag probably doesn't - // work with non ascii alphabets, findAndReplace uses a more + // work with non-ASCII alphabets, findAndReplace uses a more // complicated regexp, see // https://github.com/ckeditor/ckeditor5/blob/b95e2faf817262ac0e1e21993d9c0bde3f1be594/packages/ckeditor5-find-and-replace/src/utils.js#L145 const wholeWordChar = wholeWord ? "\\b" : ""; @@ -166,8 +166,6 @@ export default class FindInCode { } }); } - // Restore the highlightSelectionMatches setting - codeEditor.setOption("highlightSelectionMatches", this.oldHighlightSelectionMatches); this.findResult = null; codeEditor.focus(); diff --git a/src/public/app/widgets/ribbon_widgets/file_properties.js b/src/public/app/widgets/ribbon_widgets/file_properties.js index 633a3a60d..ad842124a 100644 --- a/src/public/app/widgets/ribbon_widgets/file_properties.js +++ b/src/public/app/widgets/ribbon_widgets/file_properties.js @@ -125,18 +125,15 @@ export default class FilePropertiesWidget extends NoteContextAwareWidget { } async refreshWithNote(note) { - const attributes = note.getAttributes(); - const attributeMap = utils.toObject(attributes, l => [l.name, l.value]); - this.$widget.show(); this.$fileNoteId.text(note.noteId); - this.$fileName.text(attributeMap.originalFileName || "?"); + this.$fileName.text(note.getLabelValue('originalFileName') || "?"); this.$fileType.text(note.mime); const blob = await this.note.getBlob(); - this.$fileSize.text(utils.formatNoteSize(blob.contentLength)); + this.$fileSize.text(utils.formatSize(blob.contentLength)); // open doesn't work for protected notes since it works through a browser which isn't in protected session this.$openButton.toggle(!note.isProtected); diff --git a/src/public/app/widgets/ribbon_widgets/image_properties.js b/src/public/app/widgets/ribbon_widgets/image_properties.js index db10ecafa..e95d47075 100644 --- a/src/public/app/widgets/ribbon_widgets/image_properties.js +++ b/src/public/app/widgets/ribbon_widgets/image_properties.js @@ -111,15 +111,12 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget { } async refreshWithNote(note) { - const attributes = note.getAttributes(); - const attributeMap = utils.toObject(attributes, l => [l.name, l.value]); - this.$widget.show(); const blob = await this.note.getBlob(); - this.$fileName.text(attributeMap.originalFileName || "?"); - this.$fileSize.text(`${blob.contentLength} bytes`); + this.$fileName.text(note.getLabelValue('originalFileName') || "?"); + this.$fileSize.text(utils.formatSize(blob.contentLength)); this.$fileType.text(note.mime); } } diff --git a/src/public/app/widgets/ribbon_widgets/note_info_widget.js b/src/public/app/widgets/ribbon_widgets/note_info_widget.js index c6911150a..2416ffe3d 100644 --- a/src/public/app/widgets/ribbon_widgets/note_info_widget.js +++ b/src/public/app/widgets/ribbon_widgets/note_info_widget.js @@ -106,12 +106,12 @@ export default class NoteInfoWidget extends NoteContextAwareWidget { this.$subTreeSize.empty().append($('')); const noteSizeResp = await server.get(`stats/note-size/${this.noteId}`); - this.$noteSize.text(utils.formatNoteSize(noteSizeResp.noteSize)); + this.$noteSize.text(utils.formatSize(noteSizeResp.noteSize)); const subTreeResp = await server.get(`stats/subtree-size/${this.noteId}`); if (subTreeResp.subTreeNoteCount > 1) { - this.$subTreeSize.text(`(subtree size: ${utils.formatNoteSize(subTreeResp.subTreeSize)} in ${subTreeResp.subTreeNoteCount} notes)`); + this.$subTreeSize.text(`(subtree size: ${utils.formatSize(subTreeResp.subTreeSize)} in ${subTreeResp.subTreeNoteCount} notes)`); } else { this.$subTreeSize.text(""); diff --git a/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js b/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js index 933d38283..a68371f35 100644 --- a/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js +++ b/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js @@ -1,7 +1,6 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; import AttributeDetailWidget from "../attribute_widgets/attribute_detail.js"; import AttributeEditorWidget from "../attribute_widgets/attribute_editor.js"; -import attributeService from "../../services/attributes.js"; const TPL = `
diff --git a/src/public/app/widgets/toc.js b/src/public/app/widgets/toc.js index 604d3bf80..ac718b9fd 100644 --- a/src/public/app/widgets/toc.js +++ b/src/public/app/widgets/toc.js @@ -84,15 +84,11 @@ export default class TocWidget extends RightPanelWidget { } async refreshWithNote(note) { - /*The reason for adding tocPreviousVisible is to record whether the previous state of the toc is hidden or displayed, - * and then let it be displayed/hidden at the initial time. If there is no such value, - * when the right panel needs to display highlighttext but not toc, every time the note content is changed, + /*The reason for adding tocPreviousVisible is to record whether the previous state of the toc is hidden or displayed, + * and then let it be displayed/hidden at the initial time. If there is no such value, + * when the right panel needs to display highlighttext but not toc, every time the note content is changed, * toc will appear and then close immediately, because getToc(html) function will consume time*/ - if (this.noteContext.viewScope.tocPreviousVisible ==true){ - this.toggleInt(true); - }else{ - this.toggleInt(false); - } + this.toggleInt(!!this.noteContext.viewScope.tocPreviousVisible); const tocLabel = note.getLabel('toc'); @@ -112,10 +108,10 @@ export default class TocWidget extends RightPanelWidget { this.$toc.html($toc); if (["", "show"].includes(tocLabel?.value) || headingCount >= options.getInt('minTocHeadings')){ this.toggleInt(true); - this.noteContext.viewScope.tocPreviousVisible=true; + this.noteContext.viewScope.tocPreviousVisible=true; }else{ this.toggleInt(false); - this.noteContext.viewScope.tocPreviousVisible=false; + this.noteContext.viewScope.tocPreviousVisible=false; } this.triggerCommand("reEvaluateRightPaneVisibility"); diff --git a/src/public/app/widgets/type_widgets/read_only_text.js b/src/public/app/widgets/type_widgets/read_only_text.js index 0e2fa92cb..ffab9fcef 100644 --- a/src/public/app/widgets/type_widgets/read_only_text.js +++ b/src/public/app/widgets/type_widgets/read_only_text.js @@ -1,5 +1,4 @@ import AbstractTextTypeWidget from "./abstract_text_type_widget.js"; -import treeService from "../../services/tree.js"; import libraryLoader from "../../services/library_loader.js"; const TPL = ` diff --git a/src/public/stylesheets/tree.css b/src/public/stylesheets/tree.css index 6e26b872c..fc7183054 100644 --- a/src/public/stylesheets/tree.css +++ b/src/public/stylesheets/tree.css @@ -62,10 +62,7 @@ span.fancytree-node.fancytree-hide { display: inline-block; width: 16px; height: 16px; - margin-left: 5px; - margin-right: 8px; - margin-top: 4px; - margin-bottom: 2px; + margin: 4px 8px 2px 5px; } .fancytree-loading span.fancytree-expander:after { diff --git a/src/routes/api/note_map.js b/src/routes/api/note_map.js index d0b2c1254..4faa5b3a8 100644 --- a/src/routes/api/note_map.js +++ b/src/routes/api/note_map.js @@ -35,7 +35,7 @@ function buildDescendantCountMap(noteIdsToCount) { } /** * @param {BNote} note - * @param {integer} depth + * @param {int} depth * @returns {string[]} noteIds */ function getNeighbors(note, depth) { diff --git a/src/routes/index.js b/src/routes/index.js index d0fbc4211..107f8cac1 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -15,7 +15,7 @@ const appPath = require("../services/app_path"); function index(req, res) { const options = optionService.getOptionMap(); - let view = (!utils.isElectron() && req.cookies['trilium-device'] === 'mobile') + const view = (!utils.isElectron() && req.cookies['trilium-device'] === 'mobile') ? 'mobile' : 'desktop'; @@ -47,18 +47,14 @@ function index(req, res) { function getThemeCssUrl(theme) { if (theme === 'light') { return false; // light theme is always loaded as baseline - } - - if (theme === 'dark') { + } else if (theme === 'dark') { return `${assetPath}/stylesheets/theme-dark.css`; - } - else { + } else { const themeNote = attributeService.getNoteWithLabel('appTheme', theme); if (themeNote) { return `api/notes/download/${themeNote.noteId}`; - } - else { + } else { return false; // baseline light theme } } diff --git a/src/routes/login.js b/src/routes/login.js index dd44da4da..42c0e59a0 100644 --- a/src/routes/login.js +++ b/src/routes/login.js @@ -59,7 +59,7 @@ function login(req, res) { const guessedPassword = req.body.password; if (verifyPassword(guessedPassword)) { - const rememberMe = req.body.remember_me; + const rememberMe = req.body.rememberMe; req.session.regenerate(() => { if (rememberMe) { diff --git a/src/routes/setup.js b/src/routes/setup.js index 8ed6756db..1d4de5dad 100644 --- a/src/routes/setup.js +++ b/src/routes/setup.js @@ -21,8 +21,8 @@ function setupPage(req, res) { return; } - // we got here because DB is not completely initialized so if schema exists - // it means we're in sync in progress state. + // we got here because DB is not completely initialized, so if schema exists, + // it means we're in "sync in progress" state. const syncInProgress = sqlInit.schemaExists(); if (syncInProgress) { diff --git a/src/services/backend_script_api.js b/src/services/backend_script_api.js index 17f64296b..8baa9e080 100644 --- a/src/services/backend_script_api.js +++ b/src/services/backend_script_api.js @@ -215,7 +215,7 @@ function BackendScriptApi(currentNote, apiParams) { * @property {boolean} [params.isProtected=false] * @property {boolean} [params.isExpanded=false] * @property {string} [params.prefix=''] - * @property {integer} [params.notePosition] - default is last existing notePosition in a parent + 10 + * @property {int} [params.notePosition] - default is last existing notePosition in a parent + 10 * @returns {{note: BNote, branch: BBranch}} object contains newly created entities note and branch */ this.createNewNote = noteService.createNewNote; @@ -412,7 +412,7 @@ function BackendScriptApi(currentNote, apiParams) { * Return randomly generated string of given length. This random string generation is NOT cryptographically secure. * * @method - * @param {integer} length of the string + * @param {int} length of the string * @returns {string} random string */ this.randomString = utils.randomString; diff --git a/src/services/cloning.js b/src/services/cloning.js index 846cffb06..87cab8122 100644 --- a/src/services/cloning.js +++ b/src/services/cloning.js @@ -59,9 +59,9 @@ function cloneNoteToBranch(noteId, parentBranchId, prefix) { } function ensureNoteIsPresentInParent(noteId, parentNoteId, prefix) { - if (isNoteDeleted(noteId)) { + if (!(noteId in becca.notes)) { return { branch: null, success: false, message: `Note '${noteId}' is deleted.` }; - } else if (isNoteDeleted(parentNoteId)) { + } else if (!(parentNoteId in becca.notes)) { return { branch: null, success: false, message: `Note '${parentNoteId}' is deleted.` }; } diff --git a/src/services/export/zip.js b/src/services/export/zip.js index 91ec8528a..b543d3b72 100644 --- a/src/services/export/zip.js +++ b/src/services/export/zip.js @@ -40,7 +40,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) const noteIdToMeta = {}; /** - * @param {Object.} existingFileNames + * @param {Object.} existingFileNames * @param {string} fileName * @returns {string} */ @@ -60,7 +60,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) return `${index}_${fileName}`; } - else {[] + else { existingFileNames[lcFileName] = 1; return fileName; @@ -71,7 +71,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) * @param {string|null} type * @param {string} mime * @param {string} baseFileName - * @param {Object.} existingFileNames + * @param {Object.} existingFileNames * @return {string} */ function getDataFileName(type, mime, baseFileName, existingFileNames) { @@ -119,7 +119,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) /** * @param {BBranch} branch * @param {NoteMeta} parentMeta - * @param {Object.} existingFileNames + * @param {Object.} existingFileNames * @returns {NoteMeta|null} */ function createNoteMeta(branch, parentMeta, existingFileNames) { diff --git a/src/services/meta/attachment_meta.js b/src/services/meta/attachment_meta.js index 8baa568a1..067a4a336 100644 --- a/src/services/meta/attachment_meta.js +++ b/src/services/meta/attachment_meta.js @@ -7,7 +7,7 @@ class AttachmentMeta { role; /** @type {string} */ mime; - /** @type {integer} */ + /** @type {int} */ position; /** @type {string} */ dataFileName; diff --git a/src/services/meta/attribute_meta.js b/src/services/meta/attribute_meta.js index c77e557bc..3d50cb585 100644 --- a/src/services/meta/attribute_meta.js +++ b/src/services/meta/attribute_meta.js @@ -7,7 +7,7 @@ class AttributeMeta { value; /** @type {boolean} */ isInheritable; - /** @type {integer} */ + /** @type {int} */ position; } diff --git a/src/services/meta/note_meta.js b/src/services/meta/note_meta.js index 7ddc99504..fd24381d6 100644 --- a/src/services/meta/note_meta.js +++ b/src/services/meta/note_meta.js @@ -7,7 +7,7 @@ class NoteMeta { isClone; /** @type {string} */ title; - /** @type {integer} */ + /** @type {int} */ notePosition; /** @type {string} */ prefix; diff --git a/src/services/notes.js b/src/services/notes.js index 473e5a8e1..b02d619ad 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -152,7 +152,7 @@ function getAndValidateParent(params) { * - {boolean} isProtected - default is false * - {boolean} isExpanded - default is false * - {string} prefix - default is empty string - * - {integer} notePosition - default is last existing notePosition in a parent + 10 + * - {int} notePosition - default is last existing notePosition in a parent + 10 * * @param params * @returns {{note: BNote, branch: BBranch}} diff --git a/src/services/options.js b/src/services/options.js index d30bd3d93..956d0f74b 100644 --- a/src/services/options.js +++ b/src/services/options.js @@ -26,7 +26,7 @@ function getOption(name) { return val; } -/** @returns {integer} */ +/** @returns {int} */ function getOptionInt(name, defaultValue = undefined) { const val = getOption(name); diff --git a/src/services/utils.js b/src/services/utils.js index 77a48e379..5b6d84fdd 100644 --- a/src/services/utils.js +++ b/src/services/utils.js @@ -7,7 +7,6 @@ const escape = require('escape-html'); const sanitize = require("sanitize-filename"); const mimeTypes = require('mime-types'); const path = require('path'); -const log = require('./log'); function newEntityId() { return randomString(12); @@ -33,11 +32,6 @@ function hashedBlobId(content) { return base64Hash.substr(0, 20); } -function randomBlobId(content) { - // underscore prefix to easily differentiate the random as opposed to hashed - return '_' + randomString(19); -} - function toBase64(plainText) { return Buffer.from(plainText).toString('base64'); } @@ -71,30 +65,6 @@ function sanitizeSqlIdentifier(str) { return str.replace(/[^A-Za-z0-9_]/g, ""); } -function prepareSqlForLike(prefix, str, suffix) { - const value = str - .replace(/\\/g, "\\\\") - .replace(/'/g, "''") - .replace(/_/g, "\\_") - .replace(/%/g, "\\%"); - - return `'${prefix}${value}${suffix}' ESCAPE '\\'`; -} - -function stopWatch(what, func, timeLimit = 0) { - const start = Date.now(); - - const ret = func(); - - const tookMs = Date.now() - start; - - if (tookMs >= timeLimit) { - log.info(`${what} took ${tookMs}ms`); - } - - return ret; -} - function escapeHtml(str) { return escape(str); } @@ -119,10 +89,6 @@ function stripTags(text) { return text.replace(/<(?:.|\n)*?>/gm, ''); } -function intersection(a, b) { - return a.filter(value => b.indexOf(value) !== -1); -} - function union(a, b) { const obj = {}; @@ -231,7 +197,7 @@ function formatDownloadTitle(fileName, type, mime) { if (mime === 'application/octet-stream') { // we didn't find any good guess for this one, it will be better to just return - // the current name without fake extension. It's possible that the title still preserves to correct + // the current name without a fake extension. It's possible that the title still preserves the correct // extension too return fileName; @@ -318,10 +284,6 @@ function normalize(str) { return removeDiacritic(str).toLowerCase(); } -function filterAttributeName(name) { - return name.replace(/[^\p{L}\p{N}_:]/ug, ""); -} - module.exports = { randomSecureToken, randomString, @@ -334,17 +296,13 @@ module.exports = { hash, isEmptyOrWhitespace, sanitizeSqlIdentifier, - prepareSqlForLike, - stopWatch, escapeHtml, unescapeHtml, toObject, stripTags, - intersection, union, escapeRegExp, crash, - sanitizeFilenameForHeader, getContentDisposition, isStringNote, quoteRegex, @@ -356,7 +314,5 @@ module.exports = { deferred, removeDiacritic, normalize, - filterAttributeName, hashedBlobId, - randomBlobId }; diff --git a/src/share/shaca/entities/sattribute.js b/src/share/shaca/entities/sattribute.js index 083e6ac4d..26b285ce8 100644 --- a/src/share/shaca/entities/sattribute.js +++ b/src/share/shaca/entities/sattribute.js @@ -14,7 +14,7 @@ class SAttribute extends AbstractShacaEntity { this.type = type; /** @param {string} */ this.name = name; - /** @param {integer} */ + /** @param {int} */ this.position = position; /** @param {string} */ this.value = value; diff --git a/src/share/shaca/shaca.js b/src/share/shaca/shaca.js index 694f76b69..4e1c3a1ba 100644 --- a/src/share/shaca/shaca.js +++ b/src/share/shaca/shaca.js @@ -16,7 +16,7 @@ class Shaca { this.attributes = {}; /** @type {Object.} */ this.attachments = {}; - /** @type {Object.} */ + /** @type {Object.} */ this.aliasToNote = {}; /** @type {SNote|null} */ diff --git a/src/views/login.ejs b/src/views/login.ejs index 31cc50d02..9fd72c2f4 100644 --- a/src/views/login.ejs +++ b/src/views/login.ejs @@ -28,7 +28,7 @@