From ddda4d9867a16c17f6f6ff675e77de5fec146503 Mon Sep 17 00:00:00 2001 From: zadam Date: Tue, 27 Jun 2023 22:57:13 +0200 Subject: [PATCH] fix constructing result note path in the jump to note dialog, closes #4054 --- .../search/expressions/note_flat_text.js | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/services/search/expressions/note_flat_text.js b/src/services/search/expressions/note_flat_text.js index 62985f590..3703b5a2f 100644 --- a/src/services/search/expressions/note_flat_text.js +++ b/src/services/search/expressions/note_flat_text.js @@ -19,20 +19,22 @@ class NoteFlatTextExp extends Expression { /** * @param {BNote} note - * @param {string[]} tokens - * @param {string[]} path + * @param {string[]} remainingTokens - tokens still needed to be found in the path towards root + * @param {string[]} takenPath - path so far taken towards from candidate note towards the root. + * It contains the suffix fragment of the full note path. */ - const searchDownThePath = (note, tokens, path) => { - if (tokens.length === 0) { - const retPath = this.getNotePath(note, path); + const searchPathTowardsRoot = (note, remainingTokens, takenPath) => { + if (remainingTokens.length === 0) { + // we're done, just build the result + const resultPath = this.getNotePath(note, takenPath); - if (retPath) { - const noteId = retPath[retPath.length - 1]; + if (resultPath) { + const noteId = resultPath[resultPath.length - 1]; if (!resultNoteSet.hasNoteId(noteId)) { // we could get here from multiple paths, the first one wins because the paths // are sorted by importance - executionContext.noteIdToNotePath[noteId] = retPath; + executionContext.noteIdToNotePath[noteId] = resultPath; resultNoteSet.add(becca.notes[noteId]); } @@ -42,22 +44,23 @@ class NoteFlatTextExp extends Expression { } if (note.parents.length === 0 || note.noteId === 'root') { + // we've reached root, but there are still remaining tokens -> this candidate note produced no result return; } const foundAttrTokens = []; - for (const token of tokens) { + for (const token of remainingTokens) { if (note.type.includes(token) || note.mime.includes(token)) { foundAttrTokens.push(token); } } - for (const attribute of note.ownedAttributes) { + for (const attribute of note.getOwnedAttributes()) { const normalizedName = utils.normalize(attribute.name); const normalizedValue = utils.normalize(attribute.value); - for (const token of tokens) { + for (const token of remainingTokens) { if (normalizedName.includes(token) || normalizedValue.includes(token)) { foundAttrTokens.push(token); } @@ -68,19 +71,19 @@ class NoteFlatTextExp extends Expression { const title = utils.normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); const foundTokens = foundAttrTokens.slice(); - for (const token of tokens) { + for (const token of remainingTokens) { if (title.includes(token)) { foundTokens.push(token); } } if (foundTokens.length > 0) { - const remainingTokens = tokens.filter(token => !foundTokens.includes(token)); + const newRemainingTokens = remainingTokens.filter(token => !foundTokens.includes(token)); - searchDownThePath(parentNote, remainingTokens, [...path, note.noteId]); + searchPathTowardsRoot(parentNote, newRemainingTokens, [note.noteId, ...takenPath]); } else { - searchDownThePath(parentNote, tokens, [...path, note.noteId]); + searchPathTowardsRoot(parentNote, remainingTokens, [note.noteId, ...takenPath]); } } } @@ -90,7 +93,7 @@ class NoteFlatTextExp extends Expression { for (const note of candidateNotes) { // autocomplete should be able to find notes by their noteIds as well (only leafs) if (this.tokens.length === 1 && note.noteId.toLowerCase() === this.tokens[0]) { - searchDownThePath(note, [], []); + searchPathTowardsRoot(note, [], [note.noteId]); continue; } @@ -123,7 +126,7 @@ class NoteFlatTextExp extends Expression { if (foundTokens.length > 0) { const remainingTokens = this.tokens.filter(token => !foundTokens.includes(token)); - searchDownThePath(parentNote, remainingTokens, [note.noteId]); + searchPathTowardsRoot(parentNote, remainingTokens, [note.noteId]); } } } @@ -131,14 +134,22 @@ class NoteFlatTextExp extends Expression { return resultNoteSet; } - getNotePath(note, path) { - if (path.length === 0) { + /** + * @param {BNote} note + * @param {string[]} takenPath + * @returns {string[]} + */ + getNotePath(note, takenPath) { + if (takenPath.length === 0) { + throw new Error("Path is not expected to be empty."); + } else if (takenPath.length === 1 && takenPath[0] === note.noteId) { return note.getBestNotePath(); } else { - const closestNoteId = path[0]; - const closestNoteBestNotePath = becca.getNote(closestNoteId).getBestNotePath(); + // this note is the closest to root containing the last matching token(s), thus completing the requirements + // what's in this note's predecessors does not matter, thus we'll choose the best note path + const topMostMatchingTokenNotePath = becca.getNote(takenPath[0]).getBestNotePath(); - return [...closestNoteBestNotePath, ...path.slice(1)]; + return [...topMostMatchingTokenNotePath, ...takenPath.slice(1)]; } }