Merge pull request #351 from teaxyz/fuse-search

implement Fuse index use for search
This commit is contained in:
Chris Waters 2023-05-17 11:43:02 -04:00 committed by GitHub
commit 146ce40cd7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -94,8 +94,9 @@
overflow: hidden; overflow: hidden;
} }
</style> </style>
<script async src="https://unpkg.com/string-similarity@4.0.1/umd/string-similarity.min.js"></script> <script language="javascript" type="module">
<script language="javascript" type="text/javascript"> import Fuse from 'https://cdn.jsdelivr.net/npm/fuse.js@6.6.2/dist/fuse.esm.js'
const sortOptions = { const sortOptions = {
popularity: 'popularity', popularity: 'popularity',
last_modified: 'last_modified', last_modified: 'last_modified',
@ -108,7 +109,11 @@
const grid = document.getElementById('packageGrid'); const grid = document.getElementById('packageGrid');
const packagesCache = Array.from(grid.children).filter((e) => e.dataset && e.dataset.name); const packagesCache = Array.from(grid.children).filter((e) => e.dataset && e.dataset.name);
const packagesIndex = new Fuse(packagesCache.map((p) => p.dataset), {
keys: ["name", "maintainer", "description"],
minMatchCharLength: 3,
threshold: 0.3
});
function debounce(fn, delay) { function debounce(fn, delay) {
var timer = null; var timer = null;
return function () { return function () {
@ -125,20 +130,21 @@
const noResult = document.getElementById('noResult'); const noResult = document.getElementById('noResult');
if (searchInput.value) { if (searchInput.value) {
const term = searchInput.value; const term = searchInput.value;
const res = packagesIndex.search(term, { limit: 5 });
const matchedPackages = res.map((r) => r.item.name);
const packages = getPackageThumbs(); const packages = getPackageThumbs();
for(let pkg of packages) {
pkg.match_score = getMatchScore(term, pkg.dataset); const sortedPackages = [
} ...matchedPackages.map((mp) => packages.find((p) => p.dataset.name === mp)),
const sortedPackages = packages.sort((a, b) => { ...packages.filter((p) => !matchedPackages.includes(p.dataset.name)),
return b.match_score - (a ? a.match_score : 0); ]
});
const grid = document.getElementById('packageGrid'); const grid = document.getElementById('packageGrid');
grid.textContent = ''; grid.textContent = '';
let searchCount = 0; let searchCount = 0;
for(const sp of sortedPackages) { for(const sp of sortedPackages) {
const score = getMatchScore(term, sp.dataset); if (matchedPackages.includes(sp.dataset.name)) {
if (score > 20) {
sp.classList.remove('hidden'); sp.classList.remove('hidden');
searchCount++; searchCount++;
} else { } else {
@ -214,14 +220,6 @@
} }
} }
function getMatchScore(term, dataset) {
// provide higher value with name
const { name, maintainer, description } = dataset;
const exactMatch = [maintainer, name].join(" ").toLocaleLowerCase().includes(term.toLocaleLowerCase());
const nameScore = stringSimilarity.compareTwoStrings(name, term);
const descriptionScore = stringSimilarity.compareTwoStrings(description, term);
return (nameScore*80) + (descriptionScore*20) + (exactMatch ? 100 : 0);
}
const loadMoreButton = document.getElementById('loadMorePackagesBtn'); const loadMoreButton = document.getElementById('loadMorePackagesBtn');
if (showAllPackages) { if (showAllPackages) {