diff --git a/frontend/composables/recipes/use-recipe-ingredients.test.ts b/frontend/composables/recipes/use-recipe-ingredients.test.ts
index ed2870535..caa3b4ef6 100644
--- a/frontend/composables/recipes/use-recipe-ingredients.test.ts
+++ b/frontend/composables/recipes/use-recipe-ingredients.test.ts
@@ -205,4 +205,34 @@ describe("parseIngredientText", () => {
expect(parseIngredientText(ingredient)).toEqual("2 tablespoons diced onion");
});
+
+ test("decimal below minimum precision shows < 0.001", () => {
+ const ingredient = createRecipeIngredient({
+ quantity: 0.0001,
+ unit: { id: "1", name: "cup", useAbbreviation: false },
+ food: { id: "1", name: "salt" },
+ });
+
+ expect(parseIngredientText(ingredient)).toEqual("< 0.001 cup salt");
+ });
+
+ test("fraction below minimum denominator shows < 1/10", () => {
+ const ingredient = createRecipeIngredient({
+ quantity: 0.05,
+ unit: { id: "1", name: "cup", fraction: true, useAbbreviation: false },
+ food: { id: "1", name: "salt" },
+ });
+
+ expect(parseIngredientText(ingredient)).toEqual("< 1⁄10 cup salt");
+ });
+
+ test("fraction below minimum denominator without formatting shows < 1/10", () => {
+ const ingredient = createRecipeIngredient({
+ quantity: 0.05,
+ unit: { id: "1", name: "cup", fraction: true, useAbbreviation: false },
+ food: { id: "1", name: "salt" },
+ });
+
+ expect(parseIngredientText(ingredient, 1, false)).toEqual("< 1/10 cup salt");
+ });
});
diff --git a/frontend/composables/recipes/use-recipe-ingredients.ts b/frontend/composables/recipes/use-recipe-ingredients.ts
index 8872bb6d9..0e839af73 100644
--- a/frontend/composables/recipes/use-recipe-ingredients.ts
+++ b/frontend/composables/recipes/use-recipe-ingredients.ts
@@ -5,6 +5,9 @@ import type { CreateIngredientFood, CreateIngredientUnit, IngredientFood, Ingred
const { frac } = useFraction();
+const FRAC_MIN_DENOM = 10;
+const DECIMAL_PRECISION = 3;
+
export function sanitizeIngredientHTML(rawHtml: string) {
return DOMPurify.sanitize(rawHtml, {
USE_PROFILES: { html: true },
@@ -91,11 +94,19 @@ export function useIngredientTextParser() {
// casting to number is required as sometimes quantity is a string
if (quantity && Number(quantity) !== 0) {
+ const scaledQuantity = Number((quantity * scale));
+
if (unit && !unit.fraction) {
- returnQty = Number((quantity * scale).toPrecision(3)).toString();
+ const minVal = 10 ** -DECIMAL_PRECISION;
+ returnQty = scaledQuantity >= minVal
+ ? Number(scaledQuantity.toPrecision(DECIMAL_PRECISION)).toString()
+ : `< ${minVal}`;
}
else {
- const fraction = frac(quantity * scale, 10, true);
+ const minVal = 1 / FRAC_MIN_DENOM;
+ const isUnderMinVal = !(scaledQuantity >= minVal);
+
+ const fraction = !isUnderMinVal ? frac(scaledQuantity, FRAC_MIN_DENOM, true) : [0, 1, FRAC_MIN_DENOM];
if (fraction[0] !== undefined && fraction[0] > 0) {
returnQty += fraction[0];
}
@@ -105,6 +116,10 @@ export function useIngredientTextParser() {
? `${fraction[1]}⁄${fraction[2]}`
: ` ${fraction[1]}/${fraction[2]}`;
}
+
+ if (isUnderMinVal) {
+ returnQty = `< ${returnQty}`;
+ }
}
}