mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 07:14:11 +00:00
[Refactor/TS] Simplify node filter logic (#3275)
This commit is contained in:
@@ -1,6 +1,80 @@
|
||||
import Fuse, { FuseOptionKey, FuseSearchOptions, IFuseOptions } from 'fuse.js'
|
||||
|
||||
type SearchAuxScore = number[]
|
||||
export type SearchAuxScore = number[]
|
||||
|
||||
export interface FuseFilterWithValue<T, O = string> {
|
||||
filterDef: FuseFilter<T, O>
|
||||
value: O
|
||||
}
|
||||
|
||||
export class FuseFilter<T, O = string> {
|
||||
public readonly fuseSearch: FuseSearch<O>
|
||||
/** The unique identifier for the filter. */
|
||||
public readonly id: string
|
||||
/** The name of the filter for display purposes. */
|
||||
public readonly name: string
|
||||
/** The sequence of characters to invoke the filter. */
|
||||
public readonly invokeSequence: string
|
||||
/** A function that returns the options for the filter. */
|
||||
public readonly getItemOptions: (item: T) => O[]
|
||||
|
||||
constructor(
|
||||
data: T[],
|
||||
options: {
|
||||
id: string
|
||||
name: string
|
||||
invokeSequence: string
|
||||
getItemOptions: (item: T) => O[]
|
||||
fuseOptions?: IFuseOptions<O>
|
||||
}
|
||||
) {
|
||||
this.id = options.id
|
||||
this.name = options.name
|
||||
this.invokeSequence = options.invokeSequence
|
||||
this.getItemOptions = options.getItemOptions
|
||||
|
||||
this.fuseSearch = new FuseSearch(this.getAllNodeOptions(data), {
|
||||
fuseOptions: options.fuseOptions
|
||||
})
|
||||
}
|
||||
|
||||
public getAllNodeOptions(data: T[]): O[] {
|
||||
const options = new Set<O>()
|
||||
for (const item of data) {
|
||||
for (const option of this.getItemOptions(item)) {
|
||||
options.add(option)
|
||||
}
|
||||
}
|
||||
return Array.from(options)
|
||||
}
|
||||
|
||||
public matches(
|
||||
item: T,
|
||||
value: O,
|
||||
extraOptions: {
|
||||
wildcard?: O
|
||||
} = {}
|
||||
): boolean {
|
||||
const { wildcard } = extraOptions
|
||||
|
||||
if (wildcard && value === wildcard) {
|
||||
return true
|
||||
}
|
||||
const options = this.getItemOptions(item)
|
||||
return (
|
||||
options.includes(value) ||
|
||||
(!!wildcard && options.some((option) => option === wildcard))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export interface FuseSearchable {
|
||||
postProcessSearchScores: (scores: SearchAuxScore) => SearchAuxScore
|
||||
}
|
||||
|
||||
function isFuseSearchable(item: any): item is FuseSearchable {
|
||||
return 'postProcessSearchScores' in item
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around Fuse.js that provides a more type-safe API.
|
||||
@@ -56,20 +130,22 @@ export class FuseSearch<T> {
|
||||
|
||||
public calcAuxScores(query: string, entry: T, score: number): SearchAuxScore {
|
||||
let values: string[] = []
|
||||
if (!this.keys.length) values = [entry as string]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
else values = this.keys.map((x) => entry[x])
|
||||
if (typeof entry === 'string') {
|
||||
values = [entry]
|
||||
} else if (typeof entry === 'object' && entry !== null) {
|
||||
values = this.keys
|
||||
.map((x) => entry[x as keyof T])
|
||||
.filter((x) => typeof x === 'string') as string[]
|
||||
}
|
||||
const scores = values.map((x) => this.calcAuxSingle(query, x, score))
|
||||
let result = scores.sort(this.compareAux)[0]
|
||||
|
||||
const deprecated = values.some((x) =>
|
||||
x.toLocaleLowerCase().includes('deprecated')
|
||||
)
|
||||
result[0] += deprecated && result[0] != 0 ? 5 : 0
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (entry['postProcessSearchScores']) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
result = entry['postProcessSearchScores'](result) as SearchAuxScore
|
||||
result[0] += deprecated && result[0] !== 0 ? 5 : 0
|
||||
if (isFuseSearchable(entry)) {
|
||||
result = entry.postProcessSearchScores(result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user