Trying Svelte, displaying the number of matches
This commit is contained in:
@@ -8,6 +8,10 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.omnisearch-result__counter {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
.omnisearch-result__body {
|
.omnisearch-result__body {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
|
|||||||
20
src/CmpNoteResult.svelte
Normal file
20
src/CmpNoteResult.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let title = ''
|
||||||
|
export let content = ''
|
||||||
|
export let id = ''
|
||||||
|
export let nbMatches = 0
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div data-note-id={id} class="omnisearch-result">
|
||||||
|
<span class="omnisearch-result__title">
|
||||||
|
{@html title}
|
||||||
|
</span>
|
||||||
|
<span class="omnisearch-result__counter">
|
||||||
|
{nbMatches}
|
||||||
|
{#if nbMatches > 1}matches{:else}match{/if}
|
||||||
|
</span>
|
||||||
|
<div class="omnisearch-result__body">
|
||||||
|
{@html content}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
export let variable: number;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="number"><span>My number is {variable}!</span></div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.number {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
44
src/modal.ts
44
src/modal.ts
@@ -1,12 +1,13 @@
|
|||||||
import { MarkdownView, SuggestModal, TFile } from 'obsidian'
|
import { MarkdownView, SuggestModal, TFile } from 'obsidian'
|
||||||
import type { ResultNote } from './globals'
|
import type { ResultNote } from './globals'
|
||||||
import type OmnisearchPlugin from './main'
|
import type OmnisearchPlugin from './main'
|
||||||
import Component from './Component.svelte'
|
import CmpNoteResult from './CmpNoteResult.svelte'
|
||||||
import { escapeHTML, escapeRegex, getAllIndexes, highlighter } from './utils'
|
import { escapeHTML, escapeRegex, getAllIndexes, highlighter } from './utils'
|
||||||
|
import { selectedNoteId } from './store'
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
|
||||||
export class OmnisearchModal extends SuggestModal<ResultNote> {
|
export class OmnisearchModal extends SuggestModal<ResultNote> {
|
||||||
private plugin: OmnisearchPlugin
|
private plugin: OmnisearchPlugin
|
||||||
private selectedNoteId?: string
|
|
||||||
private mutationObserver?: MutationObserver
|
private mutationObserver?: MutationObserver
|
||||||
|
|
||||||
constructor(plugin: OmnisearchPlugin) {
|
constructor(plugin: OmnisearchPlugin) {
|
||||||
@@ -27,7 +28,7 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onKeydown(ev: KeyboardEvent): Promise<void> {
|
async onKeydown(ev: KeyboardEvent): Promise<void> {
|
||||||
const noteId = this.selectedNoteId
|
const noteId = get(selectedNoteId)
|
||||||
if (ev.key !== 'Enter' || !noteId) return
|
if (ev.key !== 'Enter' || !noteId) return
|
||||||
|
|
||||||
if (ev.ctrlKey || ev.metaKey) {
|
if (ev.ctrlKey || ev.metaKey) {
|
||||||
@@ -66,9 +67,11 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
(event.target as HTMLDivElement).classList.contains('is-selected'),
|
(event.target as HTMLDivElement).classList.contains('is-selected'),
|
||||||
)
|
)
|
||||||
const id =
|
const id =
|
||||||
(record?.target as HTMLElement)?.getAttribute('data-note-id') ?? null
|
(record?.target?.firstChild as HTMLElement)?.getAttribute(
|
||||||
|
'data-note-id',
|
||||||
|
) ?? null
|
||||||
if (id) {
|
if (id) {
|
||||||
this.selectedNoteId = id
|
selectedNoteId.set(id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.mutationObserver.observe(modalEl, {
|
this.mutationObserver.observe(modalEl, {
|
||||||
@@ -79,8 +82,7 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
|
|
||||||
onOpen(): void {
|
onOpen(): void {
|
||||||
this.inputEl.focus()
|
this.inputEl.focus()
|
||||||
this.setupObserver(this.modalEl)
|
this.inputEl.onkeydown = this.onKeydown.bind(this)
|
||||||
|
|
||||||
// Reload last search, if any
|
// Reload last search, if any
|
||||||
if (this.plugin.lastSearch) {
|
if (this.plugin.lastSearch) {
|
||||||
const event = new Event('input', {
|
const event = new Event('input', {
|
||||||
@@ -93,7 +95,7 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
this.inputEl.spellcheck = false
|
this.inputEl.spellcheck = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inputEl.onkeydown = this.onKeydown.bind(this)
|
this.setupObserver(this.modalEl)
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose(): void {
|
onClose(): void {
|
||||||
@@ -110,7 +112,12 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
prefix: true,
|
prefix: true,
|
||||||
fuzzy: term => (term.length > 4 ? 0.2 : false),
|
fuzzy: term => (term.length > 4 ? 0.2 : false),
|
||||||
combineWith: 'AND',
|
combineWith: 'AND',
|
||||||
boost: { basename: 2, headings1: 1.5, headings2: 1.3, headings3: 1.1 },
|
boost: {
|
||||||
|
basename: 2,
|
||||||
|
headings1: 1.5,
|
||||||
|
headings2: 1.3,
|
||||||
|
headings3: 1.1,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.sort((a, b) => b.score - a.score)
|
.sort((a, b) => b.score - a.score)
|
||||||
.slice(0, 50)
|
.slice(0, 50)
|
||||||
@@ -164,20 +171,15 @@ export class OmnisearchModal extends SuggestModal<ResultNote> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderSuggestion(value: ResultNote, el: HTMLElement): void {
|
renderSuggestion(value: ResultNote, el: HTMLElement): void {
|
||||||
const component = new Component({
|
new CmpNoteResult({
|
||||||
target: el,
|
target: el,
|
||||||
props: { variable: 1 },
|
props: {
|
||||||
|
id: value.path,
|
||||||
|
title: value.basename,
|
||||||
|
content: value.content,
|
||||||
|
nbMatches: value.matches.length,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
el.setAttribute('data-note-id', value.path)
|
|
||||||
el.addClass('omnisearch-result')
|
|
||||||
|
|
||||||
// title
|
|
||||||
const title = el.createEl('div', { cls: 'omnisearch-result__title' })
|
|
||||||
title.innerHTML = value.basename
|
|
||||||
|
|
||||||
// body
|
|
||||||
const body = el.createEl('div', { cls: 'omnisearch-result__body' })
|
|
||||||
body.innerHTML = value.content
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onChooseSuggestion(item: ResultNote): Promise<void> {
|
async onChooseSuggestion(item: ResultNote): Promise<void> {
|
||||||
|
|||||||
3
src/store.ts
Normal file
3
src/store.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { writable } from 'svelte/store'
|
||||||
|
|
||||||
|
export const selectedNoteId = writable<string>()
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { CachedMetadata } from 'obsidian'
|
import type { CachedMetadata } from 'obsidian'
|
||||||
import {
|
import {
|
||||||
isSearchMatch,
|
isSearchMatch,
|
||||||
regexLineSplit,
|
regexLineSplit,
|
||||||
regexWikilink,
|
regexWikilink,
|
||||||
regexYaml,
|
regexYaml,
|
||||||
SearchMatch,
|
|
||||||
} from './globals'
|
} from './globals'
|
||||||
|
import type { SearchMatch } from './globals'
|
||||||
|
|
||||||
export function highlighter(str: string): string {
|
export function highlighter(str: string): string {
|
||||||
return '<span class="search-result-file-matched-text">' + str + '</span>'
|
return '<span class="search-result-file-matched-text">' + str + '</span>'
|
||||||
|
|||||||
Reference in New Issue
Block a user