import * as cheerio from "cheerio"; import { CheerioAPI } from "cheerio"; import { z as z$1 } from "zod"; import { ParseIngredientOptions } from "parse-ingredient"; import { StandardSchemaV1 } from "@standard-schema/spec"; //#region src/logger.d.ts declare enum LogLevel { VERBOSE = 0, DEBUG = 1, INFO = 2, WARN = 3, ERROR = 4 } declare class Logger { private context; private logLevel; constructor(context: string, logLevel?: LogLevel); verbose(...args: unknown[]): void; debug(...args: unknown[]): void; log(...args: unknown[]): void; info(...args: unknown[]): void; warn(...args: unknown[]): void; error(...args: unknown[]): void; } //#endregion //#region src/abstract-plugin.d.ts declare abstract class AbstractPlugin { readonly $: CheerioAPI; /** The name of the plugin */ abstract name: string; /** The priority of the plugin */ abstract priority: number; constructor($: CheerioAPI); } //#endregion //#region src/schemas/recipe.schema.d.ts /** * Current schema version for recipe objects. * Increment this when making breaking changes to the schema. * * Version history: * - 1.0.0: Initial schema version */ declare const RECIPE_SCHEMA_VERSION: "1.0.0"; /** * Schema for a parsed ingredient from the parse-ingredient library. * This represents the structured data extracted from an ingredient string. * @see https://github.com/jakeboone02/parse-ingredient */ declare const ParsedIngredientSchema: z$1.ZodObject<{ quantity: z$1.ZodNullable; quantity2: z$1.ZodNullable; unitOfMeasureID: z$1.ZodNullable; unitOfMeasure: z$1.ZodNullable; description: z$1.ZodString; isGroupHeader: z$1.ZodBoolean; }, z$1.core.$strip>; /** * Schema for a single ingredient item */ declare const IngredientItemSchema: z$1.ZodObject<{ value: z$1.ZodPipe>; parsed: z$1.ZodNullable; quantity2: z$1.ZodNullable; unitOfMeasureID: z$1.ZodNullable; unitOfMeasure: z$1.ZodNullable; description: z$1.ZodString; isGroupHeader: z$1.ZodBoolean; }, z$1.core.$strip>>>; }, z$1.core.$strip>; /** * Schema for a group of ingredients */ declare const IngredientGroupSchema: z$1.ZodObject<{ name: z$1.ZodNullable>>; items: z$1.ZodArray>; parsed: z$1.ZodNullable; quantity2: z$1.ZodNullable; unitOfMeasureID: z$1.ZodNullable; unitOfMeasure: z$1.ZodNullable; description: z$1.ZodString; isGroupHeader: z$1.ZodBoolean; }, z$1.core.$strip>>>; }, z$1.core.$strip>>; }, z$1.core.$strip>; /** * Schema for all recipe ingredients * Must have at least one group with at least one ingredient */ declare const IngredientsSchema: z$1.ZodArray>>; items: z$1.ZodArray>; parsed: z$1.ZodNullable; quantity2: z$1.ZodNullable; unitOfMeasureID: z$1.ZodNullable; unitOfMeasure: z$1.ZodNullable; description: z$1.ZodString; isGroupHeader: z$1.ZodBoolean; }, z$1.core.$strip>>>; }, z$1.core.$strip>>; }, z$1.core.$strip>>; /** * Schema for a single instruction step */ declare const InstructionItemSchema: z$1.ZodObject<{ value: z$1.ZodPipe>; }, z$1.core.$strip>; /** * Schema for a group of instruction steps */ declare const InstructionGroupSchema: z$1.ZodObject<{ name: z$1.ZodNullable>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>; /** * Schema for all recipe instructions * Must have at least one group with at least one step */ declare const InstructionsSchema: z$1.ZodArray>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>>; /** * Schema for a single recipe note */ declare const NoteItemSchema: z$1.ZodObject<{ value: z$1.ZodPipe>; }, z$1.core.$strip>; /** * Schema for a group of recipe notes */ declare const NoteGroupSchema: z$1.ZodObject<{ name: z$1.ZodNullable>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>; /** * Schema for all recipe notes * Must have at least one group with at least one note */ declare const NotesSchema: z$1.ZodArray>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>>; /** * Schema for a link object */ declare const LinkSchema: z$1.ZodObject<{ href: z$1.ZodURL; text: z$1.ZodPipe>; }, z$1.core.$strip>; /** * Base RecipeObject schema without cross-field validations. * Use this schema when you need to extend the recipe object with custom fields. * * @example * ```ts * import { RecipeObjectBaseSchema, applyRecipeValidations } from 'recipe-scrapers-js' * * const MyCustomRecipeSchema = RecipeObjectBaseSchema.extend({ * customField: z.string(), * }) * * // Apply the standard recipe validations * const MyValidatedRecipeSchema = applyRecipeValidations(MyCustomRecipeSchema) * ``` */ declare const RecipeObjectBaseSchema: z$1.ZodObject<{ schemaVersion: z$1.ZodDefault>; host: z$1.ZodCustomStringFormat<"hostname">; title: z$1.ZodPipe>; author: z$1.ZodPipe>; ingredients: z$1.ZodArray>>; items: z$1.ZodArray>; parsed: z$1.ZodNullable; quantity2: z$1.ZodNullable; unitOfMeasureID: z$1.ZodNullable; unitOfMeasure: z$1.ZodNullable; description: z$1.ZodString; isGroupHeader: z$1.ZodBoolean; }, z$1.core.$strip>>>; }, z$1.core.$strip>>; }, z$1.core.$strip>>; instructions: z$1.ZodArray>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>>; notes: z$1.ZodOptional>>; items: z$1.ZodArray>; }, z$1.core.$strip>>; }, z$1.core.$strip>>>; canonicalUrl: z$1.ZodURL; image: z$1.ZodURL; totalTime: z$1.ZodNullable; cookTime: z$1.ZodNullable; prepTime: z$1.ZodNullable; ratings: z$1.ZodDefault; ratingsCount: z$1.ZodDefault; yields: z$1.ZodPipe>; description: z$1.ZodPipe>; language: z$1.ZodDefault>>>; siteName: z$1.ZodNullable>>; cookingMethod: z$1.ZodNullable>>; category: z$1.ZodDefault>>>; cuisine: z$1.ZodDefault>>>; keywords: z$1.ZodDefault>>>; dietaryRestrictions: z$1.ZodDefault>>>; equipment: z$1.ZodDefault>>>; links: z$1.ZodOptional>; }, z$1.core.$strip>>>; nutrients: z$1.ZodDefault>; reviews: z$1.ZodDefault>; }, z$1.core.$strip>; /** * Applies recipe-specific transformations and validations to a schema. * Use this when extending RecipeObjectBaseSchema with custom fields. * * @param schema - A Zod object schema that includes * all RecipeObjectBaseSchema fields * @returns A schema with transforms and field validations applied * * @example * ```ts * const CustomSchema = RecipeObjectBaseSchema.extend({ * tags: z.array(z.string()), * }) * * const ValidatedCustomSchema = applyRecipeValidations(CustomSchema) * ``` */ declare function applyRecipeValidations>(schema: z$1.ZodType): z$1.ZodPipe>, z$1.ZodTransform, T>>; /** * Strict RecipeObject schema with all validations enforced. * This is the standard schema used by recipe scrapers. * * For custom extensions, use RecipeObjectBaseSchema.extend() and then * apply validations with applyRecipeValidations(). */ declare const RecipeObjectSchema: z$1.ZodPipe; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, unknown, z$1.core.$ZodTypeInternals<{ schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, unknown>>, z$1.ZodTransform<{ schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, { schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }>>; //#endregion //#region src/types/recipe.interface.d.ts type List = Set; /** * Parsed ingredient data from the parse-ingredient library */ type ParsedIngredient = z$1.infer; /** * A single ingredient item */ type IngredientItem = z$1.infer; /** * A group of ingredients with an optional group name */ type IngredientGroup = z$1.infer; /** * All recipe ingredients as an array of groups */ type Ingredients = IngredientGroup[]; /** * A single instruction step */ type InstructionItem = z$1.infer; /** * A group of instruction steps with an optional group name */ type InstructionGroup = z$1.infer; /** * All recipe instructions as an array of groups */ type Instructions = InstructionGroup[]; /** * A single recipe note */ type NoteItem = z$1.infer; /** * A group of recipe notes with an optional group name */ type NoteGroup = z$1.infer; /** * All recipe notes as an array of groups */ type Notes = z$1.infer; /** * The complete recipe object */ type RecipeObject = z$1.infer; /** * A link with href and display text */ type Link = z$1.infer; interface RecipeData { /** * The host name of the website the Scraper class is for. * @example 'bbcgoodfood.com' */ host: string; /** * The website name, as defined in the page's HTML. * @default null */ siteName: string | null; /** * The author of the recipe. This is typically a person's name * but can sometimes be an organization or the name of the website * the recipe came from. If the recipe does not explicitly define an author, * this should return the name of the website. * @example 'Good Food team' */ author: string; /** * The title of the recipe, usually a short sentence or phrase. */ title: string; /** * The URL to the main image associated with the recipe, * usually a photograph of the completed recipe. */ image: string; /** * The canonical URL for the scraped recipe. * The canonical URL is the direct URL (defined by the website) at which the * recipe can be found. This URL will generally not contain any query * parameters or fragments, except those required to load the recipe. */ canonicalUrl: string; /** * The language of the recipe page, as defined within the page's HTML. * This is typically a two-letter BCP 47 language code, such as 'en' for * English or 'de' for German, but may also include the dialect or * variation, such as 'en-US' for American English. * * The language code is based on BCP 47 standards. * For a comprehensive list of BCP 47 language codes, * refer to this GitHub Gist: * @ref https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1 * * @default 'en' */ language: string; /** * An list of all links found in the page HTML defined within an anchor * `` element. * Only present when `linksEnabled` option is set to `true`. */ links?: Link[]; /** * A description of the recipe. This is normally a sentence or short * paragraph describing the recipe. Often the website defines the * description, but sometimes it has to be inferred from the page content. */ description: string; /** * The ingredients needed to make the recipe. * * This is an array of ingredient groups, where each group has a name * (e.g., "For the sauce", "For the dough") and a list of ingredient items. * When there are no groups, the group name is null. * * @example * [ * { * name: 'For the sauce', * items: [ * { value: '2 tablespoons olive oil' }, * { value: '1 onion, chopped' }, * ] * } * ] */ ingredients: Ingredients; /** * A list of instructions for preparing the recipe. * This is usually a step-by-step guide on how to make the recipe. * * This is an array of instruction groups, where each group has a name * (e.g., "For the sauce", "For assembly") and a list of instruction steps. * When there are no groups, the group name is null. * * @example * [ * { * name: 'For the dough', * items: [ * { value: 'Mix flour and water.' }, * { value: 'Knead for 10 minutes.' }, * ] * } * ] */ instructions: Instructions; /** * Optional recipe notes supplied by the recipe author. * This is usually extra guidance, substitutions, or storage tips. * * This is an array of note groups, where each group has a name * and a list of note items. When there are no groups, the group name is null. * * @example * [ * { * name: null, * items: [ * { value: 'Store in an airtight container for up to 3 weeks.' }, * ] * } * ] */ notes?: Notes; /** * The category or categories that the recipe belongs to. * This can contain a mix of cuisine type (for example, country names), * mealtime (breakfast/dinner/etc) and dietary properties (gluten-free, * vegetarian). The value is defined by the website, so it may overlap with * other fields (e.g. `cuisine`). * @default Set() * @example ['Italian', 'Vegetarian', 'Dinner'] */ category: List; /** * The number of items or servings the recipe will make, * including the quantity and unit of the yield. * @example '4 servings', '6 items', '12 cookies'. */ yields: string; /** * The total time (in minutes) required to complete the recipe. * @example 45 */ totalTime: number | null; /** * The time (in minutes) to cook the recipe, excluding any time * to prepare the ingredients. * @default null * @example 30 */ cookTime: number | null; /** * The time (in minutes) to prepare the ingredients for the recipe. * @default null * @example 15 */ prepTime: number | null; /** * A list of cuisines that the recipe belongs to. * This is a `Set` of strings representing the cuisine types. * @example ['Italian', 'Vegetarian'] */ cuisine: List; /** * The method of cooking the recipe. * @default null */ cookingMethod: string | null; /** * The recipe rating. When available, this is usually the average * of all the ratings given to the recipe on the website. * @example 4.5 */ ratings: number; /** * The total number of ratings contributed to the recipes rating. * @example 150 */ ratingsCount: number; /** * A list of cooking equipment needed for the recipe. * @default Set() * @example ['Mixing Bowl', 'Whisk', 'Baking Tray'] */ equipment: List; /** * Reviews of the recipe from the website. * The keys of the `Map` are the reviewer's name * and the values are the review text. * @default Map() */ reviews: Map; /** * The nutrition information for the recipe. * Each nutrition entry is usually given per unit of yield, * i.e. per servings, or per item. * The keys of the `Map` are the nutrients (including calories) * and the values are the amount of that nutrient, including the unit. * @default Map() * @example * { * calories: '389 calories', * fatContent: '19 grams fat', * // ... * } */ nutrients: Map; /** * The dietary restrictions specified by the recipe. * @default Set() * @example ['Vegan Diet', 'Vegetarian Diet'] */ dietaryRestrictions: List; /** * A list of keywords associated with a recipe. * @example ['easy', 'quick', 'dinner'] */ keywords: List; } /** * The fields of a recipe that can be extracted by scraping the HTML. * The 'host' field is omitted because it is a static field * that is not scraped. */ type RecipeFields = Omit; /** * The fields that aren't required for a recipe to be valid. */ type OptionalRecipeFields = Pick; //#endregion //#region src/abstract-extractor-plugin.d.ts declare abstract class ExtractorPlugin extends AbstractPlugin { /** Whether this plugin can extract the given field */ abstract supports(field: keyof RecipeFields): boolean; /** * Extracts the field from the cheerio root. * @param field The field to extract * @returns The extracted field value */ abstract extract(field: Key): RecipeFields[Key] | Promise; } //#endregion //#region src/abstract-postprocessor-plugin.d.ts declare abstract class PostProcessorPlugin { /** The name of the plugin */ abstract name: string; /** The priority of the plugin */ abstract priority: number; abstract shouldProcess(field: Key): boolean; abstract process(field: keyof RecipeFields, value: T): T | Promise; } //#endregion //#region src/plugin-manager.d.ts declare class PluginManager { private extractorPlugins; private postProcessorPlugins; constructor(baseExtractors: ExtractorPlugin[], basePostProcessors: PostProcessorPlugin[], extraExtractors?: ExtractorPlugin[], extraPostProcessors?: PostProcessorPlugin[]); getExtractors(): ExtractorPlugin[]; getPostProcessors(): PostProcessorPlugin[]; } //#endregion //#region src/recipe-extractor.d.ts declare class RecipeExtractor { private plugins; private readonly scraperName; private readonly options; private readonly logger; constructor(plugins: ExtractorPlugin[], scraperName: string, options?: { logLevel?: LogLevel; }); private getContext; extract(field: Key, extractor?: (prevValue: RecipeFields[Key] | undefined) => RecipeFields[Key] | Promise): Promise; } //#endregion //#region src/schema-adapter.d.ts /** * A normalized validation issue used across supported schema libraries. */ type ValidationIssue = StandardSchemaV1.Issue & { dotPath?: string | null; }; type SafeParseErrorType = 'validation' | 'extraction'; type SafeParseErrorCode = 'validation_failed' | 'extractor_not_found' | 'extraction_runtime_error' | 'extraction_failed'; interface SafeParseErrorContext { field?: string; source?: string; } /** * Validation error payload returned by `safeParse`. */ interface SafeParseError { type: SafeParseErrorType; code: SafeParseErrorCode; issues: ReadonlyArray; cause?: unknown; context?: SafeParseErrorContext; } /** * Library-agnostic safe parse result. */ type SafeParseResult = { success: true; data: T; } | { success: false; error: SafeParseError; }; /** * Runtime check for Standard Schema compatibility. */ declare function isStandardSchemaV1(value: unknown): value is StandardSchemaV1; /** * Validates input using any Standard Schema-compatible schema. */ declare function safeParseWithStandardSchema(schema: StandardSchemaV1, value: unknown): Promise>; //#endregion //#region src/types/scraper.interface.d.ts interface ScraperOptions { /** * Additional extractors to be used by the scraper. * These extractors will be added to the default set of extractors. * Extractors are applied according to their priority. * Higher priority extractors will run first. * @default [] */ extraExtractors?: ExtractorPlugin[]; /** * Additional post-processors to be used by the scraper. * These post-processors will be added to the default set of post-processors. * Post-processors are applied after all extractors have run. * Post-processors are also applied according to their priority. * Higher priority post-processors will run first. * @default [] */ extraPostProcessors?: PostProcessorPlugin[]; /** * Non-empty value to use when no extractor can find a recipe yield. * Extracted yield values always take precedence. * * When omitted, a missing yield remains an extraction failure. */ fallbackYield?: string; /** * Whether link scraping is enabled. * @default false */ linksEnabled?: boolean; /** * Logging level for the scraper. * This controls the verbosity of logs produced by the scraper. * @default LogLevel.Warn */ logLevel?: LogLevel; /** * Enable ingredient parsing using the parse-ingredient library. * When enabled, each ingredient item will include a `parsed` field * containing structured data (quantity, unit, description, etc.). * * Can be set to `true` to enable with default options, or pass * an options object to customize parsing behavior. * * @see https://github.com/jakeboone02/parse-ingredient * @default false * * @example * // Enable with defaults * { parseIngredients: true } * * @example * // Enable with custom options * { parseIngredients: { normalizeUOM: true } } */ parseIngredients?: boolean | ParseIngredientOptions; /** * Enable recipe note parsing from supported HTML recipe blocks. * When enabled, recipes may include a `notes` field containing * grouped note items when the source markup supports it. * * @default false */ parseNotes?: boolean; /** * Standard Schema-compatible recipe schema. * Use this to validate with libraries such as Zod, Valibot, ArkType, etc. */ schema?: StandardSchemaV1; } //#endregion //#region src/abstract-scraper.d.ts type RecipeFieldExtractor = (prevValue: RecipeFields[Key] | undefined) => RecipeFields[Key] | Promise; type ScraperExtractors = { [Key in keyof RecipeFields]?: RecipeFieldExtractor }; declare abstract class AbstractScraper { protected readonly html: string; protected readonly url: string; protected readonly options: ScraperOptions; protected readonly logger: Logger; protected readonly pluginManager: PluginManager; protected readonly recipeExtractor: RecipeExtractor; private validationSchema; readonly $: cheerio.CheerioAPI; recipeData: RecipeData | null; constructor(html: string, url: string, options?: ScraperOptions); /** * Site-specific extractors (implemented by subclasses) * Each extractor is a function that takes the previous value * returned by the extractor chain (if any) and returns the field value. */ protected readonly extractors: ScraperExtractors; /** * Main extraction method - tries site-specific first, then plugins, * then applies post-processing. */ extract(field: Key): Promise; /** * Static method to get the host of the scraper. * This should be implemented by subclasses to return the specific host. */ static host(): string; /** * Returns the host value stored in the final recipe data. * Subclasses can override when host must be derived from instance context. */ protected getHost(): string; /***************************************************************************** * Default implementations for common fields that can be overridden * by subclasses. ****************************************************************************/ canonicalUrl(): RecipeFields['canonicalUrl']; language(): RecipeFields['language']; links(): RecipeFields['links']; protected notes(): RecipeData['notes']; private extractYields; /** * Scrape's the recipe and caches the data. */ scrape(): Promise; /** * Converts the scraper's data into a JSON-serializable object. * Note: schemaVersion is added during validation by parse() or safeParse(). */ toRecipeObject(): Promise>; /** * Get the default schema used for validation. * Subclasses can override this method to customize the default schema. * For custom validation schemas, pass `schema` in options. */ protected getSchema(): import("zod").ZodPipe; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, unknown, import("zod/v4/core").$ZodTypeInternals<{ schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, unknown>>, import("zod").ZodTransform<{ schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }, { schemaVersion: "1.0.0"; host: string; title: string; author: string; ingredients: { name: string | null; items: { value: string; parsed?: { quantity: number | null; quantity2: number | null; unitOfMeasureID: string | null; unitOfMeasure: string | null; description: string; isGroupHeader: boolean; } | null | undefined; }[]; }[]; instructions: { name: string | null; items: { value: string; }[]; }[]; canonicalUrl: string; image: string; totalTime: number | null; cookTime: number | null; prepTime: number | null; ratings: number; ratingsCount: number; yields: string; description: string; language: string; siteName: string | null; cookingMethod: string | null; category: string[]; cuisine: string[]; keywords: string[]; dietaryRestrictions: string[]; equipment: string[]; nutrients: Record; reviews: Record; notes?: { name: string | null; items: { value: string; }[]; }[] | undefined; links?: { href: string; text: string; }[] | undefined; }>>; /** * Resolve the Standard Schema used for validation. * * Resolution order: * 1) `options.schema` * 2) default schema from `getSchema()` */ protected getValidationSchema(): StandardSchemaV1; /** * Extract and validate recipe data. * Throws ValidationException if validation fails. * * @returns Validated recipe object * @throws {ValidationException} If validation fails */ parse(): Promise; /** * Extract and validate recipe data without throwing. * Returns a result object indicating success or failure. * * @returns Result object with either data or error */ safeParse(): Promise>; } //#endregion //#region src/scrapers/_index.d.ts /** * Constructor type for scraper classes. */ type ScraperClass = { new (html: string, url: string, options?: ScraperOptions): AbstractScraper; host(): string; }; /** * A map of all scrapers keyed by host and aliases. */ declare const scrapers: Record; //#endregion //#region src/scrapers/generic.d.ts declare class GenericScraper extends AbstractScraper { static host(): string; protected getHost(): string; } //#endregion //#region src/utils/parse-yields.d.ts /** * Returns a string of servings or items. If the recipe is for a number of * items (not servings), it returns "x item(s)" where x is the quantity. * This function handles cases where the yield is in dozens, * such as "4 dozen cookies", returning "4 dozen" instead of "4 servings". * Additionally accommodates yields specified in batches * (e.g., "2 batches of brownies"), returning the yield as stated. * * @param value The yield string from the recipe * @returns The number of servings, items, dozen, batches, etc... */ declare function parseYields(element: string): string; //#endregion //#region src/index.d.ts interface GetScraperOptions { /** * Return a generic schema.org scraper for unsupported hosts. * @default false */ wildMode?: boolean; } interface BaseScrapeRecipeOptions extends ScraperOptions { /** * Allow parsing unsupported hosts with GenericScraper fallback. * @default true */ wildMode?: boolean; } interface ScrapeRecipeOptions extends BaseScrapeRecipeOptions { /** * Return a safe-parse result instead of throwing. * @default false */ safeParse?: false; } interface ScrapeRecipeSafeParseOptions extends BaseScrapeRecipeOptions { /** * Return a safe-parse result instead of throwing. */ safeParse: true; } /** * Returns a scraper class for the given URL, if implemented. * Returns a GenericScraper if the host is not supported and `wildMode` is true. * Throws an error if the host is not supported and `wildMode` is false. */ declare function getScraper(url: string, { wildMode }?: GetScraperOptions): { new (html: string, url: string, options?: ScraperOptions): AbstractScraper; host(): string; }; /** * Parse a recipe from HTML and URL in one call. * Falls back to generic schema.org extraction by default. */ declare function scrapeRecipe(html: string, url: string, options: ScrapeRecipeSafeParseOptions): Promise>; declare function scrapeRecipe(html: string, url: string, options?: ScrapeRecipeOptions): Promise; //#endregion export { ExtractorPlugin, GenericScraper, GetScraperOptions, IngredientGroup, IngredientGroupSchema, IngredientItem, IngredientItemSchema, Ingredients, IngredientsSchema, InstructionGroup, InstructionGroupSchema, InstructionItem, InstructionItemSchema, Instructions, InstructionsSchema, Link, LinkSchema, List, LogLevel, Logger, NoteGroup, NoteGroupSchema, NoteItem, NoteItemSchema, Notes, NotesSchema, OptionalRecipeFields, ParsedIngredient, ParsedIngredientSchema, PostProcessorPlugin, RECIPE_SCHEMA_VERSION, RecipeData, RecipeFields, RecipeObject, RecipeObjectBaseSchema, RecipeObjectSchema, SafeParseError, SafeParseErrorCode, SafeParseErrorContext, SafeParseErrorType, SafeParseResult, ScrapeRecipeOptions, ScrapeRecipeSafeParseOptions, ScraperOptions, ValidationIssue, applyRecipeValidations, getScraper, isStandardSchemaV1, parseYields, safeParseWithStandardSchema, scrapeRecipe, scrapers }; //# sourceMappingURL=index.d.mts.map