Files
2026-07-21 16:50:58 +02:00

85 lines
2.4 KiB
JavaScript

/**
* 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 };