Merge branch 'develop'

This commit is contained in:
Simon Cambier
2024-07-31 11:18:30 +02:00
18 changed files with 282 additions and 140 deletions

View File

@@ -14,17 +14,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: pnpm/action-setup@v2.1.0
- uses: actions/checkout@v4
with:
version: 7.17.0
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9.3.0
run_install: true
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: "18.x"
cache: 'pnpm'
node-version: "20.x"
- name: Build
id: build
@@ -37,6 +40,18 @@ jobs:
ls
echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)"
- name: Generate a changelog
uses: orhun/git-cliff-action@v3
id: git-cliff
with:
config: cliff.toml
args: --verbose
env:
GITHUB_REPO: ${{ github.repository }}
- name: Print the changelog
run: cat "${{ steps.git-cliff.outputs.changelog }}"
- name: Create Release
id: create_release
uses: actions/create-release@v1
@@ -46,7 +61,8 @@ jobs:
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
body: ${{ steps.git-cliff.outputs.changelog }}
draft: true
prerelease: false
- name: Upload zip file

12
cliff.toml Normal file
View File

@@ -0,0 +1,12 @@
[changelog]
header = "Changelog"
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}
{% endfor %}
{% endfor %}
"""
trim = true
footer = "<!-- generated by git-cliff -->"

View File

@@ -1,6 +1,6 @@
{
"name": "scambier.obsidian-search",
"version": "1.23.1",
"version": "1.24.0-beta.3",
"description": "A search engine for Obsidian",
"main": "dist/main.js",
"scripts": {
@@ -52,6 +52,5 @@
"overrides": {
"moment@>=2.18.0 <2.29.4": ">=2.29.4"
}
},
"packageManager": "pnpm@9.1.0+sha512.67f5879916a9293e5cf059c23853d571beaf4f753c707f40cb22bed5fb1578c6aad3b6c4107ccb3ba0b35be003eb621a16471ac836c87beb53f9d54bb4612724"
}
}

View File

@@ -6,7 +6,10 @@ describe('The Query class', () => {
it('should correctly parse string queries', () => {
// Act
const query = new Query(stringQuery, { ignoreDiacritics: true })
const query = new Query(stringQuery, {
ignoreDiacritics: true,
ignoreArabicDiacritics: true,
})
// Assert
const segments = query.query.text
@@ -25,7 +28,10 @@ describe('The Query class', () => {
it('should not exclude words when there is no space before', () => {
// Act
const query = new Query('foo bar-baz', { ignoreDiacritics: true })
const query = new Query('foo bar-baz', {
ignoreDiacritics: true,
ignoreArabicDiacritics: true,
})
// Assert
expect(query.query.exclude.text).toHaveLength(0)
@@ -34,7 +40,10 @@ describe('The Query class', () => {
describe('.getExactTerms()', () => {
it('should an array of strings containg "exact" values', () => {
// Act
const query = new Query(stringQuery, { ignoreDiacritics: true })
const query = new Query(stringQuery, {
ignoreDiacritics: true,
ignoreArabicDiacritics: true,
})
// Assert
expect(query.getExactTerms()).toEqual(['lorem ipsum', 'sit amet'])

View File

@@ -5,7 +5,7 @@ import {
getAliasesFromMetadata,
getTagsFromMetadata,
isFileCanvas,
isFileFromDataloomPlugin,
isFileFromDataloom,
isFileImage,
isFileOffice,
isFilePDF,
@@ -136,7 +136,7 @@ export class CacheManager {
}
// ** Dataloom plugin **
else if (isFileFromDataloomPlugin(path)) {
else if (isFileFromDataloom(path)) {
try {
const data = JSON.parse(await app.vault.cachedRead(file))
// data is a json object, we recursively iterate the keys
@@ -230,10 +230,11 @@ export class CacheManager {
}
}
}
const displayTitle = metadata?.frontmatter?.[this.plugin.settings.displayTitle] ?? ''
const tags = getTagsFromMetadata(metadata)
return {
basename: file.basename,
displayTitle,
content,
/** Content without diacritics and markdown chars */
cleanedContent: stripMarkdownCharacters(removeDiacritics(content)),

View File

@@ -141,6 +141,7 @@
}
query = new Query(searchQuery, {
ignoreDiacritics: plugin.settings.ignoreDiacritics,
ignoreArabicDiacritics: plugin.settings.ignoreArabicDiacritics,
})
cancelableQuery = cancelable(
new Promise(resolve => {

View File

@@ -3,7 +3,7 @@
import type { ResultNote } from '../globals'
import {
getExtension,
isFileCanvas,
isFileCanvas, isFileExcalidraw,
isFileImage,
isFilePDF,
pathWithoutFilename,
@@ -36,7 +36,7 @@
$: cleanedContent = plugin.textProcessor.makeExcerpt(note.content, note.matches[0]?.offset ?? -1)
$: glyph = false //cacheManager.getLiveDocument(note.path)?.doesNotExist
$: {
title = note.basename
title = note.displayTitle || note.basename
notePath = pathWithoutFilename(note.path)
// Icons
@@ -44,11 +44,18 @@
setIcon(elFolderPathIcon, 'folder-open')
}
if (elFilePathIcon) {
if (isFileImage(note.path)) setIcon(elFilePathIcon, 'image')
else if (isFilePDF(note.path)) setIcon(elFilePathIcon, 'file-text')
else if (isFileCanvas(note.path))
if (isFileImage(note.path)) {
setIcon(elFilePathIcon, 'image')
}
else if (isFilePDF(note.path)) {
setIcon(elFilePathIcon, 'file-text')
}
else if (isFileCanvas(note.path) || isFileExcalidraw(note.path)) {
setIcon(elFilePathIcon, 'layout-dashboard')
else setIcon(elFilePathIcon, 'file')
}
else {
setIcon(elFilePathIcon, 'file')
}
}
}
</script>

View File

@@ -119,7 +119,7 @@ abstract class OmnisearchModal extends Modal {
})
// Open in background
this.scope.register(['Alt'], 'O', e => {
this.scope.register(['Ctrl'], 'O', e => {
if (!isInputComposition()) {
// Check if the user is still typing
e.preventDefault()

View File

@@ -46,6 +46,7 @@ export type DocumentRef = { path: string; mtime: number }
export type IndexedDocument = {
path: string
basename: string
displayTitle: string
mtime: number
content: string
@@ -76,6 +77,7 @@ export type ResultNote = {
score: number
path: string
basename: string
displayTitle: string
content: string
foundWords: string[]
matches: SearchMatch[]

View File

@@ -138,7 +138,9 @@ export default class OmnisearchPlugin extends Plugin {
})
)
this.refreshIndexCallback = this.notesIndexer.refreshIndex.bind(this.notesIndexer)
this.refreshIndexCallback = this.notesIndexer.refreshIndex.bind(
this.notesIndexer
)
addEventListener('blur', this.refreshIndexCallback)
removeEventListener
@@ -272,16 +274,21 @@ export default class OmnisearchPlugin extends Plugin {
indexingStep.set(IndexingStepType.WritingCache)
// Disable settings.useCache while writing the cache, in case it freezes
const cacheEnabled = this.settings.useCache
if (cacheEnabled && !this.settings.DANGER_forceSaveCache) {
this.settings.useCache = false
await saveSettings(this)
}
// Write the cache
await searchEngine.writeToCache()
// Re-enable settings.caching
if (cacheEnabled) {
this.settings.useCache = true
await saveSettings(this)
}
}
console.timeEnd('Omnisearch - Indexing total time')
if (diff.toAdd.length >= 1000 && isCacheEnabled()) {

View File

@@ -4,7 +4,7 @@ import { removeAnchors } from './tools/notes'
import type { IndexedDocument } from './globals'
import {
isFileCanvas,
isFileFromDataloomPlugin,
isFileFromDataloom,
isFileImage,
isFilePDF,
logDebug,
@@ -51,7 +51,7 @@ export class NotesIndexer {
return (
this.isFilePlaintext(path) ||
isFileCanvas(path) ||
isFileFromDataloomPlugin(path) ||
isFileFromDataloom(path) ||
(canIndexPDF && isFilePDF(path)) ||
(canIndexImages && isFileImage(path)) ||
(canIndexImagesAI && isFileImage(path))
@@ -63,7 +63,7 @@ export class NotesIndexer {
this.canIndexUnsupportedFiles() ||
this.isFilePlaintext(path) ||
isFileCanvas(path) ||
isFileFromDataloomPlugin(path)
isFileFromDataloom(path)
)
}
@@ -91,6 +91,7 @@ export class NotesIndexer {
return {
path: filename,
basename: name,
displayTitle: '',
mtime: 0,
content: '',

View File

@@ -13,9 +13,9 @@ export class Query {
}
#inQuotes: string[]
constructor(text = '', options: { ignoreDiacritics: boolean }) {
constructor(text = '', options: { ignoreDiacritics: boolean, ignoreArabicDiacritics: boolean}) {
if (options.ignoreDiacritics) {
text = removeDiacritics(text)
text = removeDiacritics(text, options.ignoreArabicDiacritics)
}
const parsed = parse(text.toLowerCase(), {
tokenize: true,

View File

@@ -154,8 +154,9 @@ export class SearchEngine {
term.length <= 3 ? 0 : term.length <= 5 ? fuzziness / 2 : fuzziness,
boost: {
basename: settings.weightBasename,
directory: settings.weightDirectory,
aliases: settings.weightBasename,
displayTitle: settings.weightBasename,
directory: settings.weightDirectory,
headings1: settings.weightH1,
headings2: settings.weightH2,
headings3: settings.weightH3,
@@ -304,7 +305,12 @@ export class SearchEngine {
const title = document?.path.toLowerCase() ?? ''
const content = (document?.cleanedContent ?? '').toLowerCase()
return exactTerms.every(
q => content.includes(q) || removeDiacritics(title).includes(q)
q =>
content.includes(q) ||
removeDiacritics(
title,
this.plugin.settings.ignoreArabicDiacritics
).includes(q)
)
})
}
@@ -434,7 +440,7 @@ export class SearchEngine {
},
processTerm: (term: string) =>
(this.plugin.settings.ignoreDiacritics
? removeDiacritics(term)
? removeDiacritics(term, this.plugin.settings.ignoreArabicDiacritics)
: term
).toLowerCase(),
idField: 'path',

View File

@@ -15,6 +15,7 @@ export class Tokenizer {
* @returns
*/
public tokenizeForIndexing(text: string): string[] {
try {
const words = this.tokenizeWords(text)
let urls: string[] = []
if (this.plugin.settings.tokenizeUrls) {
@@ -45,6 +46,10 @@ export class Tokenizer {
tokens = [...new Set(tokens)]
return tokens
} catch (e) {
console.error('Error tokenizing text, skipping document', e)
return []
}
}
/**

View File

@@ -11,7 +11,8 @@ import {
import { writable } from 'svelte/store'
import { K_DISABLE_OMNISEARCH } from './globals'
import type OmnisearchPlugin from './main'
import { enablePrintDebug } from "./tools/utils";
import { enablePrintDebug } from './tools/utils'
import { debounce } from 'lodash-es'
interface WeightingSettings {
weightBasename: number
@@ -32,8 +33,12 @@ export interface OmnisearchSettings extends WeightingSettings {
downrankedFoldersFilters: string[]
/** Ignore diacritics when indexing files */
ignoreDiacritics: boolean
ignoreArabicDiacritics: boolean
/** Extensions of plain text files to index, in addition to .md */
indexedFileTypes: string[]
/** Custom title field */
displayTitle: string
/** Enable PDF indexing */
PDFIndexing: boolean
/** Enable Images indexing */
@@ -71,6 +76,7 @@ export interface OmnisearchSettings extends WeightingSettings {
httpApiNotice: boolean
DANGER_httpHost: string | null
DANGER_forceSaveCache: boolean
}
/**
@@ -97,6 +103,11 @@ export class SettingsTab extends PluginSettingTab {
const { containerEl } = this
const database = this.plugin.database
const textExtractor = this.plugin.getTextExtractor()
const clearCacheDebounced = debounce(async () => {
await database.clearCache()
}, 1000)
const aiImageAnalyzer = this.plugin.getAIImageAnalyzer()
containerEl.empty()
@@ -138,18 +149,24 @@ export class SettingsTab extends PluginSettingTab {
new Setting(containerEl)
.setName('Indexing')
.setHeading()
.setDesc(indexingDesc)
.setDesc(
htmlDescription(`⚠️ <span style="color: var(--text-accent)">Changing indexing settings will clear the cache, and requires a restart of Obsidian.</span><br/><br/>
${
textExtractor
? `👍 You have installed <a href="https://github.com/scambier/obsidian-text-extractor">Text Extractor</a>, Omnisearch can use it to index PDFs and images contents.
<br />Text extraction only works on desktop, but the cache can be synchronized with your mobile device.`
: `⚠️ Omnisearch requires <a href="https://github.com/scambier/obsidian-text-extractor">Text Extractor</a> to index PDFs and images.`
}`)
)
// PDF Indexing
const indexPDFsDesc = new DocumentFragment()
indexPDFsDesc.createSpan({}, span => {
span.innerHTML = `Omnisearch will use Text Extractor to index the content of your PDFs.`
})
new Setting(containerEl)
.setName(
`PDFs content indexing ${textExtractor ? '' : '⚠️ Disabled'}`
.setName(`PDFs content indexing ${textExtractor ? '' : '⚠️ Disabled'}`)
.setDesc(
htmlDescription(
`Omnisearch will use Text Extractor to index the content of your PDFs.`
)
)
.setDesc(indexPDFsDesc)
.addToggle(toggle =>
toggle.setValue(settings.PDFIndexing).onChange(async v => {
await database.clearCache()
@@ -160,13 +177,13 @@ export class SettingsTab extends PluginSettingTab {
.setDisabled(!textExtractor)
// Images Indexing
const indexImagesDesc = new DocumentFragment()
indexImagesDesc.createSpan({}, span => {
span.innerHTML = `Omnisearch will use Text Extractor to OCR your images and index their content.`
})
new Setting(containerEl)
.setName(`Images OCR indexing ${textExtractor ? '' : '⚠️ Disabled'}`)
.setDesc(indexImagesDesc)
.setDesc(
htmlDescription(
`Omnisearch will use Text Extractor to OCR your images and index their content.`
)
)
.addToggle(toggle =>
toggle.setValue(settings.imagesIndexing).onChange(async v => {
await database.clearCache()
@@ -213,38 +230,49 @@ export class SettingsTab extends PluginSettingTab {
.setDisabled(!aiImageAnalyzer)
// Index filenames of unsupported files
const indexUnsupportedDesc = new DocumentFragment()
indexUnsupportedDesc.createSpan({}, span => {
span.innerHTML = `
Omnisearch can index file<strong>names</strong> of "unsupported" files, such as e.g. <pre style="display:inline">.mp4</pre>
or non-extracted PDFs & images.<br/>
"Obsidian setting" will respect the value of "Files & Links > Detect all file extensions".`
})
new Setting(containerEl)
.setName('Index paths of unsupported files')
.setDesc(indexUnsupportedDesc)
.setDesc(
htmlDescription(`
Omnisearch can index file<strong>names</strong> of "unsupported" files, such as e.g. <pre style="display:inline">.mp4</pre>
or non-extracted PDFs & images.<br/>
"Obsidian setting" will respect the value of "Files & Links > Detect all file extensions".`)
)
.addDropdown(dropdown => {
dropdown
.addOptions({ yes: 'Yes', no: 'No', default: 'Obsidian setting' })
.setValue(settings.unsupportedFilesIndexing)
.onChange(async v => {
await database.clearCache()
await clearCacheDebounced()
;(settings.unsupportedFilesIndexing as any) = v
await saveSettings(this.plugin)
})
})
// Additional text files to index
const indexedFileTypesDesc = new DocumentFragment()
indexedFileTypesDesc.createSpan({}, span => {
span.innerHTML = `In addition to standard <code>md</code> files, Omnisearch can also index other <strong style="color: var(--text-accent)">PLAINTEXT</strong> files.<br/>
Add extensions separated by a space, without the dot. Example: "<code>txt org csv</code>".<br />
⚠️ <span style="color: var(--text-accent)">Using extensions of non-plaintext files (like .pptx) WILL cause crashes,
because Omnisearch will try to index their content.</span>`
// Custom display title
new Setting(containerEl)
.setName('Set frontmatter property key as title')
.setDesc(
htmlDescription(`If you have a custom property in your notes that you want to use as the title in search results.<br>
Leave empty to disable.`)
)
.addText(component => {
component.setValue(settings.displayTitle).onChange(async v => {
await clearCacheDebounced()
settings.displayTitle = v
await saveSettings(this.plugin)
})
})
// Additional text files to index
new Setting(containerEl)
.setName('Additional TEXT files to index')
.setDesc(indexedFileTypesDesc)
.setDesc(
htmlDescription(`In addition to standard <code>md</code> files, Omnisearch can also index other <strong style="color: var(--text-accent)">PLAINTEXT</strong> files.<br/>
Add extensions separated by a space, without the dot. Example: "<code>txt org csv</code>".<br />
⚠️ <span style="color: var(--text-accent)">Using extensions of non-plaintext files (like .pptx) WILL cause crashes,
because Omnisearch will try to index their content.</span>`)
)
.addText(component => {
component
.setValue(settings.indexedFileTypes.join(' '))
@@ -319,16 +347,13 @@ export class SettingsTab extends PluginSettingTab {
})
// Split CamelCaseWords
const camelCaseDesc = new DocumentFragment()
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>
${needsARestart}
`
})
new Setting(containerEl)
.setName('Split CamelCaseWords')
.setDesc(camelCaseDesc)
.setDesc(
htmlDescription(`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>
${needsARestart}`)
)
.addToggle(toggle =>
toggle.setValue(settings.splitCamelCase).onChange(async v => {
await database.clearCache()
@@ -469,14 +494,12 @@ export class SettingsTab extends PluginSettingTab {
)
// Show "Create note" button
const createBtnDesc = new DocumentFragment()
createBtnDesc.createSpan({}, span => {
span.innerHTML = `Shows a button next to the search input, to create a note.
Acts the same as the <code>shift ↵</code> shortcut, can be useful for mobile device users.`
})
new Setting(containerEl)
.setName('Show "Create note" button')
.setDesc(createBtnDesc)
.setDesc(
htmlDescription(`Shows a button next to the search input, to create a note.
Acts the same as the <code>shift ↵</code> shortcut, can be useful for mobile device users.`)
)
.addToggle(toggle =>
toggle.setValue(settings.showCreateButton).onChange(async v => {
settings.showCreateButton = v
@@ -589,14 +612,14 @@ export class SettingsTab extends PluginSettingTab {
//#region HTTP Server
if (!Platform.isMobile) {
const httpServerDesc = new DocumentFragment()
httpServerDesc.createSpan({}, span => {
span.innerHTML = `Omnisearch can be used through a simple HTTP server (<a href="https://publish.obsidian.md/omnisearch/Public+API+%26+URL+Scheme#HTTP+Server">more information</a>).`
})
new Setting(containerEl)
.setName('API Access Through HTTP')
.setHeading()
.setDesc(httpServerDesc)
.setDesc(
htmlDescription(
`Omnisearch can be used through a simple HTTP server (<a href="https://publish.obsidian.md/omnisearch/Public+API+%26+URL+Scheme#HTTP+Server">more information</a>).`
)
)
new Setting(containerEl)
.setName('Enable the HTTP server')
@@ -668,17 +691,14 @@ export class SettingsTab extends PluginSettingTab {
new Setting(containerEl).setName('Danger Zone').setHeading()
// Ignore diacritics
const diacriticsDesc = new DocumentFragment()
diacriticsDesc.createSpan({}, span => {
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>
${needsARestart}
`
})
new Setting(containerEl)
.setName('Ignore diacritics')
.setDesc(diacriticsDesc)
.setDesc(
htmlDescription(`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>
${needsARestart}`)
)
.addToggle(toggle =>
toggle.setValue(settings.ignoreDiacritics).onChange(async v => {
await database.clearCache()
@@ -687,6 +707,16 @@ export class SettingsTab extends PluginSettingTab {
})
)
new Setting(containerEl)
.setName('Ignore Arabic diacritics (beta)')
.addToggle(toggle =>
toggle.setValue(settings.ignoreArabicDiacritics).onChange(async v => {
await database.clearCache()
settings.ignoreArabicDiacritics = v
await saveSettings(this.plugin)
})
)
// Disable Omnisearch
const disableDesc = new DocumentFragment()
disableDesc.createSpan({}, span => {
@@ -700,24 +730,38 @@ export class SettingsTab extends PluginSettingTab {
toggle.setValue(isPluginDisabled(this.app)).onChange(async v => {
if (v) {
this.app.saveLocalStorage(K_DISABLE_OMNISEARCH, '1')
new Notice('Omnisearch - Disabled. Please restart Obsidian.')
} else {
this.app.saveLocalStorage(K_DISABLE_OMNISEARCH) // No value = unset
new Notice('Omnisearch - Enabled. Please restart Obsidian.')
}
new Notice('Omnisearch - Disabled. Please restart Obsidian.')
})
)
// Force save cache
new Setting(containerEl)
.setName('Force save the cache')
.setDesc(
htmlDescription(`Omnisearch has a security feature that automatically disables cache writing if it cannot fully perform the operation.<br>
Use this option to force the cache to be saved, even if it causes a crash.<br>
⚠️ <span style="color: var(--text-accent)">Enabling this setting could lead to crash loops</span>`)
)
.addToggle(toggle =>
toggle.setValue(settings.DANGER_forceSaveCache).onChange(async v => {
settings.DANGER_forceSaveCache = v
await saveSettings(this.plugin)
})
)
// Clear cache data
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>
${needsARestart}`
})
new Setting(containerEl)
.setName('Clear cache data')
.setDesc(resetCacheDesc)
.setDesc(
htmlDescription(`Erase all Omnisearch cache data.
Use this if Omnisearch results are inconsistent, missing, or appear outdated.<br>
${needsARestart}`)
)
.addButton(btn => {
btn.setButtonText('Clear cache')
btn.onClick(async () => {
@@ -725,6 +769,7 @@ export class SettingsTab extends PluginSettingTab {
})
})
}
//#endregion Danger Zone
}
@@ -745,7 +790,9 @@ export function getDefaultSettings(app: App): OmnisearchSettings {
hideExcluded: false,
downrankedFoldersFilters: [] as string[],
ignoreDiacritics: true,
ignoreArabicDiacritics: false,
indexedFileTypes: [] as string[],
displayTitle: '',
PDFIndexing: false,
officeIndexing: false,
imagesIndexing: false,
@@ -781,11 +828,20 @@ export function getDefaultSettings(app: App): OmnisearchSettings {
verboseLogging: false,
DANGER_httpHost: null,
DANGER_forceSaveCache: false,
}
}
let settings: OmnisearchSettings
function htmlDescription(innerHTML: string): DocumentFragment {
const desc = new DocumentFragment()
desc.createSpan({}, span => {
span.innerHTML = innerHTML
})
return desc
}
// /**
// * @deprecated
// */

View File

@@ -88,6 +88,7 @@ export function getApi(plugin: OmnisearchPlugin) {
async search(q: string): Promise<ResultNoteApi[]> {
const query = new Query(q, {
ignoreDiacritics: plugin.settings.ignoreDiacritics,
ignoreArabicDiacritics: plugin.settings.ignoreArabicDiacritics,
})
const raw = await plugin.searchEngine.getSuggestions(query)
return mapResults(plugin, raw)

View File

@@ -115,7 +115,7 @@ export class TextProcessor {
const originalText = text
// text = text.toLowerCase().replace(new RegExp(SEPARATORS, 'gu'), ' ')
if (this.plugin.settings.ignoreDiacritics) {
text = removeDiacritics(text)
text = removeDiacritics(text, this.plugin.settings.ignoreArabicDiacritics)
}
const startTime = new Date().getTime()
let match: RegExpExecArray | null = null

View File

@@ -109,15 +109,30 @@ export function getTagsFromMetadata(metadata: CachedMetadata | null): string[] {
/**
* https://stackoverflow.com/a/37511463
*/
export function removeDiacritics(str: string): string {
// Japanese diacritics that should be distinguished
const excludeDiacritics: string[] = ['\\u30FC', '\\u309A', '\\u3099']
const regexpExclude: string = excludeDiacritics.join('|')
const regexp: RegExp = new RegExp(`(?!${regexpExclude})\\p{Diacritic}`, 'gu')
export function removeDiacritics(str: string, arabic = false): string {
if (str === null || str === undefined) {
return ''
}
// Japanese diacritics that should be distinguished
const japaneseDiacritics: string[] = ['\\u30FC', '\\u309A', '\\u3099']
const regexpExclude: string = japaneseDiacritics.join('|')
const regexp: RegExp = new RegExp(`(?!${regexpExclude})\\p{Diacritic}`, 'gu')
if (arabic) {
// Arabic diacritics
// https://stackoverflow.com/a/40959537
str = str
.replace(/([^\u0621-\u063A\u0641-\u064A\u0660-\u0669a-zA-Z 0-9])/g, '')
.replace(/(آ|إ|أ)/g, 'ا')
.replace(/(ة)/g, 'ه')
.replace(/(ئ|ؤ)/g, 'ء')
.replace(/(ى)/g, 'ي')
for (let i = 0; i < 10; i++) {
str.replace(String.fromCharCode(0x660 + i), String.fromCharCode(48 + i))
}
}
// Keep backticks for code blocks, because otherwise they are removed by the .normalize() function
// https://stackoverflow.com/a/36100275
str = str.replaceAll('`', '[__omnisearch__backtick__]')
@@ -152,7 +167,11 @@ export function isFileCanvas(path: string): boolean {
return path.endsWith('.canvas')
}
export function isFileFromDataloomPlugin(path: string): boolean {
export function isFileExcalidraw(path: string): boolean {
return path.endsWith('.excalidraw')
}
export function isFileFromDataloom(path: string): boolean {
return path.endsWith('.loom')
}
@@ -219,7 +238,7 @@ export function warnDebug(...args: any[]): void {
printDebug(console.warn, ...args)
}
let printDebugEnabled= false
let printDebugEnabled = false
export function enablePrintDebug(enable: boolean): void {
printDebugEnabled = enable
}