refactor: simplify parse ingredients code

This commit is contained in:
2025-01-19 19:22:19 +01:00
parent f106460502
commit 78e94ccf82
14 changed files with 201 additions and 137 deletions

View File

@@ -1,6 +1,5 @@
import {
type DocumentChild,
getTextOfChild,
getTextOfRange,
parseDocument,
} from "@lib/documents.ts";
@@ -9,7 +8,7 @@ import { createCrud } from "@lib/crud.ts";
import { extractHashTags } from "@lib/string.ts";
import { Ingredient, IngredientGroup } from "@lib/recipeSchema.ts";
import { fixRenderedMarkdown } from "@lib/helpers.ts";
import { parseIngredient } from "@lib/parseIngredient.ts";
import { parseIngredients } from "@lib/parseIngredient.ts";
export type Recipe = {
type: "recipe";
@@ -33,72 +32,14 @@ export type Recipe = {
};
};
function parseIngredientItem(listItem: DocumentChild): Ingredient | undefined {
if (listItem.type === "listItem") {
const children: DocumentChild[] = listItem.children[0]?.children ||
listItem.children;
const text = children.map((c) => getTextOfChild(c)).join(" ").trim();
return parseIngredient(text);
}
}
const isIngredient = (item: Ingredient | undefined): item is Ingredient => {
return !!item;
};
function parseIngredientsList(list: DocumentChild): Ingredient[] {
if (list.type === "list" && "children" in list) {
return list.children.map((listItem) => {
return parseIngredientItem(listItem);
}).filter(isIngredient);
}
return [];
}
function parseIngredients(children: DocumentChild[]): Recipe["ingredients"] {
const ingredients: (Ingredient | IngredientGroup)[] = [];
if (!children) return [];
let skip = false;
for (let i = 0; i < children.length; i++) {
if (skip) {
skip = false;
continue;
}
const child = children[i];
if (child.type === "paragraph") {
const nextChild = children[i + 1];
if (!nextChild || nextChild.type !== "list") continue;
const name = getTextOfChild(child);
ingredients.push({
name: name || "",
items: parseIngredientsList(nextChild),
});
skip = true;
continue;
}
if (child.type === "list") {
ingredients.push(...parseIngredientsList(child));
}
}
return ingredients;
}
function extractSteps(
content: string,
seperator: RegExp = /\n(?=\d+\.)/g,
): string[] {
const steps = content.split(seperator).map((step) => {
const match = step.match(/^(\d+)\.\s*(.*)/);
if (!match) return;
const [, , text] = match;
return text;
if (match) return match[2];
return step;
}).filter((step) => !!step);
return steps as string[];
}
@@ -141,7 +82,14 @@ export function parseRecipe(original: string, id: string): Recipe {
let description = getTextOfRange(groups[0], original);
const ingredients = parseIngredients(groups[1]);
let ingredientsText = getTextOfRange(groups[1], original);
if (ingredientsText) {
ingredientsText = ingredientsText.replace(/#+\s?Ingredients?/, "");
} else {
ingredientsText = "";
}
const ingredients = parseIngredients(ingredientsText);
const instructionText = getTextOfRange(groups[2], original);
let instructions = extractSteps(instructionText || "");