+34
-14
@@ -30,33 +30,53 @@ function formatQuantity(value) {
|
||||
));
|
||||
if (Math.abs(fraction - remainder) <= 0.02) {
|
||||
const adjustedWhole = fraction === 1 ? whole + 1 : whole;
|
||||
return `${adjustedWhole || ""}${adjustedWhole && symbol ? " " : ""}${symbol}` || "0";
|
||||
return {
|
||||
value: `${adjustedWhole || ""}${adjustedWhole && symbol ? " " : ""}${symbol}` || "0",
|
||||
approximate: false
|
||||
};
|
||||
}
|
||||
return Number(value.toFixed(2)).toString();
|
||||
return { value: Number(value.toFixed(2)).toString(), approximate: true };
|
||||
}
|
||||
|
||||
function scaleIngredientWithStatus(ingredient, factor) {
|
||||
if (typeof ingredient !== "string" || factor === 1) {
|
||||
return { value: ingredient, status: "unchanged" };
|
||||
}
|
||||
const match = ingredient.match(/^(\s*)(?:(\d+)\s+)?(\d+\/\d+|\d+(?:\.\d+)?|[¼½¾⅓⅔⅛⅜⅝⅞])(?=\s|[a-zA-Z])/);
|
||||
if (!match) {
|
||||
const hasLeadingQuantity = /^\s*(?:\d|[¼½¾⅓⅔⅛⅜⅝⅞])/.test(ingredient);
|
||||
return { value: ingredient, status: hasLeadingQuantity ? "unscalable" : "unquantified" };
|
||||
}
|
||||
const whole = Number(match[2] || 0);
|
||||
const quantity = parseQuantity(match[3]);
|
||||
if (!Number.isFinite(quantity)) return { value: ingredient, status: "unscalable" };
|
||||
const formatted = formatQuantity((whole + quantity) * factor);
|
||||
const replacement = `${match[1]}${formatted.value}`;
|
||||
return {
|
||||
value: replacement + ingredient.slice(match[0].length),
|
||||
status: formatted.approximate ? "approximate" : "scaled"
|
||||
};
|
||||
}
|
||||
|
||||
function scaleIngredient(ingredient, factor) {
|
||||
if (typeof ingredient !== "string" || factor === 1) return ingredient;
|
||||
const match = ingredient.match(/^(\s*)(?:(\d+)\s+)?(\d+\/\d+|\d+(?:\.\d+)?|[¼½¾⅓⅔⅛⅜⅝⅞])(?=\s|[a-zA-Z])/);
|
||||
if (!match) return ingredient;
|
||||
const whole = Number(match[2] || 0);
|
||||
const quantity = parseQuantity(match[3]);
|
||||
if (!Number.isFinite(quantity)) return ingredient;
|
||||
const replacement = `${match[1]}${formatQuantity((whole + quantity) * factor)}`;
|
||||
return replacement + ingredient.slice(match[0].length);
|
||||
return scaleIngredientWithStatus(ingredient, factor).value;
|
||||
}
|
||||
|
||||
function scaleRecipe(recipe, portions) {
|
||||
const basePortions = parseYield(recipe?.recipeYield);
|
||||
if (!basePortions || !Number.isInteger(portions) || portions < 1) return recipe;
|
||||
const suffix = String(recipe.recipeYield).replace(/^\s*\d+(?:\.\d+)?\s*/, "");
|
||||
const factor = portions / basePortions;
|
||||
const ingredients = (recipe.recipeIngredient || []).map((ingredient) => (
|
||||
scaleIngredientWithStatus(ingredient, factor)
|
||||
));
|
||||
return {
|
||||
...recipe,
|
||||
recipeYield: suffix ? `${portions} ${suffix}` : portions,
|
||||
recipeIngredient: (recipe.recipeIngredient || []).map((ingredient) => (
|
||||
scaleIngredient(ingredient, portions / basePortions)
|
||||
))
|
||||
originalRecipeYield: recipe.recipeYield,
|
||||
recipeIngredient: ingredients.map(({ value }) => value),
|
||||
recipeIngredientStatus: ingredients.map(({ status }) => status)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { parseYield, scaleIngredient, scaleRecipe };
|
||||
module.exports = { parseYield, scaleIngredient, scaleIngredientWithStatus, scaleRecipe };
|
||||
|
||||
Reference in New Issue
Block a user