Skip to content

Commit

Permalink
#287 - Fixed & improved highlightText() + a bit of cleaning (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
scambier authored Sep 11, 2023
1 parent d651278 commit 0558b9a
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/search/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export class Query {
return this.getTags().map(o => o.replace(/^#/, ''))
}

/**
*
* @returns An array of strings that are in quotes
*/
public getExactTerms(): string[] {
return [
...new Set(
Expand Down
72 changes: 34 additions & 38 deletions src/tools/text-processing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import {
excerptBefore,
} from 'src/globals'
import { settings } from 'src/settings'
import { escapeRegex, warnDebug } from './utils'
import { warnDebug } from './utils'
import type { Query } from 'src/search/query'
import { Notice } from 'obsidian'
import { escapeRegExp } from 'lodash-es'

export function highlighterGroups(_substring: string, ...args: any[]) {
// args[0] is the single char preceding args[1], which is the word we want to highlight
Expand All @@ -21,39 +22,35 @@ export function highlighterGroups(_substring: string, ...args: any[]) {
return '<no content>'
}

/**
* Wraps the matches in the text with a <span> element and a highlight class
* @param text
* @param matches
* @returns The html string with the matches highlighted
*/
export function highlightText(text: string, matches: SearchMatch[]): string {
matches.forEach(matchInfo => {
const matchRegex = new RegExp(`\\b${matchInfo.match}\\b`, 'giu')
const matchOffsets = []

let match
while ((match = matchRegex.exec(text)) !== null) {
matchOffsets.push({ index: match.index, text: match[0] })
}

if (!matchOffsets.length) {
return text
}

const closestMatch = matchOffsets.reduce((prev, curr) => {
return Math.abs(curr.index - matchInfo.offset) <
Math.abs(prev.index - matchInfo.offset)
? curr
: prev
})

if (matchOffsets.includes(closestMatch)) {
const originalMatch = closestMatch.text
text =
text.substring(0, closestMatch.index) +
`<span class="${highlightClass}">` +
originalMatch +
'</span>' +
text.substring(closestMatch.index + originalMatch.length)
}
})

return text
try {
return text.replace(
new RegExp(
matches
.map(matchInfo => `\\b${escapeRegExp(matchInfo.match)}\\b`)
.join('|'),
'giu'
),
match => {
const matchInfo = matches.find(info =>
match.match(new RegExp(`\\b${escapeRegExp(info.match)}\\b`, 'giu'))
)
if (matchInfo) {
return `<span class="${highlightClass}">${match}</span>`
}
return match
}
)
} catch (e) {
console.error('Omnisearch - Error in highlightText()', e)
return text
}
}

export function escapeHTML(html: string): string {
Expand Down Expand Up @@ -94,10 +91,9 @@ export function stringsToRegex(strings: string[]): RegExp {
? `^|${SPACE_OR_PUNCTUATION_UNIQUE.source}|\-|[A-Z]`
: `^|${SPACE_OR_PUNCTUATION_UNIQUE.source}|\-`) +
')' +
`(${strings.map(s => escapeRegex(s)).join('|')})`
`(${strings.map(s => escapeRegExp(s)).join('|')})`

const reg = new RegExp(`${joined}`, 'gu')
return reg
return new RegExp(`${joined}`, 'gu')
}

export function getMatches(
Expand All @@ -122,8 +118,8 @@ export function getMatches(
}
}

// If the query can be found "as is" in the text, put this match first
if (query) {
// If the query is more than 1 token and can be found "as is" in the text, put this match first
if (query && query.query.text.length > 1) {
const best = text.indexOf(query.segmentsToStr())
if (best > -1 && matches.find(m => m.offset === best)) {
matches = matches.filter(m => m.offset !== best)
Expand Down
6 changes: 0 additions & 6 deletions src/tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ export function wait(ms: number): Promise<void> {
})
}

// https://stackoverflow.com/a/3561711
// but we enclose special chars in brackets to avoid them being interpreted as regex
export function escapeRegex(str: string): string {
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '[$&]')
}

/**
* Returns the positions of all occurences of `val` inside of `text`
* https://stackoverflow.com/a/58828841
Expand Down

0 comments on commit 0558b9a

Please sign in to comment.