diff --git a/.eslintrc.js b/.eslintrc.js index 12f8725da..17b060730 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -92,6 +92,7 @@ module.exports = { renderMathInElement: true, // \src\public\app\widgets\type_widgets\editable_text.js BalloonEditor: true, + FancytreeNode: true, CKEditorInspector: true, // \src\public\app\widgets\type_widgets\editable_code.js CodeMirror: true, diff --git a/src/becca/entities/abstract_becca_entity.js b/src/becca/entities/abstract_becca_entity.js index 0fbf01630..4806063b5 100644 --- a/src/becca/entities/abstract_becca_entity.js +++ b/src/becca/entities/abstract_becca_entity.js @@ -189,7 +189,7 @@ class AbstractBeccaEntity { * We're using the unencrypted blob for the hash calculation, because otherwise the random IV would * cause every content blob to be unique which would balloon the database size (esp. with revisioning). * This has minor security implications (it's easy to infer that given content is shared between different - * notes/attachments, but the trade-off comes out clearly positive. + * notes/attachments, but the trade-off comes out clearly positive). */ newBlobId = utils.hashedBlobId(unencryptedContentForHashCalculation); blobNeedsInsert = !sql.getValue('SELECT 1 FROM blobs WHERE blobId = ?', [newBlobId]); @@ -228,7 +228,10 @@ class AbstractBeccaEntity { return newBlobId; } - /** @protected */ + /** + * @protected + * @returns {string|Buffer} + */ _getContent() { const row = sql.getRow(`SELECT content FROM blobs WHERE blobId = ?`, [this.blobId]); diff --git a/src/becca/entities/battachment.js b/src/becca/entities/battachment.js index fd303542a..118e617fc 100644 --- a/src/becca/entities/battachment.js +++ b/src/becca/entities/battachment.js @@ -86,7 +86,7 @@ class BAttachment extends AbstractBeccaEntity { || protectedSessionService.isProtectedSessionAvailable() } - /** @returns {*} */ + /** @returns {string|Buffer} */ getContent() { return this._getContent(); } diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index 4b15792b0..a02ca99aa 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -207,7 +207,7 @@ class BNote extends AbstractBeccaEntity { * - but to the user note content and title changes are one and the same - single dateModified (so all changes must go through Note and content is not a separate entity) */ - /** @returns {*} */ + /** @returns {string|Buffer} */ getContent() { return this._getContent(); } @@ -965,7 +965,7 @@ class BNote extends AbstractBeccaEntity { }; } - /** @returns {String[]} - includes the subtree root note as well */ + /** @returns {string[]} - includes the subtree root note as well */ getSubtreeNoteIds({includeArchived = true, includeHidden = false, resolveSearch = false} = {}) { return this.getSubtree({includeArchived, includeHidden, resolveSearch}) .notes @@ -1157,13 +1157,10 @@ class BNote extends AbstractBeccaEntity { } const parentNotes = this.getParentNotes(); - let notePaths = []; - if (parentNotes.length === 1) { // optimization for most common case - notePaths = parentNotes[0].getAllNotePaths(); - } else { - notePaths = parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); - } + const notePaths = parentNotes.length === 1 + ? parentNotes[0].getAllNotePaths() // optimization for most common case + : parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); for (const notePath of notePaths) { notePath.push(this.noteId); @@ -1514,10 +1511,10 @@ class BNote extends AbstractBeccaEntity { /** * (Soft) delete a note and all its descendants. * - * @param {string} [deleteId] - optional delete identified + * @param {string} [deleteId=null] - optional delete identified * @param {TaskContext} [taskContext] */ - deleteNote(deleteId, taskContext) { + deleteNote(deleteId = null, taskContext = null) { if (this.isDeleted) { return; } diff --git a/src/becca/entities/bnote_revision.js b/src/becca/entities/bnote_revision.js index 0167d22a5..982bdc497 100644 --- a/src/becca/entities/bnote_revision.js +++ b/src/becca/entities/bnote_revision.js @@ -80,7 +80,7 @@ class BNoteRevision extends AbstractBeccaEntity { * This is the same approach as is used for Note's content. */ - /** @returns {*} */ + /** @returns {string|Buffer} */ getContent() { return this._getContent(); } diff --git a/src/public/app/components/main_tree_executors.js b/src/public/app/components/main_tree_executors.js index 4889eea9f..f718ca7a6 100644 --- a/src/public/app/components/main_tree_executors.js +++ b/src/public/app/components/main_tree_executors.js @@ -47,7 +47,7 @@ export default class MainTreeExecutors extends Component { } const parentNotePath = treeService.getNotePath(node.getParent()); - const isProtected = await treeService.getParentProtectedStatus(node); + const isProtected = treeService.getParentProtectedStatus(node); if (node.data.noteId === 'root' || node.data.noteId === hoistedNoteService.getHoistedNoteId()) { return; diff --git a/src/public/app/components/note_context.js b/src/public/app/components/note_context.js index 16a52a7a2..ed2531db6 100644 --- a/src/public/app/components/note_context.js +++ b/src/public/app/components/note_context.js @@ -152,7 +152,7 @@ class NoteContext extends Component { return resolvedNotePath; } - /** @property {FNote} */ + /** @returns {FNote} */ get note() { if (!this.noteId || !(this.noteId in froca.notes)) { return null; @@ -161,7 +161,7 @@ class NoteContext extends Component { return froca.notes[this.noteId]; } - /** @property {string[]} */ + /** @returns {string[]} */ get notePathArray() { return this.notePath ? this.notePath.split('/') : []; } diff --git a/src/public/app/components/tab_manager.js b/src/public/app/components/tab_manager.js index 73eee6f74..60e583548 100644 --- a/src/public/app/components/tab_manager.js +++ b/src/public/app/components/tab_manager.js @@ -14,6 +14,8 @@ export default class TabManager extends Component { constructor() { super(); + /** @property {NoteContext[]} */ + this.children = []; this.mutex = new Mutex(); this.activeNtxId = null; @@ -38,7 +40,7 @@ export default class TabManager extends Component { appContext.addBeforeUnloadListener(this); } - /** @type {NoteContext[]} */ + /** @returns {NoteContext[]} */ get noteContexts() { return this.children; } diff --git a/src/public/app/entities/fnote.js b/src/public/app/entities/fnote.js index 47884f557..3d8bb034f 100644 --- a/src/public/app/entities/fnote.js +++ b/src/public/app/entities/fnote.js @@ -358,13 +358,10 @@ class FNote { } const parentNotes = this.getParentNotes(); - let notePaths = []; - if (parentNotes.length === 1) { // optimization for most common case - notePaths = parentNotes[0].getAllNotePaths(); - } else { - notePaths = parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); - } + const notePaths = parentNotes.length === 1 + ? parentNotes[0].getAllNotePaths() // optimization for most common case + : parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); for (const notePath of notePaths) { notePath.push(this.noteId); diff --git a/src/public/app/menus/tree_context_menu.js b/src/public/app/menus/tree_context_menu.js index 2439371b3..aa457407f 100644 --- a/src/public/app/menus/tree_context_menu.js +++ b/src/public/app/menus/tree_context_menu.js @@ -108,7 +108,7 @@ export default class TreeContextMenu { } else if (command === "insertNoteAfter") { const parentNotePath = treeService.getNotePath(this.node.getParent()); - const isProtected = await treeService.getParentProtectedStatus(this.node); + const isProtected = treeService.getParentProtectedStatus(this.node); noteCreateService.createNote(parentNotePath, { target: 'after', diff --git a/src/public/app/services/bundle.js b/src/public/app/services/bundle.js index 09b20105f..40658f692 100644 --- a/src/public/app/services/bundle.js +++ b/src/public/app/services/bundle.js @@ -41,7 +41,7 @@ class WidgetsByParent { add(widget) { if (!widget.parentWidget) { - console.log(`Custom widget does not have mandatory 'getParent()' method defined`); + console.log(`Custom widget does not have mandatory 'parentWidget' property defined`); return; } diff --git a/src/public/app/services/debounce.js b/src/public/app/services/debounce.js index 62415da29..4e5429a32 100644 --- a/src/public/app/services/debounce.js +++ b/src/public/app/services/debounce.js @@ -9,15 +9,15 @@ * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/ * @param {Function} func to wrap * @param {Number} waitMs in ms (`100`) - * @param {Boolean} immediate whether to execute at the beginning (`false`) + * @param {Boolean} [immediate=false] whether to execute at the beginning (`false`) * @api public */ -function debounce(func, waitMs, immediate) { - var timeout, args, context, timestamp, result; +function debounce(func, waitMs, immediate = false) { + let timeout, args, context, timestamp, result; if (null == waitMs) waitMs = 100; function later() { - var last = Date.now() - timestamp; + const last = Date.now() - timestamp; if (last < waitMs && last >= 0) { timeout = setTimeout(later, waitMs - last); @@ -30,11 +30,11 @@ function debounce(func, waitMs, immediate) { } } - var debounced = function(){ + const debounced = function () { context = this; args = arguments; timestamp = Date.now(); - var callNow = immediate && !timeout; + const callNow = immediate && !timeout; if (!timeout) timeout = setTimeout(later, waitMs); if (callNow) { result = func.apply(context, args); diff --git a/src/public/app/services/froca_updater.js b/src/public/app/services/froca_updater.js index 0b5314fd6..476812472 100644 --- a/src/public/app/services/froca_updater.js +++ b/src/public/app/services/froca_updater.js @@ -5,6 +5,7 @@ import options from "./options.js"; import noteAttributeCache from "./note_attribute_cache.js"; import FBranch from "../entities/fbranch.js"; import FAttribute from "../entities/fattribute.js"; +import FAttachment from "../entities/fattachment.js"; async function processEntityChanges(entityChanges) { const loadResults = new LoadResults(entityChanges); diff --git a/src/public/app/services/frontend_script_api.js b/src/public/app/services/frontend_script_api.js index 98d4e8460..11d4de8c3 100644 --- a/src/public/app/services/frontend_script_api.js +++ b/src/public/app/services/frontend_script_api.js @@ -322,7 +322,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance. * * @method - * @returns {Promise} instance of CKEditor + * @returns {Promise} instance of CKEditor */ this.getActiveContextTextEditor = () => appContext.tabManager.getActiveContext()?.getTextEditor(); diff --git a/src/public/app/services/open.js b/src/public/app/services/open.js index a6205173a..4ced214b4 100644 --- a/src/public/app/services/open.js +++ b/src/public/app/services/open.js @@ -79,7 +79,7 @@ async function openExternally(type, entityId, mime) { if (res) { // fallback in case there's no default application for this file - window.open(getFileUrl(type, entityId), { url: true }); + window.open(getFileUrl(type, entityId)); } } else { diff --git a/src/public/app/services/tree.js b/src/public/app/services/tree.js index 60e862f97..82436fd23 100644 --- a/src/public/app/services/tree.js +++ b/src/public/app/services/tree.js @@ -18,7 +18,7 @@ async function resolveNotePath(notePath, hoistedNoteId = 'root') { * 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. * - * @returns {string[]} + * @returns {Promise} */ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logErrors = true) { utils.assertArguments(notePath); @@ -129,7 +129,7 @@ ws.subscribeToMessages(message => { }); function getParentProtectedStatus(node) { - return hoistedNoteService.isHoistedNode(node) ? 0 : node.getParent().data.isProtected; + return hoistedNoteService.isHoistedNode(node) ? false : node.getParent().data.isProtected; } function getNoteIdFromNotePath(notePath) { diff --git a/src/public/app/services/utils.js b/src/public/app/services/utils.js index f4eb4371f..191c0965a 100644 --- a/src/public/app/services/utils.js +++ b/src/public/app/services/utils.js @@ -399,10 +399,10 @@ function escapeRegExp(str) { } function areObjectsEqual () { - var i, l, leftChain, rightChain; + let i, l, leftChain, rightChain; function compare2Objects (x, y) { - var p; + let p; // remember that NaN === NaN returns false // and isNaN(undefined) returns true diff --git a/src/public/app/widgets/attribute_widgets/attribute_editor.js b/src/public/app/widgets/attribute_widgets/attribute_editor.js index 1c4b9a3a1..8cd7aaf6f 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_editor.js +++ b/src/public/app/widgets/attribute_widgets/attribute_editor.js @@ -321,9 +321,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { parseAttributes() { try { - const attrs = attributesParser.lexAndParse(this.getPreprocessedData()); - - return attrs; + return attributesParser.lexAndParse(this.getPreprocessedData()); } catch (e) { this.$errors.text(e.message).slideDown(); diff --git a/src/public/app/widgets/bookmark_switch.js b/src/public/app/widgets/bookmark_switch.js index 3c661d9e0..b33a752b9 100644 --- a/src/public/app/widgets/bookmark_switch.js +++ b/src/public/app/widgets/bookmark_switch.js @@ -27,7 +27,7 @@ export default class BookmarkSwitchWidget extends SwitchWidget { } } - refreshWithNote(note) { + async refreshWithNote(note) { const isBookmarked = !!note.getParentBranches().find(b => b.parentNoteId === '_lbBookmarks'); this.$switchOn.toggle(!isBookmarked); diff --git a/src/public/app/widgets/buttons/note_actions.js b/src/public/app/widgets/buttons/note_actions.js index 58eec0007..f0f5b3419 100644 --- a/src/public/app/widgets/buttons/note_actions.js +++ b/src/public/app/widgets/buttons/note_actions.js @@ -90,7 +90,7 @@ export default class NoteActionsWidget extends NoteContextAwareWidget { }); } - refreshWithNote(note) { + async refreshWithNote(note) { this.$convertNoteIntoAttachmentButton.toggle(note.isEligibleForConversionToAttachment()); this.toggleDisabled(this.$findInTextButton, ['text', 'code', 'book', 'search'].includes(note.type)); diff --git a/src/public/app/widgets/dialogs/confirm.js b/src/public/app/widgets/dialogs/confirm.js index 64d6465c1..2ee8c8f42 100644 --- a/src/public/app/widgets/dialogs/confirm.js +++ b/src/public/app/widgets/dialogs/confirm.js @@ -34,7 +34,7 @@ export default class ConfirmDialog extends BasicWidget { super(); this.resolve = null; - this.$originallyFocused = null; // element focused before the dialog was opened, so we can return to it afterwards + this.$originallyFocused = null; // element focused before the dialog was opened, so we can return to it afterward } doRender() { diff --git a/src/public/app/widgets/dialogs/info.js b/src/public/app/widgets/dialogs/info.js index 113cc8732..738ac438d 100644 --- a/src/public/app/widgets/dialogs/info.js +++ b/src/public/app/widgets/dialogs/info.js @@ -27,7 +27,7 @@ export default class InfoDialog extends BasicWidget { super(); this.resolve = null; - this.$originallyFocused = null; // element focused before the dialog was opened, so we can return to it afterwards + this.$originallyFocused = null; // element focused before the dialog was opened, so we can return to it afterward } doRender() { diff --git a/src/public/app/widgets/dialogs/note_type_chooser.js b/src/public/app/widgets/dialogs/note_type_chooser.js index a3d703493..9a55b9417 100644 --- a/src/public/app/widgets/dialogs/note_type_chooser.js +++ b/src/public/app/widgets/dialogs/note_type_chooser.js @@ -46,7 +46,7 @@ export default class NoteTypeChooserDialog extends BasicWidget { super(props); this.resolve = null; - this.$originalFocused = null; // element focused before the dialog was opened, so we can return to it afterwards + this.$originalFocused = null; // element focused before the dialog was opened, so we can return to it afterward this.$originalDialog = null; } diff --git a/src/public/app/widgets/floating_buttons/code_buttons.js b/src/public/app/widgets/floating_buttons/code_buttons.js index f1763870b..3556d99cc 100644 --- a/src/public/app/widgets/floating_buttons/code_buttons.js +++ b/src/public/app/widgets/floating_buttons/code_buttons.js @@ -68,7 +68,7 @@ export default class CodeButtonsWidget extends NoteContextAwareWidget { super.doRender(); } - refreshWithNote(note) { + async refreshWithNote(note) { this.$executeButton.toggle( note.mime.startsWith('application/javascript') || note.mime === 'text/x-sqlite;schema=trilium' diff --git a/src/public/app/widgets/mermaid.js b/src/public/app/widgets/mermaid.js index 305209199..ec99d2a56 100644 --- a/src/public/app/widgets/mermaid.js +++ b/src/public/app/widgets/mermaid.js @@ -1,6 +1,5 @@ import libraryLoader from "../services/library_loader.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; -import froca from "../services/froca.js"; const TPL = `