Merge branch 'develop'

# Conflicts:
#	manifest-beta.json
#	versions.json
This commit is contained in:
Simon Cambier
2023-05-27 12:46:19 +02:00
16 changed files with 153 additions and 48 deletions

View File

@@ -18,6 +18,7 @@
}
.omnisearch-result__title {
white-space: pre-wrap;
align-items: center;
display: flex;
gap: 5px;

View File

@@ -1,7 +1,7 @@
{
"id": "omnisearch",
"name": "Omnisearch",
"version": "1.14.1-beta.3",
"version": "1.14.1-beta.2",
"minAppVersion": "1.0.0",
"description": "A search engine that just works",
"author": "Simon Cambier",

View File

@@ -1,6 +1,6 @@
{
"name": "scambier.obsidian-search",
"version": "1.14.0",
"version": "1.14.1-beta.3",
"description": "A search engine for Obsidian",
"main": "dist/main.js",
"scripts": {

6
pnpm-lock.yaml generated
View File

@@ -58,7 +58,7 @@ devDependencies:
esbuild-plugin-copy: 1.3.0_esbuild@0.14.0
esbuild-svelte: 0.7.1_wvi5wuag3veo5vm52k3h7pgaae
jest: 27.5.1
obsidian: 1.1.1
obsidian: 1.2.8
prettier: 2.8.1
prettier-plugin-svelte: 2.8.1_sro2v6ld777payjtkjtiuogcxi
svelte: 3.54.0
@@ -4119,8 +4119,8 @@ packages:
object-keys: 1.1.1
dev: true
/obsidian/1.1.1:
resolution: {integrity: sha512-GcxhsHNkPEkwHEjeyitfYNBcQuYGeAHFs1pEpZIv0CnzSfui8p8bPLm2YKLgcg20B764770B1sYGtxCvk9ptxg==}
/obsidian/1.2.8:
resolution: {integrity: sha512-HrC+feA8o0tXspj4lEAqxb1btwLwHD2oHXSwbbN+CdRHURqbCkuIDLld+nkuyJ1w1c9uvVDRVk8BoeOnWheOrQ==}
peerDependencies:
'@codemirror/state': ^6.0.0
'@codemirror/view': ^6.0.0

View File

@@ -5,24 +5,26 @@
import { cacheManager } from '../cache-manager'
export let initialValue = ''
let initialSet = false
export let placeholder = ''
let initialSet = false
let value = ''
let elInput: HTMLInputElement
const dispatch = createEventDispatcher()
export function setInputValue(v:string): void {
export function setInputValue(v: string): void {
value = v
}
$: {
if (initialValue && !initialSet && !value) {
function watchInitialValue(v: string): void {
if (v && !initialSet && !value) {
initialSet = true
value = initialValue
value = v
selectInput()
}
}
$: watchInitialValue(initialValue)
function selectInput(_?: HTMLElement): void {
tick()
.then(() => {
@@ -39,14 +41,14 @@
// the next time we open the modal, the search field will be empty
cacheManager.addToSearchHistory('')
dispatch('input', value)
}, 250)
}, 300)
</script>
<div class="omnisearch-input-container">
<div class="omnisearch-input-field">
<input
bind:this="{elInput}"
bind:value
bind:value="{value}"
class="prompt-input"
use:selectInput
on:compositionend="{_ => toggleInputComposition(false)}"

View File

@@ -27,6 +27,7 @@
import * as NotesIndex from '../notes-index'
import { cacheManager } from '../cache-manager'
import { searchEngine } from 'src/search/omnisearch'
import { cancelable, CancelablePromise } from 'cancelable-promise'
export let modal: OmnisearchVaultModal
export let previousQuery: string | undefined
@@ -38,9 +39,24 @@
let indexingStepDesc = ''
let searching = true
let refInput: InputSearch | undefined
let openInNewPaneKey: string
let openInCurrentPaneKey: string
let createInNewPaneKey: string
let createInCurrentPaneKey: string
$: selectedNote = resultNotes[selectedIndex]
$: searchQuery = searchQuery ?? previousQuery
$: if (settings.openInNewPane) {
openInNewPaneKey = '↵'
openInCurrentPaneKey = getCtrlKeyLabel() + ' ↵'
createInNewPaneKey = 'shift ↵'
createInCurrentPaneKey = getCtrlKeyLabel() + ' shift ↵'
} else {
openInNewPaneKey = getCtrlKeyLabel() + ' ↵'
openInCurrentPaneKey = '↵'
createInNewPaneKey = getCtrlKeyLabel() + ' shift ↵'
createInCurrentPaneKey = 'shift ↵'
}
$: if (searchQuery) {
searching = true
updateResults().then(() => {
@@ -112,9 +128,20 @@
refInput?.setInputValue(searchQuery)
}
let cancelableQuery: CancelablePromise<ResultNote[]> | null = null
async function updateResults() {
// If search is already in progress, cancel it and start a new one
if (cancelableQuery) {
cancelableQuery.cancel()
cancelableQuery = null
}
query = new Query(searchQuery)
resultNotes = await searchEngine.getSuggestions(query)
cancelableQuery = cancelable(
new Promise(resolve => {
resolve(searchEngine.getSuggestions(query))
})
)
resultNotes = await cancelableQuery
selectedIndex = 0
await scrollIntoView()
}
@@ -297,7 +324,7 @@
<span>to cycle history</span>
</div>
<div class="prompt-instruction">
<span class="prompt-instruction-command"></span><span>to open</span>
<span class="prompt-instruction-command">{openInCurrentPaneKey}</span><span>to open</span>
</div>
<div class="prompt-instruction">
<span class="prompt-instruction-command">tab</span>
@@ -305,15 +332,15 @@
</div>
<div class="prompt-instruction">
<span class="prompt-instruction-command">{getCtrlKeyLabel()}</span>
<span class="prompt-instruction-command">{openInNewPaneKey}</span>
<span>to open in a new pane</span>
</div>
<div class="prompt-instruction">
<span class="prompt-instruction-command">shift ↵</span>
<span class="prompt-instruction-command">{createInCurrentPaneKey}</span>
<span>to create</span>
</div>
<div class="prompt-instruction">
<span class="prompt-instruction-command">ctrl shift ↵</span>
<span class="prompt-instruction-command">{createInNewPaneKey}</span>
<span>to create in a new pane</span>
</div>

View File

@@ -71,8 +71,9 @@
<span class="omnisearch-result__title">
<span bind:this="{elFilePathIcon}"></span>
<span>{@html title.replace(reg, highlighterGroups)}</span>
<span class="omnisearch-result__extension"
>.{getExtension(note.path)}</span>
<span class="omnisearch-result__extension">
.{getExtension(note.path)}
</span>
<!-- Counter -->
{#if note.matches.length > 0}

View File

@@ -1,7 +1,9 @@
import { App, Modal, TFile } from 'obsidian'
import type { Modifier } from 'obsidian'
import ModalVault from './ModalVault.svelte'
import ModalInFile from './ModalInFile.svelte'
import { eventBus, EventNames, isInputComposition } from '../globals'
import { settings } from '../settings'
abstract class OmnisearchModal extends Modal {
protected constructor(app: App) {
@@ -61,8 +63,24 @@ abstract class OmnisearchModal extends Modal {
// #endregion Up/Down navigation
let openInCurrentPaneKey: Modifier[]
let openInNewPaneKey: Modifier[]
let createInCurrentPaneKey: Modifier[]
let createInNewPaneKey: Modifier[]
if (settings.openInNewPane) {
openInCurrentPaneKey = ['Mod']
openInNewPaneKey = []
createInCurrentPaneKey = ['Mod', 'Shift']
createInNewPaneKey = ['Shift']
} else {
openInCurrentPaneKey = []
openInNewPaneKey = ['Mod']
createInCurrentPaneKey = ['Shift']
createInNewPaneKey = ['Mod', 'Shift']
}
// Open in new pane
this.scope.register(['Mod'], 'Enter', e => {
this.scope.register(openInNewPaneKey, 'Enter', e => {
e.preventDefault()
eventBus.emit('open-in-new-pane')
})
@@ -74,17 +92,17 @@ abstract class OmnisearchModal extends Modal {
})
// Create a new note
this.scope.register(['Shift'], 'Enter', e => {
this.scope.register(createInCurrentPaneKey, 'Enter', e => {
e.preventDefault()
eventBus.emit('create-note')
})
this.scope.register(['Ctrl', 'Shift'], 'Enter', e => {
this.scope.register(createInNewPaneKey, 'Enter', e => {
e.preventDefault()
eventBus.emit('create-note', { newLeaf: true })
})
// Open in current pane
this.scope.register([], 'Enter', e => {
this.scope.register(openInCurrentPaneKey, 'Enter', e => {
if (!isInputComposition()) {
// Check if the user is still typing
e.preventDefault()

View File

@@ -16,6 +16,7 @@ export const excerptAfter = 300
export const highlightClass = `suggestion-highlight omnisearch-highlight ${
settings.highlight ? 'omnisearch-default-highlight' : ''
}`
export const K_DISABLE_OMNISEARCH = 'omnisearch-disabled'
export const eventBus = new EventBus()

View File

@@ -4,6 +4,7 @@ import {
OmnisearchVaultModal,
} from './components/modals'
import {
isPluginDisabled,
loadSettings,
saveSettings,
settings,
@@ -29,6 +30,13 @@ export default class OmnisearchPlugin extends Plugin {
async onload(): Promise<void> {
await loadSettings(this)
this.addSettingTab(new SettingsTab(this))
if (isPluginDisabled()) {
console.log('Omnisearch - Plugin disabled')
return
}
await cleanOldCacheFiles()
await OmnisearchCache.clearOldDatabases()
@@ -38,7 +46,6 @@ export default class OmnisearchPlugin extends Plugin {
this.addRibbonButton()
}
this.addSettingTab(new SettingsTab(this))
eventBus.disable('vault')
eventBus.disable('infile')
eventBus.on('global', EventNames.ToggleExcerpts, () => {
@@ -252,3 +259,4 @@ function registerAPI(plugin: OmnisearchPlugin): void {
// Deprecated
;(app as any).plugins.plugins.omnisearch.api = api
}

View File

@@ -201,13 +201,16 @@ export class Omnisearch {
logDebug('Found', results.length, 'results')
// Filter query results to only keep files that match query.extensions (if any)
if (query.extensions.length) {
// Filter query results to only keep files that match query.query.ext (if any)
if (query.query.ext?.length) {
results = results.filter(r => {
// ".can" should match ".canvas"
const ext = '.' + r.id.split('.').pop()
return query.extensions.some(e => ext.startsWith(e))
return query.query.ext?.some(e =>
ext.startsWith(e.startsWith('.') ? e : '.' + e)
)
})
console.log(query.query.ext, results.length)
}
// Filter query results that match the path
@@ -219,15 +222,14 @@ export class Omnisearch {
)
}
if (query.query.exclude.path) {
results = results.filter(r =>
!query.query.exclude.path?.some(p =>
(r.id as string).toLowerCase().includes(p.toLowerCase())
)
results = results.filter(
r =>
!query.query.exclude.path?.some(p =>
(r.id as string).toLowerCase().includes(p.toLowerCase())
)
)
}
// If the query does not return any result,
// retry but with a shorter prefix limit
if (!results.length) {
return []
}

View File

@@ -7,7 +7,7 @@ import {
} from 'obsidian'
import { writable } from 'svelte/store'
import { database } from './database'
import { getTextExtractor, isCacheEnabled } from './globals'
import { K_DISABLE_OMNISEARCH, getTextExtractor, isCacheEnabled } from './globals'
import type OmnisearchPlugin from './main'
interface WeightingSettings {
@@ -47,6 +47,7 @@ export interface OmnisearchSettings extends WeightingSettings {
simpleSearch: boolean
highlight: boolean
splitCamelCase: boolean
openInNewPane: boolean
verboseLogging: boolean
}
@@ -55,6 +56,8 @@ export interface OmnisearchSettings extends WeightingSettings {
*/
export const showExcerpt = writable(false)
const needsARestart = `<strong style="color: var(--text-accent)">Needs a restart to fully take effect.</strong>`
export class SettingsTab extends PluginSettingTab {
plugin: OmnisearchPlugin
@@ -72,6 +75,11 @@ export class SettingsTab extends PluginSettingTab {
const { containerEl } = this
containerEl.empty()
if (app.loadLocalStorage(K_DISABLE_OMNISEARCH) == '1') {
const span = containerEl.createEl('span')
span.innerHTML = `<strong style="color: var(--text-accent)">⚠️ OMNISEARCH IS DISABLED ⚠️</strong>`
}
// Settings main title
containerEl.createEl('h2', { text: 'Omnisearch' })
@@ -138,7 +146,7 @@ export class SettingsTab extends PluginSettingTab {
Add extensions separated by a space, without the dot. Example: "<code>txt org</code>".<br />
⚠️ <span style="color: var(--text-accent)">Using extensions of non-plaintext files (like .docx or .pptx) WILL cause crashes,
because Omnisearch will try to index their content.</span><br />
<strong style="color: var(--text-accent)">Needs a restart to fully take effect.</strong>`
${needsARestart}`
})
new Setting(containerEl)
.setName('Additional files to index')
@@ -192,7 +200,7 @@ export class SettingsTab extends PluginSettingTab {
span.innerHTML = `Normalize diacritics in search terms. Words like "brûlée" or "žluťoučký" will be indexed as "brulee" and "zlutoucky".<br/>
⚠️ <span style="color: var(--text-accent)">You probably should <strong>NOT</strong> disable this.</span><br>
⚠️ <span style="color: var(--text-accent)">Changing this setting will clear the cache.</span><br>
<strong style="color: var(--text-accent)">Needs a restart to fully take effect.</strong>
${needsARestart}
`
})
new Setting(containerEl)
@@ -211,7 +219,7 @@ export class SettingsTab extends PluginSettingTab {
camelCaseDesc.createSpan({}, span => {
span.innerHTML = `Enable this if you want to be able to search for CamelCaseWords as separate words.<br/>
⚠️ <span style="color: var(--text-accent)">Changing this setting will clear the cache.</span><br>
<strong style="color: var(--text-accent)">Needs a restart to fully take effect.</strong>
${needsARestart}
`
})
new Setting(containerEl)
@@ -239,6 +247,18 @@ export class SettingsTab extends PluginSettingTab {
})
)
new Setting(containerEl)
.setName('Open in new pane')
.setDesc(
'Open and create files in a new pane instead of the current pane.'
)
.addToggle(toggle =>
toggle.setValue(settings.openInNewPane).onChange(async v => {
settings.openInNewPane = v
await saveSettings(this.plugin)
})
)
//#endregion Behavior
//#region User Interface
@@ -364,7 +384,9 @@ export class SettingsTab extends PluginSettingTab {
new Setting(containerEl)
.setName('Enable verbose logging')
.setDesc('Adds a LOT of logs for debugging purposes. Don\'t forget to disable it.')
.setDesc(
"Adds a LOT of logs for debugging purposes. Don't forget to disable it."
)
.addToggle(toggle =>
toggle.setValue(settings.verboseLogging).onChange(async v => {
settings.verboseLogging = v
@@ -375,14 +397,33 @@ export class SettingsTab extends PluginSettingTab {
//#endregion Debugginh
//#region Danger Zone
if (isCacheEnabled()) {
new Setting(containerEl).setName('Danger Zone').setHeading()
new Setting(containerEl).setName('Danger Zone').setHeading()
const disableDesc = new DocumentFragment()
disableDesc.createSpan({}, span => {
span.innerHTML = `Disable Omnisearch on this device only.<br>
${needsARestart}`
})
new Setting(containerEl)
.setName('Disable on this device')
.setDesc(disableDesc)
.addToggle(toggle =>
toggle.setValue(isPluginDisabled()).onChange(async v => {
if (v) {
app.saveLocalStorage(K_DISABLE_OMNISEARCH, '1')
} else {
app.saveLocalStorage(K_DISABLE_OMNISEARCH) // No value = unset
}
new Notice('Omnisearch - Disabled. Please restart Obsidian.')
})
)
if (isCacheEnabled()) {
const resetCacheDesc = new DocumentFragment()
resetCacheDesc.createSpan({}, span => {
span.innerHTML = `Erase all Omnisearch cache data.
Use this if Omnisearch results are inconsistent, missing, or appear outdated.<br>
<strong style="color: var(--text-accent)">Needs a restart to fully take effect.</strong>`
Use this if Omnisearch results are inconsistent, missing, or appear outdated.<br>
${needsARestart}`
})
new Setting(containerEl)
.setName('Clear cache data')
@@ -417,6 +458,7 @@ export const DEFAULT_SETTINGS: OmnisearchSettings = {
PDFIndexing: false,
imagesIndexing: false,
splitCamelCase: false,
openInNewPane: false,
ribbonIcon: true,
showExcerpt: true,
@@ -446,3 +488,7 @@ export async function loadSettings(plugin: Plugin): Promise<void> {
export async function saveSettings(plugin: Plugin): Promise<void> {
await plugin.saveData(settings)
}
export function isPluginDisabled(): boolean {
return app.loadLocalStorage(K_DISABLE_OMNISEARCH) == '1'
}

View File

@@ -52,7 +52,7 @@ export async function createNote(name: string, newLeaf = false): Promise<void> {
let pathPrefix: string
switch (app.vault.getConfig('newFileLocation')) {
case 'current':
pathPrefix = (app.workspace.getActiveFile()?.parent.path ?? '') + '/'
pathPrefix = (app.workspace.getActiveFile()?.parent?.path ?? '') + '/'
break
case 'folder':
pathPrefix = app.vault.getConfig('newFileFolderPath') + '/'

View File

@@ -33,7 +33,7 @@ export function highlighterGroups(...args: any[]) {
args[2] !== null &&
args[2] !== undefined
)
return `${args[1]}<span class="${highlightClass}">${args[2]}</span>`
return `<span>${args[1]}</span><span class="${highlightClass}">${args[2]}</span>`
return '&lt;no content&gt;'
}

View File

@@ -17,7 +17,7 @@ declare module 'obsidian' {
interface App {
appId: string
loadLocalStorage(key: string): string | null
saveLocalStorage(key: string, value?: string): void
}
}

View File

@@ -107,6 +107,5 @@
"1.14.0-beta.1": "1.0.0",
"1.14.0": "1.0.0",
"1.14.1-beta.1": "1.0.0",
"1.14.1-beta.2": "1.0.0",
"1.14.1-beta.3": "1.0.0"
"1.14.1-beta.2": "1.0.0"
}