2 changed files with 67 additions and 67 deletions
@ -1,106 +1,106 @@ |
|||||||
const addWeightWithBoost = (option, query) => { |
const addWeightWithBoost = (option, query) => { |
||||||
option.weight = calculateWeight(option.clean, query) * option.clean.boost; |
option.weight = calculateWeight(option.clean, query) * option.clean.boost |
||||||
|
|
||||||
return option; |
return option |
||||||
}; |
} |
||||||
|
|
||||||
const clean = (text) => |
const clean = (text) => |
||||||
text |
text |
||||||
.trim() |
.trim() |
||||||
.replace(/['’]/g, "") |
.replace(/['’]/g, '') |
||||||
.replace(/[.,"/#!$%^&*;:{}=\-_`~()]/g, " ") |
.replace(/[.,"/#!$%^&*;:{}=\-_`~()]/g, ' ') |
||||||
.toLowerCase(); |
.toLowerCase() |
||||||
|
|
||||||
const cleanseOption = (option) => { |
const cleanseOption = (option) => { |
||||||
option.clean = { |
option.clean = { |
||||||
name: clean(option.name), |
name: clean(option.name), |
||||||
nameWithoutStopWords: removeStopWords(option.name), |
nameWithoutStopWords: removeStopWords(option.name), |
||||||
boost: option.boost || 1, |
boost: option.boost || 1 |
||||||
}; |
} |
||||||
|
|
||||||
return option; |
return option |
||||||
}; |
} |
||||||
|
|
||||||
const hasWeight = (option) => option.weight > 0; |
const hasWeight = (option) => option.weight > 0 |
||||||
|
|
||||||
const byWeightThenAlphabetically = (a, b) => { |
const byWeightThenAlphabetically = (a, b) => { |
||||||
if (a.weight > b.weight) return -1; |
if (a.weight > b.weight) return -1 |
||||||
if (a.weight < b.weight) return 1; |
if (a.weight < b.weight) return 1 |
||||||
if (a.name < b.name) return -1; |
if (a.name < b.name) return -1 |
||||||
if (a.name > b.name) return 1; |
if (a.name > b.name) return 1 |
||||||
|
|
||||||
return 0; |
return 0 |
||||||
}; |
} |
||||||
|
|
||||||
const optionName = (option) => option.name; |
const optionName = (option) => option.name |
||||||
const exactMatch = (word, query) => word === query; |
const exactMatch = (word, query) => word === query |
||||||
|
|
||||||
const startsWithRegExp = (query) => new RegExp("\\b" + query, "i"); |
const startsWithRegExp = (query) => new RegExp('\\b' + query, 'i') |
||||||
const startsWith = (word, query) => word.search(startsWithRegExp(query)) === 0; |
const startsWith = (word, query) => word.search(startsWithRegExp(query)) === 0 |
||||||
|
|
||||||
const wordsStartsWithQuery = (word, regExps) => |
const wordsStartsWithQuery = (word, regExps) => |
||||||
regExps.every((regExp) => word.search(regExp) >= 0); |
regExps.every((regExp) => word.search(regExp) >= 0) |
||||||
|
|
||||||
const calculateWeight = ({ name, nameWithoutStopWords }, query) => { |
const calculateWeight = ({ name, nameWithoutStopWords }, query) => { |
||||||
const queryWithoutStopWords = removeStopWords(query); |
const queryWithoutStopWords = removeStopWords(query) |
||||||
|
|
||||||
if (exactMatch(name, query)) return 100; |
if (exactMatch(name, query)) return 100 |
||||||
if (exactMatch(nameWithoutStopWords, queryWithoutStopWords)) return 95; |
if (exactMatch(nameWithoutStopWords, queryWithoutStopWords)) return 95 |
||||||
|
|
||||||
if (startsWith(name, query)) return 60; |
if (startsWith(name, query)) return 60 |
||||||
if (startsWith(nameWithoutStopWords, queryWithoutStopWords)) return 55; |
if (startsWith(nameWithoutStopWords, queryWithoutStopWords)) return 55 |
||||||
const startsWithRegExps = queryWithoutStopWords |
const startsWithRegExps = queryWithoutStopWords |
||||||
.split(/\s+/) |
.split(/\s+/) |
||||||
.map(startsWithRegExp); |
.map(startsWithRegExp) |
||||||
|
|
||||||
if (wordsStartsWithQuery(nameWithoutStopWords, startsWithRegExps)) return 25; |
if (wordsStartsWithQuery(nameWithoutStopWords, startsWithRegExps)) return 25 |
||||||
|
|
||||||
return 0; |
return 0 |
||||||
}; |
} |
||||||
|
|
||||||
const stopWords = ["the", "of", "in", "and", "at", "&"]; |
const stopWords = ['the', 'of', 'in', 'and', 'at', '&'] |
||||||
|
|
||||||
const removeStopWords = (text) => { |
const removeStopWords = (text) => { |
||||||
const isAllStopWords = text |
const isAllStopWords = text |
||||||
.trim() |
.trim() |
||||||
.split(" ") |
.split(' ') |
||||||
.every((word) => stopWords.includes(word)); |
.every((word) => stopWords.includes(word)) |
||||||
|
|
||||||
if (isAllStopWords) { |
if (isAllStopWords) { |
||||||
return text; |
return text |
||||||
} |
} |
||||||
|
|
||||||
const regex = new RegExp( |
const regex = new RegExp( |
||||||
stopWords.map((word) => `(\\s+)?${word}(\\s+)?`).join("|"), |
stopWords.map((word) => `(\\s+)?${word}(\\s+)?`).join('|'), |
||||||
"gi" |
'gi' |
||||||
); |
) |
||||||
return text.replace(regex, " ").trim(); |
return text.replace(regex, ' ').trim() |
||||||
}; |
} |
||||||
|
|
||||||
export const sort = (query, options) => { |
export const sort = (query, options) => { |
||||||
const cleanQuery = clean(query); |
const cleanQuery = clean(query) |
||||||
|
|
||||||
return options |
return options |
||||||
.map(cleanseOption) |
.map(cleanseOption) |
||||||
.map((option) => addWeightWithBoost(option, cleanQuery)) |
.map((option) => addWeightWithBoost(option, cleanQuery)) |
||||||
.filter(hasWeight) |
.filter(hasWeight) |
||||||
.sort(byWeightThenAlphabetically) |
.sort(byWeightThenAlphabetically) |
||||||
.map(optionName); |
.map(optionName) |
||||||
}; |
} |
||||||
|
|
||||||
export const suggestion = (value, options) => { |
export const suggestion = (value, options) => { |
||||||
const option = options.find((o) => o.name === value); |
const option = options.find((o) => o.name === value) |
||||||
if (option) { |
if (option) { |
||||||
const html = `<span>${value}</span>`; |
const html = `<span>${value}</span>` |
||||||
return html; |
return html |
||||||
} else { |
} else { |
||||||
return `<span>No results found</span>`; |
return '<span>No results found</span>' |
||||||
} |
} |
||||||
}; |
} |
||||||
|
|
||||||
export const enhanceOption = (option) => { |
export const enhanceOption = (option) => { |
||||||
return { |
return { |
||||||
name: option.label, |
name: option.label, |
||||||
boost: parseFloat(option.getAttribute("data-boost")) || 1, |
boost: parseFloat(option.getAttribute('data-boost')) || 1 |
||||||
}; |
} |
||||||
}; |
} |
||||||
|
Loading…
Reference in new issue