From 6e604988f4720d168a654c1a1cc2fefa6fdcae5a Mon Sep 17 00:00:00 2001 From: Simon Cambier Date: Fri, 17 Jun 2022 19:56:10 +0200 Subject: [PATCH] Fixed #48 - Highly favor tags in search results --- src/globals.ts | 1 + src/search.ts | 24 ++++++++++++++++++++++-- src/types.d.ts | 1 + src/utils.ts | 14 ++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/globals.ts b/src/globals.ts index 572729b..772a6be 100644 --- a/src/globals.ts +++ b/src/globals.ts @@ -27,6 +27,7 @@ export type IndexedNote = { content: string aliases: string + tags: string[], headings1: string headings2: string headings3: string diff --git a/src/search.ts b/src/search.ts index c28e2c4..9a81a47 100644 --- a/src/search.ts +++ b/src/search.ts @@ -1,5 +1,5 @@ import { Notice, TAbstractFile, TFile } from 'obsidian' -import MiniSearch, { type SearchResult } from 'minisearch' +import MiniSearch, { type Options, type SearchResult } from 'minisearch' import { chsRegex, SPACE_OR_PUNCTUATION, @@ -10,6 +10,7 @@ import { import { extractHeadingsFromCache, getAliasesFromMetadata, + getTagsFromMetadata, removeDiacritics, stringsToRegex, stripMarkdownCharacters, @@ -51,7 +52,7 @@ const tokenize = (text: string): string[] => { * and adds all the notes to the index */ export async function initGlobalSearchIndex(): Promise { - const options = { + const options: Options = { tokenize, processTerm: (term: string) => (settings.ignoreDiacritics ? removeDiacritics(term) : term).toLowerCase(), @@ -64,6 +65,7 @@ export async function initGlobalSearchIndex(): Promise { 'headings2', 'headings3', ], + storeFields: ['tags'], } if ( @@ -234,6 +236,18 @@ export async function getSuggestions( } else { results = results.slice(0, 50) + + // Put the results with tags on top + const tags = query.segments + .filter(s => s.value.startsWith('#')) + .map(s => s.value) + for (const tag of tags) { + for (const result of results) { + if (result.tags.includes(tag)) { + result.score *= 100 + } + } + } } // Map the raw results to get usable suggestions @@ -243,6 +257,10 @@ export async function getSuggestions( throw new Error(`Note "${result.id}" not indexed`) } + // Remove '#' from tags, for highlighting + query.segments.forEach(s => { + s.value = s.value.replace(/^#/, '') + }) // Clean search matches that match quoted expressions, // and inject those expressions instead const foundWords = [ @@ -251,6 +269,7 @@ export async function getSuggestions( ), ...query.segments.filter(s => s.exact).map(s => s.value), ] + const matches = getMatches(note.content, stringsToRegex(foundWords)) const resultNote: ResultNote = { score: result.score, @@ -307,6 +326,7 @@ export async function addToIndex(file: TAbstractFile): Promise { path: file.path, mtime: file.stat.mtime, + tags: getTagsFromMetadata(metadata), aliases: getAliasesFromMetadata(metadata).join(''), headings1: metadata ? extractHeadingsFromCache(metadata, 1).join(' ') diff --git a/src/types.d.ts b/src/types.d.ts index ff21c9a..c29e77a 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -7,6 +7,7 @@ declare module 'obsidian' { interface FrontMatterCache { aliases?: string[] | string + tags?: string[] | string } interface ViewState { diff --git a/src/utils.ts b/src/utils.ts index 3b1748c..ba9aefc 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -144,6 +144,20 @@ export function getAliasesFromMetadata( .filter(s => !!s) } +export function getTagsFromMetadata(metadata: CachedMetadata | null): string[] { + const arrOrString = metadata?.frontmatter?.tags ?? [] + const fromFrontMatter = ( + Array.isArray(arrOrString) ? arrOrString : arrOrString.split(',') + ) + .map(s => (s ? s.trim() : s)) + .filter(s => !!s) + const fromBody = (metadata?.tags ?? []).map(t => t.tag) + + return [...fromFrontMatter, ...fromBody].map(t => + t[0] !== '#' ? '#' + t : t, + ) +} + /** * https://stackoverflow.com/a/37511463 */