first commit
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
function normalizeSearchText(value) {
|
||||
return String(value ?? '').trim().toLocaleLowerCase().replace(/\s+/g, ' ');
|
||||
}
|
||||
|
||||
function ingredientNames(recipe) {
|
||||
return (recipe.ingredientGroups ?? [])
|
||||
.flatMap((group) => group.items ?? [])
|
||||
.map((item) => item.name)
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export function rankRecipeMatch(recipe, query) {
|
||||
const normalizedQuery = normalizeSearchText(query);
|
||||
if (!normalizedQuery) return { score: 0, matchedIngredients: [] };
|
||||
|
||||
const ingredients = ingredientNames(recipe);
|
||||
const matchedIngredients = ingredients.filter((name) => (
|
||||
normalizeSearchText(name).includes(normalizedQuery)
|
||||
));
|
||||
const hasExactIngredient = matchedIngredients.some((name) => (
|
||||
normalizeSearchText(name) === normalizedQuery
|
||||
));
|
||||
const title = normalizeSearchText(recipe.title);
|
||||
const tags = (recipe.tags ?? []).map(normalizeSearchText);
|
||||
const summary = normalizeSearchText(recipe.summary);
|
||||
|
||||
let score = 0;
|
||||
if (hasExactIngredient) score = 500;
|
||||
else if (matchedIngredients.length > 0) score = 400;
|
||||
else if (title === normalizedQuery) score = 350;
|
||||
else if (title.includes(normalizedQuery)) score = 300;
|
||||
else if (tags.includes(normalizedQuery)) score = 250;
|
||||
else if (tags.some((tag) => tag.includes(normalizedQuery))) score = 200;
|
||||
else if (summary.includes(normalizedQuery)) score = 100;
|
||||
|
||||
return { score, matchedIngredients };
|
||||
}
|
||||
|
||||
export function searchRecipes(recipes, query) {
|
||||
if (!normalizeSearchText(query)) {
|
||||
return recipes.map((recipe) => ({ recipe, score: 0, matchedIngredients: [] }));
|
||||
}
|
||||
|
||||
return recipes
|
||||
.map((recipe, index) => ({ recipe, index, ...rankRecipeMatch(recipe, query) }))
|
||||
.filter(({ score }) => score > 0)
|
||||
.sort((a, b) => b.score - a.score || a.index - b.index)
|
||||
.map(({ recipe, score, matchedIngredients }) => ({ recipe, score, matchedIngredients }));
|
||||
}
|
||||
Reference in New Issue
Block a user