#25 - quoted expressions for Vault search ok

This commit is contained in:
Simon Cambier
2022-04-26 21:50:05 +02:00
parent fc9c677d42
commit cb7a11c7aa
4 changed files with 68 additions and 12 deletions

View File

@@ -40,14 +40,14 @@ onDestroy(() => {
eventBus.enable("vault") eventBus.enable("vault")
}) })
$: { $: (async () => {
if (searchQuery) { if (searchQuery) {
note = getSuggestions(searchQuery, { singleFilePath })[0] ?? null note = (await getSuggestions(searchQuery, { singleFilePath }))[0] ?? null
lastSearch = searchQuery lastSearch = searchQuery
} }
selectedIndex = 0 selectedIndex = 0
scrollIntoView() scrollIntoView()
} })()
$: { $: {
if (note) { if (note) {

View File

@@ -20,14 +20,14 @@ let searchQuery: string
let resultNotes: ResultNote[] = [] let resultNotes: ResultNote[] = []
$: selectedNote = resultNotes[selectedIndex] $: selectedNote = resultNotes[selectedIndex]
$: { $: (async() => {
if (searchQuery) { if (searchQuery) {
resultNotes = getSuggestions(searchQuery) resultNotes = await getSuggestions(searchQuery)
lastSearch = searchQuery lastSearch = searchQuery
} }
selectedIndex = 0 selectedIndex = 0
scrollIntoView() scrollIntoView()
} })()
onMount(() => { onMount(() => {
searchQuery = lastSearch searchQuery = lastSearch

View File

@@ -6,7 +6,13 @@ import {
type ResultNote, type ResultNote,
type SearchMatch, type SearchMatch,
} from './globals' } from './globals'
import { extractHeadingsFromCache, stringsToRegex, wait } from './utils' import {
extractHeadingsFromCache,
splitQuotes,
stringsToRegex,
stripMarkdownCharacters,
wait,
} from './utils'
let minisearchInstance: MiniSearch<IndexedNote> let minisearchInstance: MiniSearch<IndexedNote>
@@ -57,9 +63,9 @@ export async function initGlobalSearchIndex(): Promise<void> {
* @param query * @param query
* @returns * @returns
*/ */
function search(query: string): SearchResult[] { async function search(query: string): Promise<SearchResult[]> {
if (!query) return [] if (!query) return []
return minisearchInstance.search(query, { let results = minisearchInstance.search(query, {
prefix: true, prefix: true,
fuzzy: term => (term.length > 4 ? 0.2 : false), fuzzy: term => (term.length > 4 ? 0.2 : false),
combineWith: 'AND', combineWith: 'AND',
@@ -70,6 +76,17 @@ function search(query: string): SearchResult[] {
headings3: 1.1, headings3: 1.1,
}, },
}) })
const quoted = splitQuotes(query.toLowerCase())
if (quoted.length) {
results = results.filter(r => {
const content = stripMarkdownCharacters(
indexedNotes[r.id]?.content ?? '',
).toLowerCase()
return quoted.every(q => content.includes(q))
})
}
return results
} }
/** /**
@@ -96,12 +113,12 @@ export function getMatches(text: string, reg: RegExp): SearchMatch[] {
* @param options * @param options
* @returns * @returns
*/ */
export function getSuggestions( export async function getSuggestions(
query: string, query: string,
options?: Partial<{ singleFilePath: string | null }>, options?: Partial<{ singleFilePath: string | null }>,
): ResultNote[] { ): Promise<ResultNote[]> {
// Get the raw results // Get the raw results
let results = search(query) let results = await search(query)
if (!results.length) return [] if (!results.length) return []
// Either keep the 50 first results, // Either keep the 50 first results,

View File

@@ -97,3 +97,42 @@ export function makeExcerpt(content: string, offset: number): string {
} }
return escapeHTML(content) return escapeHTML(content)
} }
/**
* splits a string in words or "expressions in quotes"
* @param str
* @returns
*/
export function splitQuotes(str: string): string[] {
return str.match(/"(.*?)"/g)?.map(s => s.replace(/"/g, '')) ?? []
}
function mapAsync<T, U>(
array: T[],
callbackfn: (value: T, index: number, array: T[]) => Promise<U>,
): Promise<U[]> {
return Promise.all(array.map(callbackfn))
}
/**
* https://stackoverflow.com/a/53508547
* @param arr
* @param callback
* @returns
*/
export async function filterAsync<T>(
array: T[],
callbackfn: (value: T, index: number, array: T[]) => Promise<boolean>,
): Promise<T[]> {
const filterMap = await mapAsync(array, callbackfn)
return array.filter((value, index) => filterMap[index])
}
/**
* A simple function to strip bold and italic markdown chars from a string
* @param text
* @returns
*/
export function stripMarkdownCharacters(text: string): string {
return text.replace(/(\*|\_)+(.+?)(\*|\_)+/g, (match, p1, p2) => p2)
}