mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-02 20:15:24 +02:00
feat: improve readability of ingredients list (#2502)
* feat: improve readability of notes in ingredients list Makes the notes in the ingredients list more readable by making them slightly opaque. This creates a better visual separation between the notes and the rest of the ingredient. * Use server display if available * Move note to newline and make quantity more distinct * Use safeMarkdown for shopping list * Use component * Wrap unit in accent color * Update RecipeIngredientListItem to set food in bold
This commit is contained in:
parent
2151451634
commit
50a92c165c
7 changed files with 140 additions and 25 deletions
|
@ -1,6 +1,6 @@
|
|||
export { useFraction } from "./use-fraction";
|
||||
export { useRecipe } from "./use-recipe";
|
||||
export { useRecipes, recentRecipes, allRecipes, useLazyRecipes } from "./use-recipes";
|
||||
export { parseIngredientText } from "./use-recipe-ingredients";
|
||||
export { parseIngredientText, useParsedIngredientText } from "./use-recipe-ingredients";
|
||||
export { useTools } from "./use-recipe-tools";
|
||||
export { useRecipeMeta } from "./use-recipe-meta";
|
||||
|
|
42
frontend/composables/recipes/use-recipe-ingredients.test.ts
Normal file
42
frontend/composables/recipes/use-recipe-ingredients.test.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { describe, test, expect } from "vitest";
|
||||
import { parseIngredientText } from "./use-recipe-ingredients";
|
||||
import { RecipeIngredient } from "~/lib/api/types/recipe";
|
||||
|
||||
describe(parseIngredientText.name, () => {
|
||||
const createRecipeIngredient = (overrides: Partial<RecipeIngredient>): RecipeIngredient => ({
|
||||
quantity: 1,
|
||||
food: {
|
||||
id: "1",
|
||||
name: "Item 1",
|
||||
},
|
||||
unit: {
|
||||
id: "1",
|
||||
name: "cup",
|
||||
},
|
||||
...overrides,
|
||||
});
|
||||
|
||||
test("uses ingredient note if disableAmount: true", () => {
|
||||
const ingredient = createRecipeIngredient({ note: "foo" });
|
||||
|
||||
expect(parseIngredientText(ingredient, true)).toEqual("foo");
|
||||
});
|
||||
|
||||
test("adds note section if note present", () => {
|
||||
const ingredient = createRecipeIngredient({ note: "custom note" });
|
||||
|
||||
expect(parseIngredientText(ingredient, false)).toContain("custom note");
|
||||
});
|
||||
|
||||
test("ingredient text with fraction", () => {
|
||||
const ingredient = createRecipeIngredient({ quantity: 1.5, unit: { fraction: true, id: "1", name: "cup" } });
|
||||
|
||||
expect(parseIngredientText(ingredient, false)).contain("1 <sup>1</sup>").and.to.contain("<sub>2</sub>");
|
||||
});
|
||||
|
||||
test("sanitizes html", () => {
|
||||
const ingredient = createRecipeIngredient({ note: "<script>alert('foo')</script>" });
|
||||
|
||||
expect(parseIngredientText(ingredient, false)).not.toContain("<script>");
|
||||
});
|
||||
});
|
|
@ -10,11 +10,14 @@ function sanitizeIngredientHTML(rawHtml: string) {
|
|||
});
|
||||
}
|
||||
|
||||
export function parseIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale = 1): string {
|
||||
// TODO: the backend now supplies a "display" property which does this for us, so we don't need this function
|
||||
|
||||
export function useParsedIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale = 1) {
|
||||
if (disableAmount) {
|
||||
return ingredient.note || "";
|
||||
return {
|
||||
name: ingredient.note ? sanitizeIngredientHTML(ingredient.note) : undefined,
|
||||
quantity: undefined,
|
||||
unit: undefined,
|
||||
note: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const { quantity, food, unit, note } = ingredient;
|
||||
|
@ -43,6 +46,17 @@ export function parseIngredientText(ingredient: RecipeIngredient, disableAmount:
|
|||
}
|
||||
}
|
||||
|
||||
const text = `${returnQty} ${unitDisplay || " "} ${food?.name || " "} ${note || " "}`.replace(/ {2,}/g, " ");
|
||||
return {
|
||||
quantity: returnQty ? sanitizeIngredientHTML(returnQty) : undefined,
|
||||
unit: unitDisplay ? sanitizeIngredientHTML(unitDisplay) : undefined,
|
||||
name: food?.name ? sanitizeIngredientHTML(food.name) : undefined,
|
||||
note: note ? sanitizeIngredientHTML(note) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale = 1): string {
|
||||
const { quantity, unit, name, note } = useParsedIngredientText(ingredient, disableAmount, scale);
|
||||
|
||||
const text = `${quantity || ""} ${unit || ""} ${name || ""} ${note || ""}`.replace(/ {2,}/g, " ").trim();
|
||||
return sanitizeIngredientHTML(text);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue