From eec850c11f09538239d03de4a57f2858ff638143 Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 11:14:27 +0200 Subject: [PATCH 1/7] fix toggle sidebar issues, closes #1196 --- package-lock.json | 8 ++++---- package.json | 2 +- src/public/app/widgets/note_tree.js | 1 + src/public/app/widgets/side_pane_toggles.js | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 481284c32..fee9f588c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "trilium", - "version": "0.43.0-beta", + "version": "0.43.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7923,9 +7923,9 @@ "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" }, "node-abi": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz", - "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.18.0.tgz", + "integrity": "sha512-yi05ZoiuNNEbyT/xXfSySZE+yVnQW6fxPZuFbLyS1s6b5Kw3HzV2PHOM4XR+nsjzkHxByK+2Wg+yCQbe35l8dw==", "requires": { "semver": "^5.4.1" }, diff --git a/package.json b/package.json index 4633d521f..22f2a5270 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "jimp": "0.10.3", "mime-types": "2.1.27", "multer": "1.4.2", - "node-abi": "2.16.0", + "node-abi": "2.18.0", "open": "7.0.3", "portscanner": "2.2.0", "rand-token": "1.0.1", diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index 5d78a6904..a5802acb5 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -32,6 +32,7 @@ const TPL = ` .tree { height: 100%; overflow: auto; + padding-bottom: 20px; } .refresh-search-button { diff --git a/src/public/app/widgets/side_pane_toggles.js b/src/public/app/widgets/side_pane_toggles.js index df443ae13..fbb5a055c 100644 --- a/src/public/app/widgets/side_pane_toggles.js +++ b/src/public/app/widgets/side_pane_toggles.js @@ -20,8 +20,8 @@ const TPL = ` } - - + + From a89629b3de8df2925365d761f73031a132ce618e Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 11:34:14 +0200 Subject: [PATCH 2/7] add fallback when resizing image fails, closes #1190 --- src/services/image.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/services/image.js b/src/services/image.js index 9d5d5fa50..3a525ce45 100644 --- a/src/services/image.js +++ b/src/services/image.js @@ -98,7 +98,17 @@ async function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSw async function shrinkImage(buffer, originalName) { // we do resizing with max (100) quality which will be trimmed during optimization step next - const resizedImage = await resize(buffer, 100); + let resizedImage; + + try { + resizedImage = await resize(buffer, 100); + } + catch (e) { + log.error("Failed to resize image '" + originalName + "'\nStack: " + e.stack); + + resizedImage = buffer; + } + let finalImageBuffer; const jpegQuality = await optionService.getOptionInt('imageJpegQuality'); @@ -107,7 +117,15 @@ async function shrinkImage(buffer, originalName) { finalImageBuffer = await optimize(resizedImage, jpegQuality); } catch (e) { log.error("Failed to optimize image '" + originalName + "'\nStack: " + e.stack); - finalImageBuffer = await resize(buffer, jpegQuality); + + try { + finalImageBuffer = await resize(buffer, jpegQuality); + } + catch (e) { + log.error("Failed to resize image '" + originalName + "'\nStack: " + e.stack); + + finalImageBuffer = buffer; + } } // if resizing & shrinking did not help with size then save the original From 20b4b059e33733d75d62ae303471c2c1e2fe6a0d Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 12:00:57 +0200 Subject: [PATCH 3/7] fix jsdoc --- src/services/options.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/options.js b/src/services/options.js index f2da61ab7..2118d4b9d 100644 --- a/src/services/options.js +++ b/src/services/options.js @@ -9,7 +9,7 @@ function getOption(name) { } /** - * @return {Promise} + * @return {number} */ function getOptionInt(name) { const val = getOption(name); @@ -24,7 +24,7 @@ function getOptionInt(name) { } /** - * @return {Promise} + * @return {boolean} */ function getOptionBool(name) { const val = getOption(name); From d037420acb0814a8148cff0ab3c4832764a889c5 Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 13:53:15 +0200 Subject: [PATCH 4/7] note. prefix also separates fulltext tokens from expression tokens --- spec/search/lexer.spec.js | 13 +++++++++++++ src/services/search/services/lex.js | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/spec/search/lexer.spec.js b/spec/search/lexer.spec.js index 8cce5e6c0..e781d9b43 100644 --- a/spec/search/lexer.spec.js +++ b/spec/search/lexer.spec.js @@ -75,6 +75,19 @@ describe("Lexer expression", () => { ]); }); + it("note. prefix also separates fulltext from expression", () => { + expect(lex(`hello fulltext note.labels.capital = Prague`).expressionTokens.map(t => t.token)) + .toEqual(["note", ".", "labels", ".", "capital", "=", "prague"]); + }); + + it("note. prefix in quotes will note start expression", () => { + expect(lex(`hello fulltext "note.txt"`).expressionTokens.map(t => t.token)) + .toEqual([]); + + expect(lex(`hello fulltext "note.txt"`).fulltextTokens.map(t => t.token)) + .toEqual(["hello", "fulltext", "note.txt"]); + }); + it("complex expressions with and, or and parenthesis", () => { expect(lex(`# (#label=text OR #second=text) AND ~relation`).expressionTokens.map(t => t.token)) .toEqual(["#", "(", "#label", "=", "text", "or", "#second", "=", "text", ")", "and", "~relation"]); diff --git a/src/services/search/services/lex.js b/src/services/search/services/lex.js index 821a3e2fc..4f6ab8b97 100644 --- a/src/services/search/services/lex.js +++ b/src/services/search/services/lex.js @@ -83,6 +83,10 @@ function lex(str) { continue; } else if (!quotes) { + if (!fulltextEnded && currentWord === 'note' && chr === '.') { + fulltextEnded = true; + } + if (chr === '#' || chr === '~') { if (!fulltextEnded) { fulltextEnded = true; From 0b38e2418579790ea894aa3a337189f11e097d8f Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 15:23:24 +0200 Subject: [PATCH 5/7] fixes to saved search --- package-lock.json | 6 +++--- package.json | 2 +- src/app.js | 3 ++- src/public/app/services/tree_cache.js | 15 +++++++-------- src/public/app/widgets/note_tree.js | 2 +- src/routes/api/search.js | 22 ++++++++++++---------- src/services/notes.js | 2 +- src/services/search/services/search.js | 7 +++++-- 8 files changed, 32 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index f2ded96c0..65ffd0b5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2762,9 +2762,9 @@ } }, "dayjs": { - "version": "1.8.33", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.33.tgz", - "integrity": "sha512-881TDLZCdpJFKbraWRHcUG8zfMLLX400ENf9rFZDuWc5zYMss6xifo2PhlDX0ftOmR2NRmaIY47bAa4gKQfXqw==" + "version": "1.8.34", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.34.tgz", + "integrity": "sha512-Olb+E6EoMvdPmAMq2QoucuyZycKHjTlBXmRx8Ada+wGtq4SIXuDCdtoaX4KkK0yjf1fJLnwXQURr8gQKWKaybw==" }, "debug": { "version": "4.1.1", diff --git a/package.json b/package.json index 31ed07be5..52fa7e7ea 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "commonmark": "0.29.1", "cookie-parser": "1.4.5", "csurf": "1.11.0", - "dayjs": "1.8.33", + "dayjs": "1.8.34", "debug": "4.1.1", "ejs": "3.1.5", "electron-debug": "3.1.0", diff --git a/src/app.js b/src/app.js index f18324f54..3cd32aa7c 100644 --- a/src/app.js +++ b/src/app.js @@ -23,7 +23,8 @@ app.use(helmet({ hidePoweredBy: false, // deactivated because electron 4.0 crashes on this right after startup contentSecurityPolicy: { directives: { - defaultSrc: ["*", "'unsafe-inline'", "'unsafe-eval'", "img-src 'self' data:"] + defaultSrc: ["*", "'unsafe-inline'", "'unsafe-eval'"], + imgSrc: ["'self' data:"] } } })); diff --git a/src/public/app/services/tree_cache.js b/src/public/app/services/tree_cache.js index 4dba0792a..ad5e76161 100644 --- a/src/public/app/services/tree_cache.js +++ b/src/public/app/services/tree_cache.js @@ -165,23 +165,22 @@ class TreeCache { for (const note of resp.notes) { if (note.type === 'search') { - const searchResults = await server.get('search-note/' + note.noteId); + const searchResultNoteIds = await server.get('search-note/' + note.noteId); - if (!searchResults) { + if (!searchResultNoteIds) { throw new Error(`Search note ${note.noteId} failed.`); } // force to load all the notes at once instead of one by one - await this.getNotes(searchResults.map(res => res.noteId)); + await this.getNotes(searchResultNoteIds); const branches = resp.branches.filter(b => b.noteId === note.noteId || b.parentNoteId === note.noteId); - searchResults.forEach((result, index) => branches.push({ + searchResultNoteIds.forEach((resultNoteId, index) => branches.push({ // branchId should be repeatable since sometimes we reload some notes without rerendering the tree - branchId: "virt" + result.noteId + '-' + note.noteId, - noteId: result.noteId, + branchId: "virt" + resultNoteId + '-' + note.noteId, + noteId: resultNoteId, parentNoteId: note.noteId, - prefix: this.getBranch(result.branchId).prefix, notePosition: (index + 1) * 10 })); @@ -217,7 +216,7 @@ class TreeCache { return noteIds.map(noteId => { if (!this.notes[noteId] && !silentNotFoundError) { - console.log(`Can't find note "${noteId}"`); + console.trace(`Can't find note "${noteId}"`); return null; } diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index a4494e53c..3006871e0 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -589,7 +589,7 @@ export default class NoteTreeWidget extends TabAwareWidget { const note = await branch.getNote(); if (!note) { - throw new Error(`Branch has no note ` + branch.noteId); + throw new Error(`Branch has no note "${branch.noteId}": ${JSON.stringify(note)}`); } const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title; diff --git a/src/routes/api/search.js b/src/routes/api/search.js index cb7070bc4..72cbda3e8 100644 --- a/src/routes/api/search.js +++ b/src/routes/api/search.js @@ -23,7 +23,7 @@ function searchNotes(req) { } } -function searchFromNote(req) { +async function searchFromNote(req) { const note = repository.getNote(req.params.noteId); if (!note) { @@ -44,15 +44,16 @@ function searchFromNote(req) { return []; } - let noteIds; + let searchResultNoteIds; try { if (json.searchString.startsWith('=')) { const relationName = json.searchString.substr(1).trim(); - noteIds = searchFromRelation(note, relationName); + searchResultNoteIds = await searchFromRelation(note, relationName); } else { - noteIds = searchService.searchForNoteIds(json.searchString); + searchResultNoteIds = searchService.searchNotes(json.searchString) + .map(sr => sr.noteId); } } catch (e) { @@ -62,16 +63,17 @@ function searchFromNote(req) { } // we won't return search note's own noteId - noteIds = noteIds.filter(noteId => noteId !== note.noteId); + // also don't allow root since that would force infinite cycle + searchResultNoteIds = searchResultNoteIds.filter(resultNoteId => !['root', note.noteId].includes(resultNoteId)); - if (noteIds.length > 200) { - noteIds = noteIds.slice(0, 200); + if (searchResultNoteIds.length > 200) { + searchResultNoteIds = searchResultNoteIds.slice(0, 200); } - return noteIds.map(noteCacheService.getNotePath).filter(res => !!res); + return searchResultNoteIds; } -function searchFromRelation(note, relationName) { +async function searchFromRelation(note, relationName) { const scriptNote = note.getRelationTarget(relationName); if (!scriptNote) { @@ -92,7 +94,7 @@ function searchFromRelation(note, relationName) { return []; } - const result = scriptService.executeNote(scriptNote, { originEntity: note }); + const result = await scriptService.executeNote(scriptNote, { originEntity: note }); if (!Array.isArray(result)) { log.info(`Result from ${scriptNote.noteId} is not an array.`); diff --git a/src/services/notes.js b/src/services/notes.js index 2f8d33b6f..cdd2aa1fc 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -92,7 +92,7 @@ function copyChildAttributes(parentNote, childNote) { * - {integer} notePosition - default is last existing notePosition in a parent + 10 * * @param params - * @return {Promise<{note: Note, branch: Branch}>} + * @return {{note: Note, branch: Branch}} */ function createNewNote(params) { const parentNote = repository.getNote(params.parentNoteId); diff --git a/src/services/search/services/search.js b/src/services/search/services/search.js index d3eeb1c3d..495e0b321 100644 --- a/src/services/search/services/search.js +++ b/src/services/search/services/search.js @@ -14,7 +14,7 @@ const utils = require('../../utils.js'); /** * @param {Expression} expression - * @return {Promise} + * @return {SearchResult[]} */ function findNotesWithExpression(expression) { const hoistedNote = noteCache.notes[hoistedNoteService.getHoistedNoteId()]; @@ -67,7 +67,7 @@ function parseQueryToExpression(query, parsingContext) { /** * @param {string} query * @param {ParsingContext} parsingContext - * @return {Promise} + * @return {SearchResult[]} */ function findNotesWithQuery(query, parsingContext) { const expression = parseQueryToExpression(query, parsingContext); @@ -79,6 +79,9 @@ function findNotesWithQuery(query, parsingContext) { return findNotesWithExpression(expression); } +/** + * @return {SearchResult[]} + */ function searchNotes(query) { if (!query.trim().length) { return []; From 4d4d9f2000bad158f86ae70fc1144f8587bde5f8 Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 20 Aug 2020 15:28:28 +0200 Subject: [PATCH 6/7] small fixes to saved search --- src/public/app/widgets/search_box.js | 10 +++++----- src/public/app/widgets/type_widgets/search.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/public/app/widgets/search_box.js b/src/public/app/widgets/search_box.js index cc9ce0344..cce532372 100644 --- a/src/public/app/widgets/search_box.js +++ b/src/public/app/widgets/search_box.js @@ -3,6 +3,7 @@ import toastService from "../services/toast.js"; import appContext from "../services/app_context.js"; import noteCreateService from "../services/note_create.js"; import utils from "../services/utils.js"; +import treeCache from "../services/tree_cache.js"; const TPL = `