85 lines
2.4 KiB
JavaScript
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 };
|