Merge branch 'develop'
This commit is contained in:
@@ -7,7 +7,6 @@ module.exports = {
|
|||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
arrowParens: 'avoid',
|
arrowParens: 'avoid',
|
||||||
bracketSameLine: true,
|
bracketSameLine: true,
|
||||||
svelteStrictMode: true,
|
|
||||||
svelteBracketNewLine: false,
|
svelteBracketNewLine: false,
|
||||||
svelteAllowShorthand: true,
|
svelteAllowShorthand: true,
|
||||||
svelteIndentScriptAndStyle: true,
|
svelteIndentScriptAndStyle: true,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { build } from 'esbuild'
|
import esbuild from 'esbuild'
|
||||||
import sveltePlugin from 'esbuild-svelte'
|
|
||||||
import sveltePreprocess from 'svelte-preprocess'
|
|
||||||
import { copy } from 'esbuild-plugin-copy'
|
|
||||||
import process from 'process'
|
import process from 'process'
|
||||||
import builtins from 'builtin-modules'
|
import builtins from 'builtin-modules'
|
||||||
|
import esbuildSvelte from 'esbuild-svelte'
|
||||||
|
import { sveltePreprocess } from 'svelte-preprocess'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { copy } from 'esbuild-plugin-copy'
|
||||||
|
|
||||||
const banner = `/*
|
const banner = `/*
|
||||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||||
@@ -14,7 +14,7 @@ if you want to view the source, please visit the github repository of this plugi
|
|||||||
|
|
||||||
const prod = process.argv[2] === 'production'
|
const prod = process.argv[2] === 'production'
|
||||||
|
|
||||||
build({
|
const context = await esbuild.context({
|
||||||
banner: {
|
banner: {
|
||||||
js: banner,
|
js: banner,
|
||||||
},
|
},
|
||||||
@@ -24,54 +24,42 @@ build({
|
|||||||
'obsidian',
|
'obsidian',
|
||||||
'electron',
|
'electron',
|
||||||
'@codemirror/autocomplete',
|
'@codemirror/autocomplete',
|
||||||
'@codemirror/closebrackets',
|
|
||||||
'@codemirror/collab',
|
'@codemirror/collab',
|
||||||
'@codemirror/commands',
|
'@codemirror/commands',
|
||||||
'@codemirror/comment',
|
|
||||||
'@codemirror/fold',
|
|
||||||
'@codemirror/gutter',
|
|
||||||
'@codemirror/highlight',
|
|
||||||
'@codemirror/history',
|
|
||||||
'@codemirror/language',
|
'@codemirror/language',
|
||||||
'@codemirror/lint',
|
'@codemirror/lint',
|
||||||
'@codemirror/matchbrackets',
|
|
||||||
'@codemirror/panel',
|
|
||||||
'@codemirror/rangeset',
|
|
||||||
'@codemirror/rectangular-selection',
|
|
||||||
'@codemirror/search',
|
'@codemirror/search',
|
||||||
'@codemirror/state',
|
'@codemirror/state',
|
||||||
'@codemirror/stream-parser',
|
|
||||||
'@codemirror/text',
|
|
||||||
'@codemirror/tooltip',
|
|
||||||
'@codemirror/view',
|
'@codemirror/view',
|
||||||
|
'@lezer/common',
|
||||||
|
'@lezer/highlight',
|
||||||
|
'@lezer/lr',
|
||||||
...builtins,
|
...builtins,
|
||||||
],
|
],
|
||||||
outfile: path.join('./dist', 'main.js'),
|
outfile: path.join('./dist', 'main.js'),
|
||||||
plugins: [
|
plugins: [
|
||||||
sveltePlugin({
|
esbuildSvelte({
|
||||||
|
compilerOptions: { css: 'injected' },
|
||||||
preprocess: sveltePreprocess(),
|
preprocess: sveltePreprocess(),
|
||||||
}),
|
}),
|
||||||
copy({
|
copy({
|
||||||
assets:{
|
assets:{
|
||||||
from: ['./assets/styles.css', 'manifest.json'],
|
from: ['manifest.json','./assets/styles.css'],
|
||||||
to: ['./'],
|
to: ['./']
|
||||||
},
|
}
|
||||||
}),
|
})
|
||||||
{
|
|
||||||
name: 'resolve-minisearch',
|
|
||||||
setup(build) {
|
|
||||||
build.onResolve({ filter: /^minisearch$/ }, () => {
|
|
||||||
return { path: path.resolve('node_modules/minisearch/src/MiniSearch.ts') };
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
watch: !prod,
|
|
||||||
target: 'chrome98',
|
target: 'chrome98',
|
||||||
logLevel: 'info',
|
logLevel: 'info',
|
||||||
sourcemap: prod ? false : 'inline',
|
sourcemap: prod ? false : 'inline',
|
||||||
treeShaking: true,
|
treeShaking: true,
|
||||||
minify: prod,
|
minify: prod,
|
||||||
legalComments: 'none',
|
})
|
||||||
}).catch(() => process.exit(1))
|
|
||||||
|
if (prod) {
|
||||||
|
await context.rebuild()
|
||||||
|
process.exit(0)
|
||||||
|
} else {
|
||||||
|
await context.watch()
|
||||||
|
}
|
||||||
|
|||||||
17
package.json
17
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "scambier.obsidian-search",
|
"name": "scambier.obsidian-search",
|
||||||
"version": "1.26.1",
|
"version": "1.27.0-beta.1",
|
||||||
"description": "A search engine for Obsidian",
|
"description": "A search engine for Obsidian",
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -24,19 +24,19 @@
|
|||||||
"@types/pako": "^2.0.3",
|
"@types/pako": "^2.0.3",
|
||||||
"babel-jest": "^27.5.1",
|
"babel-jest": "^27.5.1",
|
||||||
"builtin-modules": "^3.3.0",
|
"builtin-modules": "^3.3.0",
|
||||||
"esbuild": "0.14.0",
|
"esbuild": "0.17.19",
|
||||||
"esbuild-plugin-copy": "1.3.0",
|
"esbuild-plugin-copy": "1.3.0",
|
||||||
"esbuild-svelte": "0.7.1",
|
"esbuild-svelte": "^0.9.2",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
"obsidian": "1.7.2",
|
"obsidian": "1.7.2",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"prettier-plugin-svelte": "^2.10.1",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
"svelte": "^3.59.2",
|
"svelte": "^5.23.2",
|
||||||
"svelte-check": "^2.10.3",
|
"svelte-check": "^4.1.5",
|
||||||
"svelte-jester": "^2.3.2",
|
"svelte-jester": "^2.3.2",
|
||||||
"svelte-preprocess": "^4.10.7",
|
"svelte-preprocess": "^6.0.3",
|
||||||
"tslib": "2.3.1",
|
"tslib": "2.3.1",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^5.8.2",
|
||||||
"vite": "^3.2.11"
|
"vite": "^3.2.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -46,7 +46,8 @@
|
|||||||
"markdown-link-extractor": "^4.0.2",
|
"markdown-link-extractor": "^4.0.2",
|
||||||
"minisearch": "7.1.0",
|
"minisearch": "7.1.0",
|
||||||
"pure-md5": "^0.1.14",
|
"pure-md5": "^0.1.14",
|
||||||
"search-query-parser": "^1.6.0"
|
"search-query-parser": "^1.6.0",
|
||||||
|
"svelte-multiselect": "github:janosh/svelte-multiselect"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
824
pnpm-lock.yaml
generated
824
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -191,7 +191,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
We found 0 result for your search here.
|
We found 0 results for your search here.
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</ModalContainer>
|
</ModalContainer>
|
||||||
|
|||||||
@@ -30,27 +30,34 @@
|
|||||||
import type OmnisearchPlugin from '../main'
|
import type OmnisearchPlugin from '../main'
|
||||||
import LazyLoader from './lazy-loader/LazyLoader.svelte'
|
import LazyLoader from './lazy-loader/LazyLoader.svelte'
|
||||||
|
|
||||||
export let modal: OmnisearchVaultModal
|
let {
|
||||||
export let previousQuery: string | undefined
|
modal,
|
||||||
export let plugin: OmnisearchPlugin
|
previousQuery,
|
||||||
|
plugin,
|
||||||
|
}: {
|
||||||
|
modal: OmnisearchVaultModal
|
||||||
|
previousQuery?: string | undefined
|
||||||
|
plugin: OmnisearchPlugin
|
||||||
|
} = $props()
|
||||||
|
|
||||||
let selectedIndex = 0
|
let selectedIndex = $state(0)
|
||||||
let historySearchIndex = 0
|
let historySearchIndex = 0
|
||||||
let searchQuery: string | undefined
|
let searchQuery = $state(previousQuery ?? '')
|
||||||
let resultNotes: ResultNote[] = []
|
let resultNotes: ResultNote[] = $state([])
|
||||||
let query: Query
|
let query: Query
|
||||||
let indexingStepDesc = ''
|
let indexingStepDesc = $state('')
|
||||||
let searching = true
|
let searching = $state(true)
|
||||||
let refInput: InputSearch | undefined
|
let refInput: InputSearch | undefined
|
||||||
let openInNewPaneKey: string
|
let openInNewPaneKey: string = $state('')
|
||||||
let openInCurrentPaneKey: string
|
let openInCurrentPaneKey: string = $state('')
|
||||||
let createInNewPaneKey: string
|
let createInNewPaneKey: string = $state('')
|
||||||
let createInCurrentPaneKey: string
|
let createInCurrentPaneKey: string = $state('')
|
||||||
let openInNewLeafKey: string = getCtrlKeyLabel() + getAltKeyLabel() + ' ↵'
|
let openInNewLeafKey: string = `${getCtrlKeyLabel()} ${getAltKeyLabel()} ↵`
|
||||||
|
|
||||||
$: selectedNote = resultNotes[selectedIndex]
|
const selectedNote = $derived(resultNotes[selectedIndex])
|
||||||
$: searchQuery = searchQuery ?? previousQuery
|
|
||||||
$: if (plugin.settings.openInNewPane) {
|
$effect(() => {
|
||||||
|
if (plugin.settings.openInNewPane) {
|
||||||
openInNewPaneKey = '↵'
|
openInNewPaneKey = '↵'
|
||||||
openInCurrentPaneKey = getCtrlKeyLabel() + ' ↵'
|
openInCurrentPaneKey = getCtrlKeyLabel() + ' ↵'
|
||||||
createInNewPaneKey = 'Shift ↵'
|
createInNewPaneKey = 'Shift ↵'
|
||||||
@@ -61,13 +68,17 @@
|
|||||||
createInNewPaneKey = getCtrlKeyLabel() + ' Shift ↵'
|
createInNewPaneKey = getCtrlKeyLabel() + ' Shift ↵'
|
||||||
createInCurrentPaneKey = 'Shift ↵'
|
createInCurrentPaneKey = 'Shift ↵'
|
||||||
}
|
}
|
||||||
$: if (searchQuery) {
|
})
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (searchQuery) {
|
||||||
updateResultsDebounced()
|
updateResultsDebounced()
|
||||||
} else {
|
} else {
|
||||||
searching = false
|
searching = false
|
||||||
resultNotes = []
|
resultNotes = []
|
||||||
}
|
}
|
||||||
$: {
|
})
|
||||||
|
$effect(() => {
|
||||||
switch ($indexingStep) {
|
switch ($indexingStep) {
|
||||||
case IndexingStepType.LoadingCache:
|
case IndexingStepType.LoadingCache:
|
||||||
indexingStepDesc = 'Loading cache...'
|
indexingStepDesc = 'Loading cache...'
|
||||||
@@ -87,7 +98,7 @@
|
|||||||
indexingStepDesc = ''
|
indexingStepDesc = ''
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
eventBus.enable('vault')
|
eventBus.enable('vault')
|
||||||
@@ -305,17 +316,17 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<InputSearch
|
<InputSearch
|
||||||
bind:this="{refInput}"
|
bind:this={refInput}
|
||||||
plugin="{plugin}"
|
{plugin}
|
||||||
initialValue="{searchQuery}"
|
initialValue={searchQuery}
|
||||||
on:input="{e => (searchQuery = e.detail)}"
|
on:input={e => (searchQuery = e.detail)}
|
||||||
placeholder="Omnisearch - Vault">
|
placeholder="Omnisearch - Vault">
|
||||||
<div class="omnisearch-input-container__buttons">
|
<div class="omnisearch-input-container__buttons">
|
||||||
{#if plugin.settings.showCreateButton}
|
{#if plugin.settings.showCreateButton}
|
||||||
<button on:click="{onClickCreateNote}">Create note</button>
|
<button on:click={onClickCreateNote}>Create note</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if Platform.isMobile}
|
{#if Platform.isMobile}
|
||||||
<button on:click="{switchToInFileModal}">In-File search</button>
|
<button on:click={switchToInFileModal}>In-File search</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</InputSearch>
|
</InputSearch>
|
||||||
@@ -329,24 +340,24 @@
|
|||||||
<ModalContainer>
|
<ModalContainer>
|
||||||
{#each resultNotes as result, i}
|
{#each resultNotes as result, i}
|
||||||
<LazyLoader
|
<LazyLoader
|
||||||
height="{100}"
|
height={100}
|
||||||
offset="{500}"
|
offset={500}
|
||||||
keep="{true}"
|
keep={true}
|
||||||
fadeOption="{{ delay: 0, duration: 0 }}">
|
fadeOption={{ delay: 0, duration: 0 }}>
|
||||||
<ResultItemVault
|
<ResultItemVault
|
||||||
plugin="{plugin}"
|
{plugin}
|
||||||
selected="{i === selectedIndex}"
|
selected={i === selectedIndex}
|
||||||
note="{result}"
|
note={result}
|
||||||
on:mousemove="{_ => (selectedIndex = i)}"
|
on:mousemove={_ => (selectedIndex = i)}
|
||||||
on:click="{onClick}"
|
on:click={onClick}
|
||||||
on:auxclick="{evt => {
|
on:auxclick={evt => {
|
||||||
if (evt.button == 1) openNoteInNewPane()
|
if (evt.button == 1) openNoteInNewPane()
|
||||||
}}" />
|
}} />
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
{/each}
|
{/each}
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
{#if !resultNotes.length && searchQuery && !searching}
|
{#if !resultNotes.length && searchQuery && !searching}
|
||||||
We found 0 result for your search here.
|
We found 0 results for your search here.
|
||||||
{#if plugin.settings.simpleSearch && searchQuery
|
{#if plugin.settings.simpleSearch && searchQuery
|
||||||
.split(SPACE_OR_PUNCTUATION)
|
.split(SPACE_OR_PUNCTUATION)
|
||||||
.some(w => w.length < 3)}
|
.some(w => w.length < 3)}
|
||||||
@@ -408,7 +419,7 @@
|
|||||||
<span>to insert a link</span>
|
<span>to insert a link</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="prompt-instruction">
|
<div class="prompt-instruction">
|
||||||
<span class="prompt-instruction-command">Ctrl g</span>
|
<span class="prompt-instruction-command">{getCtrlKeyLabel()} g</span>
|
||||||
<span>to toggle excerpts</span>
|
<span>to toggle excerpts</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="prompt-instruction">
|
<div class="prompt-instruction">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ModalVault from './ModalVault.svelte'
|
|||||||
import ModalInFile from './ModalInFile.svelte'
|
import ModalInFile from './ModalInFile.svelte'
|
||||||
import { Action, eventBus, EventNames, isInputComposition } from '../globals'
|
import { Action, eventBus, EventNames, isInputComposition } from '../globals'
|
||||||
import type OmnisearchPlugin from '../main'
|
import type OmnisearchPlugin from '../main'
|
||||||
|
import { mount, unmount } from 'svelte'
|
||||||
|
|
||||||
abstract class OmnisearchModal extends Modal {
|
abstract class OmnisearchModal extends Modal {
|
||||||
protected constructor(plugin: OmnisearchPlugin) {
|
protected constructor(plugin: OmnisearchPlugin) {
|
||||||
@@ -119,7 +120,7 @@ abstract class OmnisearchModal extends Modal {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Open in background
|
// Open in background
|
||||||
this.scope.register(['Ctrl'], 'O', e => {
|
this.scope.register(['Mod'], 'O', e => {
|
||||||
if (!isInputComposition()) {
|
if (!isInputComposition()) {
|
||||||
// Check if the user is still typing
|
// Check if the user is still typing
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@@ -143,7 +144,7 @@ abstract class OmnisearchModal extends Modal {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Context
|
// Context
|
||||||
this.scope.register(['Ctrl'], 'G', _e => {
|
this.scope.register(['Mod'], 'G', _e => {
|
||||||
eventBus.emit(EventNames.ToggleExcerpts)
|
eventBus.emit(EventNames.ToggleExcerpts)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -170,7 +171,7 @@ export class OmnisearchVaultModal extends OmnisearchModal {
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
// Instantiate and display the Svelte component
|
// Instantiate and display the Svelte component
|
||||||
const cmp = new ModalVault({
|
const cmp = mount(ModalVault, {
|
||||||
target: this.modalEl,
|
target: this.modalEl,
|
||||||
props: {
|
props: {
|
||||||
plugin,
|
plugin,
|
||||||
@@ -178,10 +179,11 @@ export class OmnisearchVaultModal extends OmnisearchModal {
|
|||||||
previousQuery: query || selectedText || previous || '',
|
previousQuery: query || selectedText || previous || '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
this.onClose = () => {
|
this.onClose = () => {
|
||||||
// Since the component is manually created,
|
// Since the component is manually created,
|
||||||
// we also need to manually destroy it
|
// we also need to manually destroy it
|
||||||
cmp.$destroy()
|
unmount(cmp)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -196,7 +198,7 @@ export class OmnisearchInFileModal extends OmnisearchModal {
|
|||||||
) {
|
) {
|
||||||
super(plugin)
|
super(plugin)
|
||||||
|
|
||||||
const cmp = new ModalInFile({
|
const cmp = mount(ModalInFile, {
|
||||||
target: this.modalEl,
|
target: this.modalEl,
|
||||||
props: {
|
props: {
|
||||||
plugin,
|
plugin,
|
||||||
@@ -215,7 +217,7 @@ export class OmnisearchInFileModal extends OmnisearchModal {
|
|||||||
if (parent) {
|
if (parent) {
|
||||||
parent.containerEl.toggleVisibility(true)
|
parent.containerEl.toggleVisibility(true)
|
||||||
}
|
}
|
||||||
cmp.$destroy()
|
unmount(cmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/main.ts
13
src/main.ts
@@ -53,7 +53,7 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
public readonly searchHistory = new SearchHistory(this)
|
public readonly searchHistory = new SearchHistory(this)
|
||||||
|
|
||||||
private ribbonButton?: HTMLElement
|
private ribbonButton?: HTMLElement
|
||||||
private refreshIndexCallback?: () => void
|
private refreshIndexCallback?: (ev: FocusEvent) => any
|
||||||
|
|
||||||
constructor(app: App, manifest: PluginManifest) {
|
constructor(app: App, manifest: PluginManifest) {
|
||||||
super(app, manifest)
|
super(app, manifest)
|
||||||
@@ -116,10 +116,8 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
// Listeners to keep the search index up-to-date
|
// Listeners to keep the search index up-to-date
|
||||||
this.registerEvent(
|
this.registerEvent(
|
||||||
this.app.vault.on('create', file => {
|
this.app.vault.on('create', file => {
|
||||||
if (
|
if (!(file instanceof TFile)) return
|
||||||
file instanceof TFile &&
|
if (this.notesIndexer.isFileIndexable(file.path)) {
|
||||||
this.notesIndexer.isFileIndexable(file.path)
|
|
||||||
) {
|
|
||||||
logVerbose('Indexing new file', file.path)
|
logVerbose('Indexing new file', file.path)
|
||||||
searchEngine.addFromPaths([file.path])
|
searchEngine.addFromPaths([file.path])
|
||||||
this.embedsRepository.refreshEmbedsForNote(file.path)
|
this.embedsRepository.refreshEmbedsForNote(file.path)
|
||||||
@@ -128,6 +126,7 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
)
|
)
|
||||||
this.registerEvent(
|
this.registerEvent(
|
||||||
this.app.vault.on('delete', file => {
|
this.app.vault.on('delete', file => {
|
||||||
|
if (!(file instanceof TFile)) return
|
||||||
logVerbose('Removing file', file.path)
|
logVerbose('Removing file', file.path)
|
||||||
this.documentsRepository.removeDocument(file.path)
|
this.documentsRepository.removeDocument(file.path)
|
||||||
searchEngine.removeFromPaths([file.path])
|
searchEngine.removeFromPaths([file.path])
|
||||||
@@ -136,6 +135,7 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
)
|
)
|
||||||
this.registerEvent(
|
this.registerEvent(
|
||||||
this.app.vault.on('modify', async file => {
|
this.app.vault.on('modify', async file => {
|
||||||
|
if (!(file instanceof TFile)) return
|
||||||
if (this.notesIndexer.isFileIndexable(file.path)) {
|
if (this.notesIndexer.isFileIndexable(file.path)) {
|
||||||
this.notesIndexer.flagNoteForReindex(file)
|
this.notesIndexer.flagNoteForReindex(file)
|
||||||
}
|
}
|
||||||
@@ -144,6 +144,7 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
)
|
)
|
||||||
this.registerEvent(
|
this.registerEvent(
|
||||||
this.app.vault.on('rename', async (file, oldPath) => {
|
this.app.vault.on('rename', async (file, oldPath) => {
|
||||||
|
if (!(file instanceof TFile)) return
|
||||||
if (this.notesIndexer.isFileIndexable(file.path)) {
|
if (this.notesIndexer.isFileIndexable(file.path)) {
|
||||||
logVerbose('Renaming file', file.path)
|
logVerbose('Renaming file', file.path)
|
||||||
this.documentsRepository.removeDocument(oldPath)
|
this.documentsRepository.removeDocument(oldPath)
|
||||||
@@ -160,7 +161,7 @@ export default class OmnisearchPlugin extends Plugin {
|
|||||||
this.refreshIndexCallback = this.notesIndexer.refreshIndex.bind(
|
this.refreshIndexCallback = this.notesIndexer.refreshIndex.bind(
|
||||||
this.notesIndexer
|
this.notesIndexer
|
||||||
)
|
)
|
||||||
addEventListener('blur', this.refreshIndexCallback)
|
addEventListener('blur', this.refreshIndexCallback!)
|
||||||
removeEventListener
|
removeEventListener
|
||||||
|
|
||||||
await this.executeFirstLaunchTasks()
|
await this.executeFirstLaunchTasks()
|
||||||
|
|||||||
@@ -67,7 +67,16 @@ export class DocumentsRepository {
|
|||||||
}
|
}
|
||||||
logVerbose('Generating IndexedDocument from', path)
|
logVerbose('Generating IndexedDocument from', path)
|
||||||
await this.addDocument(path)
|
await this.addDocument(path)
|
||||||
return this.documents.get(path)!
|
const document = this.documents.get(path)
|
||||||
|
|
||||||
|
// Only happens if the cache is corrupted
|
||||||
|
if (!document) {
|
||||||
|
console.error('Omnisearch', path, 'cannot be read')
|
||||||
|
this.countError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The document might be undefined, but this shouldn't stop the search from mostly working
|
||||||
|
return document!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,7 +228,8 @@ export class DocumentsRepository {
|
|||||||
if (this.plugin.settings.displayTitle === '#heading') {
|
if (this.plugin.settings.displayTitle === '#heading') {
|
||||||
displayTitle = metadata?.headings?.find(h => h.level === 1)?.heading ?? ''
|
displayTitle = metadata?.headings?.find(h => h.level === 1)?.heading ?? ''
|
||||||
} else {
|
} else {
|
||||||
displayTitle = metadata?.frontmatter?.[this.plugin.settings.displayTitle] ?? ''
|
displayTitle =
|
||||||
|
metadata?.frontmatter?.[this.plugin.settings.displayTitle] ?? ''
|
||||||
}
|
}
|
||||||
const tags = getTagsFromMetadata(metadata)
|
const tags = getTagsFromMetadata(metadata)
|
||||||
return {
|
return {
|
||||||
@@ -247,10 +257,11 @@ export class DocumentsRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private countError(): void {
|
private countError(): void {
|
||||||
if (++this.errorsCount > 5 && !this.errorsWarned) {
|
if (++this.errorsCount >= 3 && !this.errorsWarned) {
|
||||||
this.errorsWarned = true
|
this.errorsWarned = true
|
||||||
new Notice(
|
new Notice(
|
||||||
'Omnisearch ⚠️ There might be an issue with your cache. You should clean it in Omnisearch settings and restart Obsidian.'
|
'Omnisearch ⚠️ There might be an issue with your cache. You should clean it in Omnisearch settings and restart Obsidian.',
|
||||||
|
0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export class SettingsTab extends PluginSettingTab {
|
|||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName('Enable verbose logging')
|
.setName('Enable verbose logging')
|
||||||
.setDesc(
|
.setDesc(
|
||||||
"Adds a LOT of logs for debugging purposes. Don't forget to disable it."
|
'Adds a LOT of logs for debugging purposes. You also need to enable "Verbose" logging in the console to see these logs.'
|
||||||
)
|
)
|
||||||
.addToggle(toggle =>
|
.addToggle(toggle =>
|
||||||
toggle.setValue(settings.verboseLogging).onChange(async v => {
|
toggle.setValue(settings.verboseLogging).onChange(async v => {
|
||||||
|
|||||||
@@ -23,55 +23,13 @@ export class TextProcessor {
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Text to highlight
|
return text.replace(
|
||||||
const smartMatches = new RegExp(
|
|
||||||
matches
|
|
||||||
.map(
|
|
||||||
// This regex will match the word (with \b word boundary)
|
|
||||||
// \b doesn't detect non-alphabetical character's word boundary, so we need to escape it
|
|
||||||
matchItem => {
|
|
||||||
const escaped = escapeRegExp(matchItem.match)
|
|
||||||
return `\\b${escaped}\\b${
|
|
||||||
!/[a-zA-Z]/.test(matchItem.match) ? `|${escaped}` : ''
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.join('|'),
|
|
||||||
'giu'
|
|
||||||
)
|
|
||||||
|
|
||||||
// Replacer function that will highlight the matches
|
|
||||||
const replacer = (match: string) => {
|
|
||||||
const matchInfo = matches.find(info =>
|
|
||||||
match.match(
|
|
||||||
new RegExp(
|
new RegExp(
|
||||||
`\\b${escapeRegExp(info.match)}\\b${
|
`(${matches.map(item => escapeRegExp(item.match)).join('|')})`,
|
||||||
!/[a-zA-Z]/.test(info.match)
|
|
||||||
? `|${escapeRegExp(info.match)}`
|
|
||||||
: ''
|
|
||||||
}`,
|
|
||||||
'giu'
|
'giu'
|
||||||
|
),
|
||||||
|
`<span class="${highlightClass}">$1</span>`
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
if (matchInfo) {
|
|
||||||
return `<span class="${highlightClass}">${match}</span>`
|
|
||||||
}
|
|
||||||
return match
|
|
||||||
}
|
|
||||||
|
|
||||||
// Effectively highlight the text
|
|
||||||
let newText = text.replace(smartMatches, replacer)
|
|
||||||
|
|
||||||
// If the text didn't change (= nothing to highlight), re-run the regex but just replace the matches without the word boundary
|
|
||||||
if (newText === text) {
|
|
||||||
const dumbMatches = new RegExp(
|
|
||||||
matches.map(matchItem => escapeRegExp(matchItem.match)).join('|'),
|
|
||||||
'giu'
|
|
||||||
)
|
|
||||||
newText = text.replace(dumbMatches, replacer)
|
|
||||||
}
|
|
||||||
return newText
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Omnisearch - Error in highlightText()', e)
|
console.error('Omnisearch - Error in highlightText()', e)
|
||||||
return text
|
return text
|
||||||
@@ -101,7 +59,12 @@ export class TextProcessor {
|
|||||||
* @param reg
|
* @param reg
|
||||||
* @param query
|
* @param query
|
||||||
*/
|
*/
|
||||||
public getMatches(text: string, words: string[], query?: Query): SearchMatch[] {
|
public getMatches(
|
||||||
|
text: string,
|
||||||
|
words: string[],
|
||||||
|
query?: Query
|
||||||
|
): SearchMatch[] {
|
||||||
|
words = words.map(escapeHTML)
|
||||||
const reg = this.stringsToRegex(words)
|
const reg = this.stringsToRegex(words)
|
||||||
const originalText = text
|
const originalText = text
|
||||||
// text = text.toLowerCase().replace(new RegExp(SEPARATORS, 'gu'), ' ')
|
// text = text.toLowerCase().replace(new RegExp(SEPARATORS, 'gu'), ' ')
|
||||||
@@ -199,4 +162,3 @@ export function escapeHTML(html: string): string {
|
|||||||
.replaceAll('"', '"')
|
.replaceAll('"', '"')
|
||||||
.replaceAll("'", ''')
|
.replaceAll("'", ''')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,27 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": [
|
"verbatimModuleSyntax": true,
|
||||||
"svelte",
|
"skipLibCheck": true,
|
||||||
"node",
|
|
||||||
"jest"
|
|
||||||
],
|
|
||||||
"strict": true,
|
|
||||||
"noUncheckedIndexedAccess": false,
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
"inlineSourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ES2021",
|
"target": "ES2021",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"lib": [
|
"lib": [
|
||||||
"DOM",
|
"DOM",
|
||||||
"ES2021"
|
"ES2021"
|
||||||
],
|
]
|
||||||
"paths": {
|
|
||||||
"minisearch": ["node_modules/minisearch/src/MiniSearch.ts"]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
"src/__tests__/event-bus-tests.mts"
|
"**/*.svelte"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user