diff --git a/packages/core/__tests__/lookup.test.js b/packages/core/__tests__/lookup.test.js index 86dec39a2..49d10e335 100644 --- a/packages/core/__tests__/lookup.test.js +++ b/packages/core/__tests__/lookup.test.js @@ -14,7 +14,10 @@ beforeEach(async () => { StorageInterface.clear(); }); -const content = { ...TEST_NOTE.content, data: "

5

" }; +const content = { + ...TEST_NOTE.content, + data: "

hello i am a note of the world

", +}; //TODO test("search notes", () => @@ -22,7 +25,7 @@ test("search notes", () => content: content, }).then(async ({ db }) => { await db.notes.add(TEST_NOTE); - let filtered = await db.lookup.notes(db.notes.all, "5"); + let filtered = await db.lookup.notes(db.notes.all, "note of the world"); expect(filtered.length).toBe(1); })); @@ -33,7 +36,7 @@ test("search notes with a locked note", () => const noteId = await db.notes.add(TEST_NOTE); await db.vault.create("password"); await db.vault.add(noteId); - let filtered = await db.lookup.notes(db.notes.all, "5"); + let filtered = await db.lookup.notes(db.notes.all, "note of the world"); expect(filtered.length).toBe(1); })); @@ -42,10 +45,10 @@ test("search notes with an empty note", () => content: content, }).then(async ({ db }) => { await db.notes.add({ - title: "hello world", + title: "world is a heavy tune", content: { type: "tiny", data: "


" }, }); - let filtered = await db.lookup.notes(db.notes.all, "hello world"); + let filtered = await db.lookup.notes(db.notes.all, "heavy tune"); expect(filtered.length).toBe(1); })); diff --git a/packages/core/api/lookup.js b/packages/core/api/lookup.js index df831b6fd..43f6a97ea 100644 --- a/packages/core/api/lookup.js +++ b/packages/core/api/lookup.js @@ -1,5 +1,4 @@ -import { qclone } from "qclone"; -import { getContentFromData } from "../content-types"; +import { Fzf } from "fzf"; export default class Lookup { /** @@ -11,28 +10,37 @@ export default class Lookup { } async notes(notes, query) { - notes = qclone(notes); const contents = await this._db.content.multi( notes.map((note) => note.contentId || "") ); - return notes.filter((note) => { - let content = ""; - if (!note.locked) { - content = contents.find( - (content) => !!content && content.id === note.contentId - ); - if (!content) return false; - content = getContentFromData(content.type, content.data); - content = content.toHTML(); - } - return search(query, note.title) || search(query, content); - }); + + const items = []; + for (let i = 0; i < notes.length; ++i) { + const note = notes[i]; + const item = { note, text: note.title }; + items.push(item); + if ( + !note.locked && + !!note.contentId && + contents.hasOwnProperty(note.contentId) + ) + item.text += " " + contents[note.contentId]["data"]; + } + + return new Fzf(items, { + selector: (v) => v.text, + normalize: false, + }) + .find(query) + .map((v) => v.item.note); } notebooks(array, query) { - return array.filter( - (item) => search(query, item.title) || search(query, item.description) - ); + return new Fzf(array, { + selector: (n) => `${n.title} ${n.description}`, + }) + .find(query) + .map((v) => v.item); } topics(array, query) { @@ -48,11 +56,10 @@ export default class Lookup { } _byTitle(array, query) { - return array.filter((item) => search(query, item.title)); + return new Fzf(array, { + selector: (n) => n.title, + }) + .find(query) + .map((v) => v.item); } } - -function search(query, string) { - const words = query.toLowerCase().split(" "); - return words.some((word) => string.toLowerCase().indexOf(word) > -1); -} diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index 27fd3ef77..d0da3515a 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -1,17 +1,18 @@ { "name": "notes-core", - "version": "6.13.1", + "version": "6.14.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "notes-core", - "version": "6.13.1", + "version": "6.14.0", "dependencies": { "@stablelib/blake2s": "^1.0.1", "async-mutex": "^0.3.2", "dayjs": "^1.10.6", "fast-sort": "^2.0.1", + "fzf": "^0.4.1", "node-html-parser": "github:thecodrr/node-html-parser", "qclone": "^1.0.4", "showdown": "github:thecodrr/showdown", @@ -4174,6 +4175,11 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/fzf": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.4.1.tgz", + "integrity": "sha512-ZKnxeZqxkJlnHXE37yfqyGez45Wan99eqns5B9xzVTvF4MazXlLsOYWeyiofdCEexgzuOmYGs3g7gtlz9lGxiQ==" + }, "node_modules/gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", @@ -11785,6 +11791,11 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "fzf": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.4.1.tgz", + "integrity": "sha512-ZKnxeZqxkJlnHXE37yfqyGez45Wan99eqns5B9xzVTvF4MazXlLsOYWeyiofdCEexgzuOmYGs3g7gtlz9lGxiQ==" + }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", diff --git a/packages/core/package.json b/packages/core/package.json index 9b7a96918..597c875fa 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -27,6 +27,7 @@ "async-mutex": "^0.3.2", "dayjs": "^1.10.6", "fast-sort": "^2.0.1", + "fzf": "^0.4.1", "node-html-parser": "github:thecodrr/node-html-parser", "qclone": "^1.0.4", "showdown": "github:thecodrr/showdown",