Fixed #48 - Highly favor tags in search results
This commit is contained in:
@@ -27,6 +27,7 @@ export type IndexedNote = {
|
|||||||
|
|
||||||
content: string
|
content: string
|
||||||
aliases: string
|
aliases: string
|
||||||
|
tags: string[],
|
||||||
headings1: string
|
headings1: string
|
||||||
headings2: string
|
headings2: string
|
||||||
headings3: string
|
headings3: string
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Notice, TAbstractFile, TFile } from 'obsidian'
|
import { Notice, TAbstractFile, TFile } from 'obsidian'
|
||||||
import MiniSearch, { type SearchResult } from 'minisearch'
|
import MiniSearch, { type Options, type SearchResult } from 'minisearch'
|
||||||
import {
|
import {
|
||||||
chsRegex,
|
chsRegex,
|
||||||
SPACE_OR_PUNCTUATION,
|
SPACE_OR_PUNCTUATION,
|
||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
extractHeadingsFromCache,
|
extractHeadingsFromCache,
|
||||||
getAliasesFromMetadata,
|
getAliasesFromMetadata,
|
||||||
|
getTagsFromMetadata,
|
||||||
removeDiacritics,
|
removeDiacritics,
|
||||||
stringsToRegex,
|
stringsToRegex,
|
||||||
stripMarkdownCharacters,
|
stripMarkdownCharacters,
|
||||||
@@ -51,7 +52,7 @@ const tokenize = (text: string): string[] => {
|
|||||||
* and adds all the notes to the index
|
* and adds all the notes to the index
|
||||||
*/
|
*/
|
||||||
export async function initGlobalSearchIndex(): Promise<void> {
|
export async function initGlobalSearchIndex(): Promise<void> {
|
||||||
const options = {
|
const options: Options<IndexedNote> = {
|
||||||
tokenize,
|
tokenize,
|
||||||
processTerm: (term: string) =>
|
processTerm: (term: string) =>
|
||||||
(settings.ignoreDiacritics ? removeDiacritics(term) : term).toLowerCase(),
|
(settings.ignoreDiacritics ? removeDiacritics(term) : term).toLowerCase(),
|
||||||
@@ -64,6 +65,7 @@ export async function initGlobalSearchIndex(): Promise<void> {
|
|||||||
'headings2',
|
'headings2',
|
||||||
'headings3',
|
'headings3',
|
||||||
],
|
],
|
||||||
|
storeFields: ['tags'],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -234,6 +236,18 @@ export async function getSuggestions(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
results = results.slice(0, 50)
|
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
|
// Map the raw results to get usable suggestions
|
||||||
@@ -243,6 +257,10 @@ export async function getSuggestions(
|
|||||||
throw new Error(`Note "${result.id}" not indexed`)
|
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,
|
// Clean search matches that match quoted expressions,
|
||||||
// and inject those expressions instead
|
// and inject those expressions instead
|
||||||
const foundWords = [
|
const foundWords = [
|
||||||
@@ -251,6 +269,7 @@ export async function getSuggestions(
|
|||||||
),
|
),
|
||||||
...query.segments.filter(s => s.exact).map(s => s.value),
|
...query.segments.filter(s => s.exact).map(s => s.value),
|
||||||
]
|
]
|
||||||
|
|
||||||
const matches = getMatches(note.content, stringsToRegex(foundWords))
|
const matches = getMatches(note.content, stringsToRegex(foundWords))
|
||||||
const resultNote: ResultNote = {
|
const resultNote: ResultNote = {
|
||||||
score: result.score,
|
score: result.score,
|
||||||
@@ -307,6 +326,7 @@ export async function addToIndex(file: TAbstractFile): Promise<void> {
|
|||||||
path: file.path,
|
path: file.path,
|
||||||
mtime: file.stat.mtime,
|
mtime: file.stat.mtime,
|
||||||
|
|
||||||
|
tags: getTagsFromMetadata(metadata),
|
||||||
aliases: getAliasesFromMetadata(metadata).join(''),
|
aliases: getAliasesFromMetadata(metadata).join(''),
|
||||||
headings1: metadata
|
headings1: metadata
|
||||||
? extractHeadingsFromCache(metadata, 1).join(' ')
|
? extractHeadingsFromCache(metadata, 1).join(' ')
|
||||||
|
|||||||
1
src/types.d.ts
vendored
1
src/types.d.ts
vendored
@@ -7,6 +7,7 @@ declare module 'obsidian' {
|
|||||||
|
|
||||||
interface FrontMatterCache {
|
interface FrontMatterCache {
|
||||||
aliases?: string[] | string
|
aliases?: string[] | string
|
||||||
|
tags?: string[] | string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ViewState {
|
interface ViewState {
|
||||||
|
|||||||
14
src/utils.ts
14
src/utils.ts
@@ -144,6 +144,20 @@ export function getAliasesFromMetadata(
|
|||||||
.filter(s => !!s)
|
.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
|
* https://stackoverflow.com/a/37511463
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user