WIP refactor to take advantage of minisearch 6.0

This commit is contained in:
Simon Cambier
2022-11-25 08:28:50 +01:00
parent 2daa718bc9
commit dcef2d3719
10 changed files with 172 additions and 97 deletions

View File

@@ -6,6 +6,10 @@ import { minisearchOptions } from './search/search-engine'
import { makeMD5 } from './tools/utils' import { makeMD5 } from './tools/utils'
class CacheManager { class CacheManager {
/**
* @deprecated
* @private
*/
private liveDocuments: Map<string, IndexedDocument> = new Map() private liveDocuments: Map<string, IndexedDocument> = new Map()
/** /**
* Show an empty input field next time the user opens Omnisearch modal * Show an empty input field next time the user opens Omnisearch modal
@@ -39,6 +43,7 @@ class CacheManager {
/** /**
* Important: keep this method async for the day it _really_ becomes async. * Important: keep this method async for the day it _really_ becomes async.
* This will avoid a refactor. * This will avoid a refactor.
* @deprecated
* @param path * @param path
* @param note * @param note
*/ */
@@ -49,19 +54,22 @@ class CacheManager {
this.liveDocuments.set(path, note) this.liveDocuments.set(path, note)
} }
/**
* @deprecated
* @param key
*/
public deleteLiveDocument(key: string): void { public deleteLiveDocument(key: string): void {
this.liveDocuments.delete(key) this.liveDocuments.delete(key)
} }
/**
* @deprecated
* @param key
*/
public getLiveDocument(key: string): IndexedDocument | undefined { public getLiveDocument(key: string): IndexedDocument | undefined {
return this.liveDocuments.get(key) return this.liveDocuments.get(key)
} }
public isDocumentOutdated(file: TFile): boolean {
const indexedNote = this.getLiveDocument(file.path)
return !indexedNote || indexedNote.mtime !== file.stat.mtime
}
//#region Minisearch //#region Minisearch
public getDocumentsChecksum(documents: IndexedDocument[]): string { public getDocumentsChecksum(documents: IndexedDocument[]): string {
@@ -82,7 +90,6 @@ class CacheManager {
public async getMinisearchCache(): Promise<MiniSearch | null> { public async getMinisearchCache(): Promise<MiniSearch | null> {
// Retrieve documents and make their checksum // Retrieve documents and make their checksum
const cachedDocs = await database.documents.toArray() const cachedDocs = await database.documents.toArray()
const checksum = this.getDocumentsChecksum(cachedDocs.map(d => d.document))
// Add those documents in the live cache // Add those documents in the live cache
cachedDocs.forEach(doc => cachedDocs.forEach(doc =>
@@ -91,13 +98,6 @@ class CacheManager {
// Retrieve the search cache, and verify the checksum // Retrieve the search cache, and verify the checksum
const cachedIndex = (await database.minisearch.toArray())[0] const cachedIndex = (await database.minisearch.toArray())[0]
if (cachedIndex?.checksum !== checksum) {
console.warn("Omnisearch - Cache - Checksums don't match, clearing cache")
// Invalid (or null) cache, clear everything
await database.minisearch.clear()
await database.documents.clear()
return null
}
try { try {
return MiniSearch.loadJS(cachedIndex.data, minisearchOptions) return MiniSearch.loadJS(cachedIndex.data, minisearchOptions)
@@ -116,7 +116,7 @@ class CacheManager {
* @param documents * @param documents
*/ */
public async getDiffDocuments(documents: IndexedDocument[]): Promise<{ public async getDiffDocuments(documents: IndexedDocument[]): Promise<{
toDelete: IndexedDocument[] toDelete: string[]
toAdd: IndexedDocument[] toAdd: IndexedDocument[]
toUpdate: { oldDoc: IndexedDocument; newDoc: IndexedDocument }[] toUpdate: { oldDoc: IndexedDocument; newDoc: IndexedDocument }[]
}> { }> {
@@ -128,7 +128,7 @@ class CacheManager {
// present in `cachedDocs` but not in `documents` // present in `cachedDocs` but not in `documents`
const toDelete = cachedDocs const toDelete = cachedDocs
.filter(c => !documents.find(d => d.path === c.path)) .filter(c => !documents.find(d => d.path === c.path))
.map(d => d.document) .map(d => d.path)
// toUpdate: same path, but different mtime // toUpdate: same path, but different mtime
const toUpdate = cachedDocs const toUpdate = cachedDocs
@@ -158,7 +158,7 @@ class CacheManager {
// Delete // Delete
// console.log(`Omnisearch - Cache - Will delete ${toDelete.length} documents`) // console.log(`Omnisearch - Cache - Will delete ${toDelete.length} documents`)
await database.documents.bulkDelete(toDelete.map(o => o.path)) await database.documents.bulkDelete(toDelete)
// Add // Add
// console.log(`Omnisearch - Cache - Will add ${toAdd.length} documents`) // console.log(`Omnisearch - Cache - Will add ${toAdd.length} documents`)

View File

@@ -6,7 +6,7 @@
import { eventBus, IndexingStep, type ResultNote } from 'src/globals' import { eventBus, IndexingStep, type ResultNote } from 'src/globals'
import { createNote, openNote } from 'src/tools/notes' import { createNote, openNote } from 'src/tools/notes'
import { SearchEngine } from 'src/search/search-engine' import { SearchEngine } from 'src/search/search-engine'
import { getCtrlKeyLabel, getExtension, loopIndex } from 'src/tools/utils' import { getCtrlKeyLabel, getExtension, isFilePDF, loopIndex } from 'src/tools/utils'
import { import {
OmnisearchInFileModal, OmnisearchInFileModal,
type OmnisearchVaultModal, type OmnisearchVaultModal,
@@ -189,7 +189,7 @@
function switchToInFileModal(): void { function switchToInFileModal(): void {
// Do nothing if the selectedNote is a PDF, // Do nothing if the selectedNote is a PDF,
// or if there is 0 match (e.g indexing in progress) // or if there is 0 match (e.g indexing in progress)
if (selectedNote?.path.endsWith('.pdf') || !selectedNote?.matches.length) { if (isFilePDF(selectedNote?.path) || !selectedNote?.matches.length) {
return return
} }

View File

@@ -21,6 +21,7 @@
// @ts-ignore // @ts-ignore
const file = app.vault.getFiles().find(f => f.path === note.path) const file = app.vault.getFiles().find(f => f.path === note.path)
if (file) { if (file) {
// @ts-ignore
imagePath = app.vault.getResourcePath(file) imagePath = app.vault.getResourcePath(file)
} }
} }

View File

@@ -32,12 +32,26 @@ export class OmnisearchCache extends Dexie {
//#region Table declarations //#region Table declarations
documents!: Dexie.Table< documents!: Dexie.Table<
{ path: string; mtime: number; document: IndexedDocument }, {
path: string
mtime: number
/**
* @deprecated
*/
document: IndexedDocument
},
string string
> >
searchHistory!: Dexie.Table<{ id?: number; query: string }, number> searchHistory!: Dexie.Table<{ id?: number; query: string }, number>
minisearch!: Dexie.Table< minisearch!: Dexie.Table<
{ date: string; checksum: string; data: AsPlainObject }, {
date: string
/**
* @deprecated
*/
checksum: string
data: AsPlainObject
},
string string
> >

View File

@@ -4,14 +4,13 @@ import {
getAliasesFromMetadata, getAliasesFromMetadata,
getTagsFromMetadata, getTagsFromMetadata,
isFileImage, isFileImage,
isFilePDF,
isFilePlaintext, isFilePlaintext,
removeDiacritics, removeDiacritics,
} from './tools/utils' } from './tools/utils'
import * as NotesIndex from './notes-index'
import type { TFile } from 'obsidian' import type { TFile } from 'obsidian'
import type { IndexedDocument } from './globals' import type { IndexedDocument } from './globals'
import { getNonExistingNotes } from './tools/notes' import { getImageText, getPdfText } from 'obsidian-text-extract'
import { getPdfText, getImageText } from 'obsidian-text-extract'
/** /**
* Return all plaintext files as IndexedDocuments * Return all plaintext files as IndexedDocuments
@@ -20,9 +19,9 @@ export async function getPlainTextFiles(): Promise<IndexedDocument[]> {
const allFiles = app.vault.getFiles().filter(f => isFilePlaintext(f.path)) const allFiles = app.vault.getFiles().filter(f => isFilePlaintext(f.path))
const data: IndexedDocument[] = [] const data: IndexedDocument[] = []
for (const file of allFiles) { for (const file of allFiles) {
const doc = await fileToIndexedDocument(file) const doc = await getIndexedDocument(file.path)
data.push(doc) data.push(doc)
await cacheManager.updateLiveDocument(file.path, doc) // await cacheManager.updateLiveDocument(file.path, doc)
} }
return data return data
} }
@@ -31,7 +30,7 @@ export async function getPlainTextFiles(): Promise<IndexedDocument[]> {
* Return all PDFs as IndexedDocuments. * Return all PDFs as IndexedDocuments.
*/ */
export async function getPDFAsDocuments(): Promise<IndexedDocument[]> { export async function getPDFAsDocuments(): Promise<IndexedDocument[]> {
const files = app.vault.getFiles().filter(f => f.path.endsWith('.pdf')) const files = app.vault.getFiles().filter(f => isFilePDF(f.path))
return await getBinaryFiles(files) return await getBinaryFiles(files)
} }
@@ -49,8 +48,8 @@ async function getBinaryFiles(files: TFile[]): Promise<IndexedDocument[]> {
for (const file of files) { for (const file of files) {
input.push( input.push(
new Promise(async (resolve, reject) => { new Promise(async (resolve, reject) => {
const doc = await fileToIndexedDocument(file) const doc = await getIndexedDocument(file.path)
await cacheManager.updateLiveDocument(file.path, doc) // await cacheManager.updateLiveDocument(file.path, doc)
data.push(doc) data.push(doc)
return resolve(null) return resolve(null)
}) })
@@ -60,37 +59,34 @@ async function getBinaryFiles(files: TFile[]): Promise<IndexedDocument[]> {
return data return data
} }
/** export async function getIndexedDocument(
* Convert a file into an IndexedDocument. path: string
* Will use the cache if possible.
*/
export async function fileToIndexedDocument(
file: TFile
): Promise<IndexedDocument> { ): Promise<IndexedDocument> {
const file = app.vault.getFiles().find(f => f.path === path)
if (!file) throw new Error(`Invalid file path: "${path}"`)
let content: string let content: string
if (isFilePlaintext(file.path)) { if (isFilePlaintext(path)) {
content = await app.vault.cachedRead(file) content = await app.vault.cachedRead(file)
} else if (file.path.endsWith('.pdf')) { } else if (isFilePDF(path)) {
content = await getPdfText(file) content = await getPdfText(file)
} else if (isFileImage(file.path)) { } else if (isFileImage(file.path)) {
content = await getImageText(file) content = await getImageText(file)
} else { } else {
throw new Error('Invalid file: ' + file.path) throw new Error('Invalid file format: ' + file.path)
} }
content = removeDiacritics(content) content = removeDiacritics(content)
const metadata = app.metadataCache.getFileCache(file) const metadata = app.metadataCache.getFileCache(file)
// Look for links that lead to non-existing files, // Look for links that lead to non-existing files,
// and add them to the index. // and add them to the index.
if (metadata) { if (metadata) {
// FIXME: https://github.com/scambier/obsidian-omnisearch/issues/129 // // FIXME: https://github.com/scambier/obsidian-omnisearch/issues/129
const nonExisting = getNonExistingNotes(file, metadata) // const nonExisting = getNonExistingNotes(file, metadata)
for (const name of nonExisting.filter( // for (const name of nonExisting.filter(
o => !cacheManager.getLiveDocument(o) // o => !cacheManager.getLiveDocument(o)
)) { // )) {
NotesIndex.addNonExistingToIndex(name, file.path) // NotesIndex.addNonExistingToIndex(name, file.path)
} // }
// EXCALIDRAW // EXCALIDRAW
// Remove the json code // Remove the json code
@@ -117,3 +113,61 @@ export async function fileToIndexedDocument(
headings3: metadata ? extractHeadingsFromCache(metadata, 3).join(' ') : '', headings3: metadata ? extractHeadingsFromCache(metadata, 3).join(' ') : '',
} }
} }
/**
* Convert a file into an IndexedDocument.
* Will use the cache if possible.
*/
// async function fileToIndexedDocument(
// file: TFile
// ): Promise<IndexedDocument> {
// let content: string
// if (isFilePlaintext(file.path)) {
// content = await app.vault.cachedRead(file)
// } else if (isFilePDF(file.path)) {
// content = await getPdfText(file)
// } else if (isFileImage(file.path)) {
// content = await getImageText(file)
// } else {
// throw new Error('Invalid file: ' + file.path)
// }
//
// content = removeDiacritics(content)
// const metadata = app.metadataCache.getFileCache(file)
//
// // Look for links that lead to non-existing files,
// // and add them to the index.
// if (metadata) {
// // FIXME: https://github.com/scambier/obsidian-omnisearch/issues/129
// const nonExisting = getNonExistingNotes(file, metadata)
// for (const name of nonExisting.filter(
// o => !cacheManager.getLiveDocument(o)
// )) {
// NotesIndex.addNonExistingToIndex(name, file.path)
// }
//
// // EXCALIDRAW
// // Remove the json code
// if (metadata.frontmatter?.['excalidraw-plugin']) {
// const comments =
// metadata.sections?.filter(s => s.type === 'comment') ?? []
// for (const { start, end } of comments.map(c => c.position)) {
// content =
// content.substring(0, start.offset - 1) + content.substring(end.offset)
// }
// }
// }
//
// return {
// basename: removeDiacritics(file.basename),
// content,
// path: file.path,
// mtime: file.stat.mtime,
//
// tags: getTagsFromMetadata(metadata),
// aliases: getAliasesFromMetadata(metadata).join(''),
// headings1: metadata ? extractHeadingsFromCache(metadata, 1).join(' ') : '',
// headings2: metadata ? extractHeadingsFromCache(metadata, 2).join(' ') : '',
// headings3: metadata ? extractHeadingsFromCache(metadata, 3).join(' ') : '',
// }
// }

View File

@@ -37,6 +37,7 @@ export type IndexedDocument = {
headings2: string headings2: string
headings3: string headings3: string
// TODO: reimplement this
doesNotExist?: boolean doesNotExist?: boolean
parent?: string parent?: string
} }

View File

@@ -8,10 +8,11 @@ import { loadSettings, settings, SettingsTab, showExcerpt } from './settings'
import { eventBus, EventNames, IndexingStep } from './globals' import { eventBus, EventNames, IndexingStep } from './globals'
import api from './tools/api' import api from './tools/api'
import { isFilePlaintext, wait } from './tools/utils' import { isFilePlaintext, wait } from './tools/utils'
import * as NotesIndex from './notes-index'
import * as FileLoader from './file-loader' import * as FileLoader from './file-loader'
import { OmnisearchCache } from './database' import { OmnisearchCache } from './database'
import { cacheManager } from './cache-manager' import { cacheManager } from './cache-manager'
import * as NotesIndex from './notes-index'
import { addToIndexAndMemCache } from "./notes-index";
export default class OmnisearchPlugin extends Plugin { export default class OmnisearchPlugin extends Plugin {
private ribbonButton?: HTMLElement private ribbonButton?: HTMLElement
@@ -186,21 +187,15 @@ async function populateIndex(): Promise<void> {
// Add // Add
await engine.addAllToMinisearch(diffDocs.toAdd) await engine.addAllToMinisearch(diffDocs.toAdd)
diffDocs.toAdd.forEach(doc =>
cacheManager.updateLiveDocument(doc.path, doc)
)
// Delete // Delete
for (const [i, doc] of diffDocs.toDelete.entries()) { for (const pathToDel of diffDocs.toDelete) {
await wait(0) NotesIndex.removeFromIndex(pathToDel)
engine.removeFromMinisearch(doc)
cacheManager.deleteLiveDocument(doc.path)
} }
// Update (delete + add) // Update (delete + add)
diffDocs.toUpdate.forEach(({ oldDoc, newDoc }) => { diffDocs.toUpdate.forEach(({ oldDoc, newDoc }) => {
engine.removeFromMinisearch(oldDoc) NotesIndex.removeFromIndex(oldDoc.path)
cacheManager.updateLiveDocument(oldDoc.path, newDoc)
}) })
await engine.addAllToMinisearch(diffDocs.toUpdate.map(d => d.newDoc)) await engine.addAllToMinisearch(diffDocs.toUpdate.map(d => d.newDoc))
} }

View File

@@ -4,7 +4,9 @@ import { removeAnchors } from './tools/notes'
import { SearchEngine } from './search/search-engine' import { SearchEngine } from './search/search-engine'
import { cacheManager } from './cache-manager' import { cacheManager } from './cache-manager'
import type { IndexedDocument } from './globals' import type { IndexedDocument } from './globals'
import { fileToIndexedDocument } from './file-loader' import { getIndexedDocument } from "./file-loader";
const indexedList: Set<string> = new Set()
/** /**
* Adds a file to the search index * Adds a file to the search index
@@ -18,21 +20,14 @@ export async function addToIndexAndMemCache(
return return
} }
// Check if the file was already indexed as non-existent.
// If so, remove it from the index, and add it again as a real note.
if (cacheManager.getLiveDocument(file.path)?.doesNotExist) {
removeFromIndex(file.path)
}
try { try {
if (cacheManager.getLiveDocument(file.path)) { if (indexedList.has(file.path)) {
throw new Error(`${file.basename} is already indexed`) throw new Error(`${file.basename} is already indexed`)
} }
// Make the document and index it // Make the document and index it
const note = await fileToIndexedDocument(file) SearchEngine.getEngine().addSingleToMinisearch(file.path)
SearchEngine.getEngine().addSingleToMinisearch(note) indexedList.add(file.path)
await cacheManager.updateLiveDocument(note.path, note)
} catch (e) { } catch (e) {
// console.trace('Error while indexing ' + file.basename) // console.trace('Error while indexing ' + file.basename)
console.error(e) console.error(e)
@@ -65,8 +60,7 @@ export function addNonExistingToIndex(name: string, parent: string): void {
doesNotExist: true, doesNotExist: true,
parent, parent,
} }
SearchEngine.getEngine().addSingleToMinisearch(note) SearchEngine.getEngine().addSingleToMinisearch(note.path)
cacheManager.updateLiveDocument(filename, note)
} }
/** /**
@@ -77,10 +71,8 @@ export function removeFromIndex(path: string): void {
console.info(`"${path}" is not an indexable file`) console.info(`"${path}" is not an indexable file`)
return return
} }
const note = cacheManager.getLiveDocument(path) if (indexedList.has(path)) {
if (note) { SearchEngine.getEngine().removeFromMinisearch(path)
SearchEngine.getEngine().removeFromMinisearch(note)
cacheManager.deleteLiveDocument(path)
// FIXME: only remove non-existing notes if they don't have another parent // FIXME: only remove non-existing notes if they don't have another parent
// cacheManager // cacheManager

View File

@@ -2,10 +2,10 @@ import MiniSearch, { type Options, type SearchResult } from 'minisearch'
import { import {
chsRegex, chsRegex,
type IndexedDocument, type IndexedDocument,
IndexingStep,
type ResultNote, type ResultNote,
type SearchMatch, type SearchMatch,
SPACE_OR_PUNCTUATION, SPACE_OR_PUNCTUATION,
IndexingStep,
} from '../globals' } from '../globals'
import { import {
removeDiacritics, removeDiacritics,
@@ -17,8 +17,9 @@ import { settings } from '../settings'
import { cacheManager } from '../cache-manager' import { cacheManager } from '../cache-manager'
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
import { Notice } from 'obsidian' import { Notice } from 'obsidian'
import { getIndexedDocument } from '../file-loader'
let previousResults: ResultNote[] = [] let previousResults: SearchResult[] = []
const tokenize = (text: string): string[] => { const tokenize = (text: string): string[] => {
const tokens = text.split(SPACE_OR_PUNCTUATION) const tokens = text.split(SPACE_OR_PUNCTUATION)
@@ -102,7 +103,10 @@ export class SearchEngine {
query: Query, query: Query,
options: { prefixLength: number } options: { prefixLength: number }
): Promise<SearchResult[]> { ): Promise<SearchResult[]> {
if (!query.segmentsToStr()) return [] if (query.isEmpty()) {
previousResults = []
return []
}
let results = this.minisearch.search(query.segmentsToStr(), { let results = this.minisearch.search(query.segmentsToStr(), {
prefix: term => term.length >= options.prefixLength, prefix: term => term.length >= options.prefixLength,
@@ -116,6 +120,7 @@ export class SearchEngine {
headings3: settings.weightH3, headings3: settings.weightH3,
}, },
}) })
if (!results.length) return previousResults
// Downrank files that are in Obsidian's excluded list // Downrank files that are in Obsidian's excluded list
if (settings.respectExcluded) { if (settings.respectExcluded) {
@@ -124,19 +129,23 @@ export class SearchEngine {
app.metadataCache.isUserIgnored && app.metadataCache.isUserIgnored &&
app.metadataCache.isUserIgnored(result.id) app.metadataCache.isUserIgnored(result.id)
) { ) {
result.score /= 10 // TODO: make this value configurable or toggleable? result.score /= 10
} }
}) })
} }
const documents = await Promise.all(
results.map(async result => await getIndexedDocument(result.id))
)
// If the search query contains quotes, filter out results that don't have the exact match // If the search query contains quotes, filter out results that don't have the exact match
const exactTerms = query.getExactTerms() const exactTerms = query.getExactTerms()
if (exactTerms.length) { if (exactTerms.length) {
results = results.filter(r => { results = results.filter(r => {
const title = const document = documents.find(d => d.path === r.id)
cacheManager.getLiveDocument(r.id)?.path.toLowerCase() ?? '' const title = document?.path.toLowerCase() ?? ''
const content = stripMarkdownCharacters( const content = stripMarkdownCharacters(
cacheManager.getLiveDocument(r.id)?.content ?? '' document?.content ?? ''
).toLowerCase() ).toLowerCase()
return exactTerms.every(q => content.includes(q) || title.includes(q)) return exactTerms.every(q => content.includes(q) || title.includes(q))
}) })
@@ -147,16 +156,22 @@ export class SearchEngine {
if (exclusions.length) { if (exclusions.length) {
results = results.filter(r => { results = results.filter(r => {
const content = stripMarkdownCharacters( const content = stripMarkdownCharacters(
cacheManager.getLiveDocument(r.id)?.content ?? '' documents.find(d => d.path === r.id)?.content ?? ''
).toLowerCase() ).toLowerCase()
return exclusions.every(q => !content.includes(q.value)) return exclusions.every(q => !content.includes(q.value))
}) })
} }
// FIXME: // FIXME:
// Dedupe results - clutch for https://github.com/scambier/obsidian-omnisearch/issues/129 // Dedupe results - clutch for https://github.com/scambier/obsidian-omnisearch/issues/129
return results.filter( results = results
.filter(
(result, index, arr) => arr.findIndex(t => t.id === result.id) === index (result, index, arr) => arr.findIndex(t => t.id === result.id) === index
) )
.slice(0, 50)
previousResults = results
return results
} }
/** /**
@@ -196,10 +211,6 @@ export class SearchEngine {
query: Query, query: Query,
options?: Partial<{ singleFilePath: string | null }> options?: Partial<{ singleFilePath: string | null }>
): Promise<ResultNote[]> { ): Promise<ResultNote[]> {
if (query.isEmpty()) {
previousResults = []
return []
}
// Get the raw results // Get the raw results
let results: SearchResult[] let results: SearchResult[]
if (settings.simpleSearch) { if (settings.simpleSearch) {
@@ -207,7 +218,6 @@ export class SearchEngine {
} else { } else {
results = await this.search(query, { prefixLength: 3 }) results = await this.search(query, { prefixLength: 3 })
} }
if (!results.length) return previousResults
// Extract tags from the query // Extract tags from the query
const tags = query.segments const tags = query.segments
@@ -233,9 +243,14 @@ export class SearchEngine {
} }
} }
// TODO: this already called in search(), pass each document in its SearchResult instead?
const documents = await Promise.all(
results.map(async result => await getIndexedDocument(result.id))
)
// Map the raw results to get usable suggestions // Map the raw results to get usable suggestions
const resultNotes = results.map(result => { const resultNotes = results.map(result => {
let note = cacheManager.getLiveDocument(result.id) let note = documents.find(d => d.path === result.id)
if (!note) { if (!note) {
// throw new Error(`Omnisearch - Note "${result.id}" not indexed`) // throw new Error(`Omnisearch - Note "${result.id}" not indexed`)
console.warn(`Omnisearch - Note "${result.id}" not in the live cache`) console.warn(`Omnisearch - Note "${result.id}" not in the live cache`)
@@ -278,7 +293,6 @@ export class SearchEngine {
} }
return resultNote return resultNote
}) })
previousResults = resultNotes
return resultNotes return resultNotes
} }
@@ -291,12 +305,12 @@ export class SearchEngine {
await this.minisearch.addAllAsync(documents, { chunkSize }) await this.minisearch.addAllAsync(documents, { chunkSize })
} }
public addSingleToMinisearch(document: IndexedDocument): void { public addSingleToMinisearch(path: string): void {
this.minisearch.add(document) getIndexedDocument(path).then(doc => this.minisearch.add(doc))
} }
public removeFromMinisearch(document: IndexedDocument): void { public removeFromMinisearch(path: string): void {
this.minisearch.remove(document) this.minisearch.discard(path)
} }
// #endregion // #endregion

View File

@@ -1,9 +1,9 @@
import { import {
type CachedMetadata, type CachedMetadata,
Notice,
Platform,
getAllTags, getAllTags,
Notice,
parseFrontMatterAliases, parseFrontMatterAliases,
Platform,
} from 'obsidian' } from 'obsidian'
import type { SearchMatch } from '../globals' import type { SearchMatch } from '../globals'
import { import {
@@ -207,8 +207,8 @@ export function getCtrlKeyLabel(): 'ctrl' | '⌘' {
export function isFileIndexable(path: string): boolean { export function isFileIndexable(path: string): boolean {
return ( return (
(settings.PDFIndexing && path.endsWith('.pdf')) ||
isFilePlaintext(path) || isFilePlaintext(path) ||
(settings.PDFIndexing && isFilePDF(path)) ||
(settings.imagesIndexing && isFileImage(path)) (settings.imagesIndexing && isFileImage(path))
) )
} }
@@ -219,6 +219,10 @@ export function isFileImage(path: string): boolean {
) )
} }
export function isFilePDF(path: string): boolean {
return path.endsWith('.pdf')
}
export function isFilePlaintext(path: string): boolean { export function isFilePlaintext(path: string): boolean {
return getPlaintextExtensions().some(t => path.endsWith(`.${t}`)) return getPlaintextExtensions().some(t => path.endsWith(`.${t}`))
} }