import parseQuery from './parseQuery'import FuzzyMatch from './FuzzyMatch'import IncludeMatch from './IncludeMatch'import Config from '../../core/config'
const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type])
export default class ExtendedSearch { constructor( pattern, { isCaseSensitive = Config.isCaseSensitive, includeMatches = Config.includeMatches, minMatchCharLength = Config.minMatchCharLength, findAllMatches = Config.findAllMatches, location = Config.location, threshold = Config.threshold, distance = Config.distance } = {} ) { this.query = null this.options = { isCaseSensitive, includeMatches, minMatchCharLength, findAllMatches, location, threshold, distance }
this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase() this.query = parseQuery(this.pattern, this.options) }
static condition(_, options) { return options.useExtendedSearch }
searchIn(text) { const query = this.query
if (!query) { return { isMatch: false, score: 1 } }
const { includeMatches, isCaseSensitive } = this.options
text = isCaseSensitive ? text : text.toLowerCase()
let numMatches = 0 let allIndices = [] let totalScore = 0
for (let i = 0, qLen = query.length; i < qLen; i += 1) { const searchers = query[i]
allIndices.length = 0 numMatches = 0
for (let j = 0, pLen = searchers.length; j < pLen; j += 1) { const searcher = searchers[j] const { isMatch, indices, score } = searcher.search(text)
if (isMatch) { numMatches += 1 totalScore += score if (includeMatches) { const type = searcher.constructor.type if (MultiMatchSet.has(type)) { allIndices = [...allIndices, ...indices] } else { allIndices.push(indices) } } } else { totalScore = 0 numMatches = 0 allIndices.length = 0 break } }
if (numMatches) { let result = { isMatch: true, score: totalScore / numMatches }
if (includeMatches) { result.indices = allIndices }
return result } }
return { isMatch: false, score: 1 } }}