Skip to content

Commit

Permalink
add excludedChars config
Browse files Browse the repository at this point in the history
Signed-off-by: Augustin Husson <[email protected]>
  • Loading branch information
Nexucis committed Jul 16, 2024
1 parent b6869bc commit d961dd5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 29 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ The options passed in the method take precedence over the one passed in the cont

Indicates whether comparisons should be case-sensitive.

### excludedChars

* **Type**: `array of string`
* **Default**: `[]`

List of characters that should be ignored in the pattern or in the word used for matching

### includeMatches

* **Type**: `boolean`
Expand Down
13 changes: 13 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,19 @@ describe('partial match test', () => {
score: 4.4,
},
},
{
title: 'default conf: ignoring space',
pattern: 'my awesome text',
text: 'my-awesome-text',
config: {
excludedChars: [' '],
},
result: {
original: 'my-awesome-text',
rendered: 'my-awesome-text',
score: 68.86666666666666,
},
},
{
title: 'rendering conf: fuzzy match',
pattern: 'met',
Expand Down
73 changes: 44 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,37 +73,11 @@ export function score(intervals: FuzzyMatchingInterval[], strLength: number): nu
return result
}

// generateMatchingInterval will iterate other the given text to find the different char that matched the given pattern
function generateMatchingInterval(pattern: string, text: string, idxText: number): null | {
score: number;
intervals: FuzzyMatchingInterval[]
} {
let patternIdx = 0;
const intervals = [];
for (let i = idxText; i < text.length && patternIdx < pattern.length;) {
if (text[i] === pattern[patternIdx]) {
const interval = { from: i, to: i }
patternIdx++;
i++;
for (let j = i; j < text.length && patternIdx < pattern.length && text[j] === pattern[patternIdx]; j++) {
interval.to = j
patternIdx++
i = j
}
intervals.push(interval)
}
i++;
}
if (intervals.length === 0 || patternIdx !== pattern.length) {
return null;
}
return { score: score(intervals, text.length), intervals: intervals }
}

export interface FuzzyConfiguration {
caseSensitive?: boolean;
// List of characters that should be ignored when searching the pattern in the string
// List of characters that should be ignored in the pattern or in the word used for matching
excludedChars?: string[];
// Whenever the result should contain the list of intervals.
includeMatches?: boolean;
// If true, results will be sorted based on the score.
shouldSort?: boolean;
Expand Down Expand Up @@ -211,7 +185,7 @@ export class Fuzzy {
// For example, given the pattern `bac` and the text `babac`
// instead of matching `<ba>ba<c>, it will match ba<bac> which has a better score than the previous one.
if (localText[i] === localPattern[0]) {
const matchingResult = generateMatchingInterval(localPattern, localText, i);
const matchingResult = this.generateMatchingInterval(localPattern, localText, i, conf);
if (matchingResult === null) {
break
}
Expand Down Expand Up @@ -272,6 +246,47 @@ export class Fuzzy {
}
return str
}

// generateMatchingInterval will iterate other the given text to find the different char that matched the given pattern
private generateMatchingInterval(pattern: string, text: string, idxText: number, conf?: FuzzyConfiguration): null | {
score: number;
intervals: FuzzyMatchingInterval[]
} {
let excludedChars: string[] = []
if (conf?.excludedChars !== undefined) {
excludedChars = conf.excludedChars
} else if (this.conf.excludedChars !== undefined) {
excludedChars = this.conf.excludedChars
}
let patternIdx = 0;
const intervals = [];
for (let i = idxText; i < text.length && patternIdx < pattern.length;) {
if (excludedChars.includes(text[i])) {
i++
continue
}
if (excludedChars.includes(pattern[patternIdx])) {
patternIdx++
continue
}
if (text[i] === pattern[patternIdx]) {
const interval = { from: i, to: i }
patternIdx++;
i++;
for (let j = i; j < text.length && patternIdx < pattern.length && text[j] === pattern[patternIdx]; j++) {
interval.to = j
patternIdx++
i = j
}
intervals.push(interval)
}
i++;
}
if (intervals.length === 0 || patternIdx !== pattern.length) {
return null;
}
return { score: score(intervals, text.length), intervals: intervals }
}
}

const fuz = new Fuzzy()
Expand Down

0 comments on commit d961dd5

Please sign in to comment.