Trying Svelte, displaying the number of matches

This commit is contained in:
Simon Cambier
2022-04-15 20:39:08 +02:00
parent e5ba366840
commit 66b8980255
6 changed files with 52 additions and 34 deletions

View File

@@ -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
View 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>

View File

@@ -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>

View File

@@ -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
View File

@@ -0,0 +1,3 @@
import { writable } from 'svelte/store'
export const selectedNoteId = writable<string>()

View File

@@ -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>'