diff --git a/src/server/api/modules/recipes/service/schemas.ts b/src/server/api/modules/recipes/service/schemas.ts index 91bfcd8..ae3983f 100644 --- a/src/server/api/modules/recipes/service/schemas.ts +++ b/src/server/api/modules/recipes/service/schemas.ts @@ -1,11 +1,26 @@ import z from "zod" -export const RecipeStepSchema = z - .union([z.string(), z.object({ text: z.string() })]) - .transform((input): string => { - if (typeof input === "string") return input - return input.text - }) +type Step = { + "@context": string; + "@type": string; + text: string; +}; + +function beautifyInstructions(input: string): string { + const sections = input.split(/\n\n+/); + + const formattedSections = sections.map((section, index) => { + const numberedSection = section.replace(/\n/g, '
'); + return `${index + 1}. ${numberedSection}`; + }); + + return formattedSections.map(section => `

${section}

`).join(''); +} + +export function StepsSchema(steps: string | Step[]){ + if (typeof steps === "string") return beautifyInstructions(steps); + return beautifyInstructions(steps.map(step => step.text).join('\n\n')); +} const baseUrlSchema = z.union([z.string(), z.object({ url: z.string() })]) export const RecipeImageUrlSchema = z diff --git a/src/server/api/modules/recipes/service/scraper.ts b/src/server/api/modules/recipes/service/scraper.ts index c95f1b6..eb73f15 100644 --- a/src/server/api/modules/recipes/service/scraper.ts +++ b/src/server/api/modules/recipes/service/scraper.ts @@ -3,7 +3,7 @@ import { ExtractNumberSchema, JsonLdRecipeSchema, RecipeImageUrlSchema, - RecipeStepSchema, + StepsSchema, } from "~/server/api/modules/recipes/service/schemas" import { InsertIngredient, InsertRecipe } from "~/server/db/schema" import { JSDOM } from "jsdom" @@ -90,9 +90,13 @@ export async function hydrateRecipe(url: string) { const recipeData = getSchemaRecipeFromNodeList(nodeList) - const steps = RecipeStepSchema.array().safeParse( - recipeData.recipeInstructions - ) + let steps: string = "" + try { + steps = StepsSchema(recipeData.recipeInstructions) + } + catch(e){ + throw new Error("Could not parse steps") + } const ingredients: string[] = recipeData.recipeIngredient .flat() @@ -100,10 +104,6 @@ export async function hydrateRecipe(url: string) { const image = RecipeImageUrlSchema.safeParse(recipeData.image) - if (!steps.success) { - throw new Error("Could not parse steps") - } - const ings: Pick[] = ingredients.map( (a) => ({ scrapedName: a }) ) @@ -113,7 +113,7 @@ export async function hydrateRecipe(url: string) { const recipe: InsertRecipe = { name: recipeData.name, url, - steps: steps.data.join("\n"), + steps: steps, imageUrl: image.success ? image.data : undefined, servings: servings.success ? servings.data : undefined, }