/** * Parsing pur des fichiers `.bentext` (sources recette). * Aucun effet de bord : ne touche pas au système de fichiers, au catalogue, * ni aux assets. Utilisé par `scripts/build-recipes.mjs`. * * Format bentext : * Title * Version * Description * --- * Ingredients (une ligne par ingrédient : `Nom|quantité|unité|note`) * --- * Steps (une ligne par étape, ordre du fichier = priorité) * --- * Notes (optionnel, présent si 6+ blocs `---`) * Tags (optionnel dès 4 blocs) * Meta (optionnel dès 5 blocs) */ const splitIngredientLine = (line) => { const parts = line.split("|").map((token) => token.trim()); const name = parts[0] ?? ""; const quantity = Number(parts[1] ?? "0"); const unit = parts[2] ?? ""; const note = parts.slice(3).join(" | ").trim(); return { name, quantity, unit, note }; }; const splitNonEmptyLines = (raw) => raw .split("\n") .map((line) => line.trim()) .filter(Boolean); const readBentext = (raw) => { const parts = raw.split("---").map((part) => part.trim()); const header = (parts[0] ?? "").split("\n").map((line) => line.trim()); const title = header[0] ?? ""; const version = header[1] ?? ""; const servings = Number.parseInt(version, 10); const description = header.slice(2).join("\n").trim(); const ingredientsBlock = parts[1] ?? ""; const stepsBlock = parts[2] ?? ""; let notesBlock = ""; let tagsBlock = ""; let metaBlock = ""; if (parts.length === 4) { tagsBlock = parts[3] ?? ""; } else if (parts.length === 5) { tagsBlock = parts[3] ?? ""; metaBlock = parts[4] ?? ""; } else if (parts.length >= 6) { notesBlock = parts[3] ?? ""; tagsBlock = parts[4] ?? ""; metaBlock = parts[5] ?? ""; } const stepLines = splitNonEmptyLines(stepsBlock); const steps = stepLines.map((line, index) => ({ id: `step-${index + 1}`, priority: (index + 1) * 10, phase: "cook", dependsOn: index === 0 ? [] : [`step-${index}`], text: line })); return { title, version, servings: Number.isFinite(servings) && servings > 0 ? servings : 1, description, ingredients: splitNonEmptyLines(ingredientsBlock).map((line) => splitIngredientLine(line)), steps, notes: splitNonEmptyLines(notesBlock), tags: splitNonEmptyLines(tagsBlock).map((line) => line.toLowerCase()), meta: splitNonEmptyLines(metaBlock) }; }; export { readBentext, splitIngredientLine };