Files
mealie/frontend/composables/recipes/use-recipe-ingredients.ts
Hugo van Rijswijk 50a92c165c 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
2023-08-21 15:32:09 +00:00

63 lines
2.0 KiB
TypeScript

import DOMPurify from "isomorphic-dompurify";
import { useFraction } from "./use-fraction";
import { RecipeIngredient } from "~/lib/api/types/recipe";
const { frac } = useFraction();
function sanitizeIngredientHTML(rawHtml: string) {
return DOMPurify.sanitize(rawHtml, {
USE_PROFILES: { html: true },
ALLOWED_TAGS: ["b", "q", "i", "strong", "sup"],
});
}
export function useParsedIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale = 1) {
if (disableAmount) {
return {
name: ingredient.note ? sanitizeIngredientHTML(ingredient.note) : undefined,
quantity: undefined,
unit: undefined,
note: undefined,
};
}
const { quantity, food, unit, note } = ingredient;
let returnQty = "";
let unitDisplay = unit?.name;
// casting to number is required as sometimes quantity is a string
if (quantity && Number(quantity) !== 0) {
if (unit?.fraction) {
const fraction = frac(quantity * scale, 10, true);
if (fraction[0] !== undefined && fraction[0] > 0) {
returnQty += fraction[0];
}
if (fraction[1] > 0) {
returnQty += ` <sup>${fraction[1]}</sup>&frasl;<sub>${fraction[2]}</sub>`;
}
} else {
returnQty = (quantity * scale).toString();
}
if (unit?.useAbbreviation && unit.abbreviation) {
unitDisplay = unit.abbreviation;
}
}
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);
}