soustack 0.1.3 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +301 -203
- package/dist/cli/index.js +1763 -1365
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +60 -135
- package/dist/index.d.ts +60 -135
- package/dist/index.js +1141 -1455
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1140 -1443
- package/dist/index.mjs.map +1 -1
- package/dist/scrape.d.mts +308 -0
- package/dist/scrape.d.ts +308 -0
- package/dist/scrape.js +819 -0
- package/dist/scrape.js.map +1 -0
- package/dist/scrape.mjs +814 -0
- package/dist/scrape.mjs.map +1 -0
- package/package.json +86 -75
- package/src/profiles/.gitkeep +0 -0
- package/src/profiles/base.schema.json +9 -0
- package/src/profiles/cookable.schema.json +18 -0
- package/src/profiles/illustrated.schema.json +48 -0
- package/src/profiles/quantified.schema.json +43 -0
- package/src/profiles/scalable.schema.json +75 -0
- package/src/profiles/schedulable.schema.json +43 -0
- package/src/schema.json +63 -24
- package/src/soustack.schema.json +344 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Soustack Recipe Schema v0.1
|
|
2
|
+
* Soustack Recipe Schema v0.2.1
|
|
3
3
|
* A portable, scalable, interoperable recipe format.
|
|
4
4
|
*/
|
|
5
|
-
interface
|
|
5
|
+
interface SoustackRecipe {
|
|
6
|
+
/** Optional $schema pointer for profile-aware validation */
|
|
7
|
+
$schema?: string;
|
|
6
8
|
/** Unique identifier (slug or UUID) */
|
|
7
9
|
id?: string;
|
|
10
|
+
/** Optional display title */
|
|
11
|
+
title?: string;
|
|
8
12
|
/** The title of the recipe */
|
|
9
13
|
name: string;
|
|
10
14
|
/** Semantic versioning (e.g., 1.0.0) */
|
|
15
|
+
recipeVersion?: string;
|
|
16
|
+
/** Deprecated alias for recipeVersion */
|
|
11
17
|
version?: string;
|
|
12
18
|
description?: string;
|
|
13
19
|
/** Primary category (e.g., "Main Course") */
|
|
14
20
|
category?: string;
|
|
15
21
|
/** Additional tags for filtering */
|
|
16
22
|
tags?: string[];
|
|
17
|
-
/** URL to recipe image */
|
|
18
|
-
image?: string;
|
|
23
|
+
/** URL(s) to recipe image(s) */
|
|
24
|
+
image?: string | string[];
|
|
19
25
|
/** ISO 8601 date string */
|
|
20
26
|
dateAdded?: string;
|
|
21
27
|
/** Last updated timestamp */
|
|
@@ -29,7 +35,10 @@ interface Recipe {
|
|
|
29
35
|
storage?: Storage;
|
|
30
36
|
substitutions?: Substitution[];
|
|
31
37
|
nutrition?: NutritionFacts;
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
[k: `x-${string}`]: unknown;
|
|
32
40
|
}
|
|
41
|
+
type Recipe = SoustackRecipe;
|
|
33
42
|
interface Source {
|
|
34
43
|
author?: string;
|
|
35
44
|
url?: string;
|
|
@@ -147,7 +156,7 @@ interface InstructionSubsection {
|
|
|
147
156
|
subsection: string;
|
|
148
157
|
items: (string | Instruction)[];
|
|
149
158
|
}
|
|
150
|
-
interface
|
|
159
|
+
interface SoustackInstruction {
|
|
151
160
|
id?: string;
|
|
152
161
|
text: string;
|
|
153
162
|
destination?: string;
|
|
@@ -156,9 +165,12 @@ interface Instruction {
|
|
|
156
165
|
/** IDs of ingredients used in this step */
|
|
157
166
|
inputs?: string[];
|
|
158
167
|
timing?: StepTiming;
|
|
168
|
+
/** Optional image URL for this instruction */
|
|
169
|
+
image?: string;
|
|
159
170
|
}
|
|
171
|
+
type Instruction = SoustackInstruction;
|
|
160
172
|
interface StepTiming {
|
|
161
|
-
duration: number;
|
|
173
|
+
duration: number | string;
|
|
162
174
|
type: "active" | "passive";
|
|
163
175
|
scaling?: "linear" | "fixed" | "sqrt";
|
|
164
176
|
}
|
|
@@ -207,46 +219,43 @@ interface NutritionFacts {
|
|
|
207
219
|
[key: string]: string | number | null | string[] | undefined;
|
|
208
220
|
}
|
|
209
221
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
metadata: {
|
|
216
|
-
targetYield: number;
|
|
217
|
-
baseYield: number;
|
|
218
|
-
multiplier: number;
|
|
219
|
-
};
|
|
220
|
-
ingredients: ComputedIngredient[];
|
|
221
|
-
instructions: ComputedInstruction[];
|
|
222
|
-
timing: {
|
|
223
|
-
active: number;
|
|
224
|
-
passive: number;
|
|
225
|
-
total: number;
|
|
222
|
+
interface ScaleRecipeOptions {
|
|
223
|
+
multiplier?: number;
|
|
224
|
+
targetYield?: {
|
|
225
|
+
amount: number;
|
|
226
|
+
unit?: string;
|
|
226
227
|
};
|
|
227
228
|
}
|
|
228
|
-
|
|
229
|
-
id: string;
|
|
230
|
-
name: string;
|
|
231
|
-
amount: number;
|
|
232
|
-
unit: string | null;
|
|
233
|
-
text: string;
|
|
234
|
-
notes?: string;
|
|
235
|
-
}
|
|
236
|
-
interface ComputedInstruction {
|
|
237
|
-
id: string;
|
|
238
|
-
text: string;
|
|
239
|
-
durationMinutes: number;
|
|
240
|
-
type: 'active' | 'passive';
|
|
241
|
-
}
|
|
242
|
-
declare function scaleRecipe(recipe: Recipe, targetYieldAmount: number): ComputedRecipe;
|
|
229
|
+
declare function scaleRecipe(recipe: Recipe, options?: ScaleRecipeOptions): Recipe;
|
|
243
230
|
|
|
244
|
-
|
|
231
|
+
type ProfileName = "base" | "cookable" | "scalable" | "quantified" | "illustrated" | "schedulable";
|
|
232
|
+
interface NormalizedError {
|
|
233
|
+
path: string;
|
|
234
|
+
message: string;
|
|
235
|
+
keyword?: string;
|
|
236
|
+
}
|
|
237
|
+
interface NormalizedWarning {
|
|
238
|
+
path: string;
|
|
239
|
+
message: string;
|
|
240
|
+
}
|
|
241
|
+
interface ValidateOptions {
|
|
242
|
+
profile?: ProfileName;
|
|
243
|
+
schema?: string;
|
|
244
|
+
collectAllErrors?: boolean;
|
|
245
|
+
}
|
|
246
|
+
interface ValidationResult {
|
|
247
|
+
valid: boolean;
|
|
248
|
+
errors: NormalizedError[];
|
|
249
|
+
warnings: NormalizedWarning[];
|
|
250
|
+
normalized?: Recipe;
|
|
251
|
+
}
|
|
252
|
+
declare function validateRecipe(input: any, options?: ValidateOptions): ValidationResult;
|
|
253
|
+
declare function detectProfiles(recipe: any): ProfileName[];
|
|
245
254
|
|
|
246
255
|
declare function fromSchemaOrg(input: unknown): Recipe | null;
|
|
247
256
|
|
|
248
257
|
interface SchemaOrgRecipe$1 {
|
|
249
|
-
'@context'?: string
|
|
258
|
+
'@context'?: string | Array<string | Record<string, unknown>> | Record<string, unknown>;
|
|
250
259
|
'@type'?: string | string[];
|
|
251
260
|
name: string;
|
|
252
261
|
description?: string;
|
|
@@ -275,6 +284,9 @@ interface SchemaOrgImageObject {
|
|
|
275
284
|
'@type'?: string;
|
|
276
285
|
url?: string;
|
|
277
286
|
contentUrl?: string;
|
|
287
|
+
width?: number;
|
|
288
|
+
height?: number;
|
|
289
|
+
[key: string]: unknown;
|
|
278
290
|
}
|
|
279
291
|
type SchemaOrgImage = string | SchemaOrgImageObject | Array<string | SchemaOrgImageObject>;
|
|
280
292
|
interface SchemaOrgYield {
|
|
@@ -287,7 +299,13 @@ interface HowToStep$1 {
|
|
|
287
299
|
text?: string;
|
|
288
300
|
name?: string;
|
|
289
301
|
url?: string;
|
|
290
|
-
image?:
|
|
302
|
+
image?: SchemaOrgImage;
|
|
303
|
+
'@id'?: string;
|
|
304
|
+
id?: string;
|
|
305
|
+
totalTime?: string;
|
|
306
|
+
performTime?: string;
|
|
307
|
+
prepTime?: string;
|
|
308
|
+
duration?: string;
|
|
291
309
|
}
|
|
292
310
|
interface HowToSection {
|
|
293
311
|
'@type': 'HowToSection';
|
|
@@ -327,102 +345,9 @@ interface SchemaOrgRecipe {
|
|
|
327
345
|
aggregateRating?: unknown;
|
|
328
346
|
[key: string]: unknown;
|
|
329
347
|
}
|
|
330
|
-
interface FetchRequestInit {
|
|
331
|
-
headers?: Record<string, string>;
|
|
332
|
-
signal?: AbortSignal;
|
|
333
|
-
redirect?: 'follow' | 'error' | 'manual';
|
|
334
|
-
}
|
|
335
|
-
interface FetchResponse {
|
|
336
|
-
ok: boolean;
|
|
337
|
-
status: number;
|
|
338
|
-
statusText: string;
|
|
339
|
-
text(): Promise<string>;
|
|
340
|
-
}
|
|
341
|
-
type FetchImplementation = (url: string, init?: FetchRequestInit) => Promise<FetchResponse>;
|
|
342
|
-
interface FetchOptions {
|
|
343
|
-
timeout?: number;
|
|
344
|
-
userAgent?: string;
|
|
345
|
-
maxRetries?: number;
|
|
346
|
-
fetchFn?: FetchImplementation;
|
|
347
|
-
}
|
|
348
|
-
interface ScrapeRecipeOptions extends FetchOptions {
|
|
349
|
-
}
|
|
350
348
|
|
|
351
|
-
/**
|
|
352
|
-
* Scrapes a recipe from a URL (Node.js only).
|
|
353
|
-
*
|
|
354
|
-
* ⚠️ Not available in browser environments due to CORS restrictions.
|
|
355
|
-
* For browser usage, fetch the HTML yourself and use extractRecipeFromHTML().
|
|
356
|
-
*
|
|
357
|
-
* @param url - The URL of the recipe page to scrape
|
|
358
|
-
* @param options - Fetch options (timeout, userAgent, maxRetries)
|
|
359
|
-
* @returns A Soustack recipe object
|
|
360
|
-
* @throws Error if no recipe is found
|
|
361
|
-
*/
|
|
362
|
-
declare function scrapeRecipe(url: string, options?: ScrapeRecipeOptions): Promise<Recipe>;
|
|
363
|
-
/**
|
|
364
|
-
* Extracts a recipe from HTML string (browser and Node.js compatible).
|
|
365
|
-
*
|
|
366
|
-
* This function works in both environments and doesn't require network access.
|
|
367
|
-
* Perfect for browser usage where you fetch HTML yourself (with cookies/session).
|
|
368
|
-
*
|
|
369
|
-
* @example
|
|
370
|
-
* ```ts
|
|
371
|
-
* // In browser:
|
|
372
|
-
* const response = await fetch('https://example.com/recipe');
|
|
373
|
-
* const html = await response.text();
|
|
374
|
-
* const recipe = extractRecipeFromHTML(html);
|
|
375
|
-
* ```
|
|
376
|
-
*
|
|
377
|
-
* @param html - The HTML string containing Schema.org recipe data
|
|
378
|
-
* @returns A Soustack recipe object
|
|
379
|
-
* @throws Error if no recipe is found
|
|
380
|
-
*/
|
|
381
|
-
declare function extractRecipeFromHTML(html: string): Recipe;
|
|
382
|
-
/**
|
|
383
|
-
* Extract Schema.org recipe data from HTML string (browser-compatible).
|
|
384
|
-
*
|
|
385
|
-
* Returns the raw Schema.org recipe object, which can then be converted
|
|
386
|
-
* to Soustack format using fromSchemaOrg(). This gives you access to the
|
|
387
|
-
* original Schema.org data for inspection, debugging, or custom transformations.
|
|
388
|
-
*
|
|
389
|
-
* @param html - HTML string containing Schema.org recipe data
|
|
390
|
-
* @returns Schema.org recipe object, or null if not found
|
|
391
|
-
*
|
|
392
|
-
* @example
|
|
393
|
-
* ```ts
|
|
394
|
-
* // In browser:
|
|
395
|
-
* const response = await fetch('https://example.com/recipe');
|
|
396
|
-
* const html = await response.text();
|
|
397
|
-
* const schemaOrgRecipe = extractSchemaOrgRecipeFromHTML(html);
|
|
398
|
-
*
|
|
399
|
-
* if (schemaOrgRecipe) {
|
|
400
|
-
* // Inspect or modify Schema.org data before converting
|
|
401
|
-
* console.log('Found recipe:', schemaOrgRecipe.name);
|
|
402
|
-
*
|
|
403
|
-
* // Convert to Soustack format
|
|
404
|
-
* const soustackRecipe = fromSchemaOrg(schemaOrgRecipe);
|
|
405
|
-
* }
|
|
406
|
-
* ```
|
|
407
|
-
*/
|
|
408
349
|
declare function extractSchemaOrgRecipeFromHTML(html: string): SchemaOrgRecipe | null;
|
|
409
350
|
|
|
410
|
-
declare
|
|
411
|
-
declare function parseIngredient(text: string): ParsedIngredient;
|
|
412
|
-
declare function parseIngredientLine(text: string): ParsedIngredient;
|
|
413
|
-
declare function parseIngredients(texts: string[]): ParsedIngredient[];
|
|
414
|
-
|
|
415
|
-
declare function parseDuration(iso: string): number | null;
|
|
416
|
-
declare function parseDuration(iso: string | null | undefined): number | null;
|
|
417
|
-
declare function formatDuration(minutes: number): string;
|
|
418
|
-
declare function formatDuration(minutes: number | null | undefined): string;
|
|
419
|
-
declare function parseHumanDuration(text: string): number | null;
|
|
420
|
-
declare function parseHumanDuration(text: string | null | undefined): number | null;
|
|
421
|
-
declare function smartParseDuration(input: string): number | null;
|
|
422
|
-
declare function smartParseDuration(input: string | null | undefined): number | null;
|
|
423
|
-
|
|
424
|
-
declare function normalizeYield(text: string): string;
|
|
425
|
-
declare function parseYield(text: string): ParsedYield | null;
|
|
426
|
-
declare function formatYield(value: ParsedYield): string;
|
|
351
|
+
declare const SOUSTACK_SPEC_VERSION = "0.2.1";
|
|
427
352
|
|
|
428
|
-
export { type Alternative, type
|
|
353
|
+
export { type Alternative, type Equipment, type FrozenStorageMethod, type Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type MakeAheadComponent, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity, type Recipe, SOUSTACK_SPEC_VERSION, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingProportional, type SimpleTime, type Source, type SoustackInstruction, type SoustackRecipe, type StepTiming, type Storage, type StorageMethod, type StructuredTime, type Substitution, type Time, type Yield, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, scaleRecipe, toSchemaOrg, validateRecipe };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Soustack Recipe Schema v0.1
|
|
2
|
+
* Soustack Recipe Schema v0.2.1
|
|
3
3
|
* A portable, scalable, interoperable recipe format.
|
|
4
4
|
*/
|
|
5
|
-
interface
|
|
5
|
+
interface SoustackRecipe {
|
|
6
|
+
/** Optional $schema pointer for profile-aware validation */
|
|
7
|
+
$schema?: string;
|
|
6
8
|
/** Unique identifier (slug or UUID) */
|
|
7
9
|
id?: string;
|
|
10
|
+
/** Optional display title */
|
|
11
|
+
title?: string;
|
|
8
12
|
/** The title of the recipe */
|
|
9
13
|
name: string;
|
|
10
14
|
/** Semantic versioning (e.g., 1.0.0) */
|
|
15
|
+
recipeVersion?: string;
|
|
16
|
+
/** Deprecated alias for recipeVersion */
|
|
11
17
|
version?: string;
|
|
12
18
|
description?: string;
|
|
13
19
|
/** Primary category (e.g., "Main Course") */
|
|
14
20
|
category?: string;
|
|
15
21
|
/** Additional tags for filtering */
|
|
16
22
|
tags?: string[];
|
|
17
|
-
/** URL to recipe image */
|
|
18
|
-
image?: string;
|
|
23
|
+
/** URL(s) to recipe image(s) */
|
|
24
|
+
image?: string | string[];
|
|
19
25
|
/** ISO 8601 date string */
|
|
20
26
|
dateAdded?: string;
|
|
21
27
|
/** Last updated timestamp */
|
|
@@ -29,7 +35,10 @@ interface Recipe {
|
|
|
29
35
|
storage?: Storage;
|
|
30
36
|
substitutions?: Substitution[];
|
|
31
37
|
nutrition?: NutritionFacts;
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
[k: `x-${string}`]: unknown;
|
|
32
40
|
}
|
|
41
|
+
type Recipe = SoustackRecipe;
|
|
33
42
|
interface Source {
|
|
34
43
|
author?: string;
|
|
35
44
|
url?: string;
|
|
@@ -147,7 +156,7 @@ interface InstructionSubsection {
|
|
|
147
156
|
subsection: string;
|
|
148
157
|
items: (string | Instruction)[];
|
|
149
158
|
}
|
|
150
|
-
interface
|
|
159
|
+
interface SoustackInstruction {
|
|
151
160
|
id?: string;
|
|
152
161
|
text: string;
|
|
153
162
|
destination?: string;
|
|
@@ -156,9 +165,12 @@ interface Instruction {
|
|
|
156
165
|
/** IDs of ingredients used in this step */
|
|
157
166
|
inputs?: string[];
|
|
158
167
|
timing?: StepTiming;
|
|
168
|
+
/** Optional image URL for this instruction */
|
|
169
|
+
image?: string;
|
|
159
170
|
}
|
|
171
|
+
type Instruction = SoustackInstruction;
|
|
160
172
|
interface StepTiming {
|
|
161
|
-
duration: number;
|
|
173
|
+
duration: number | string;
|
|
162
174
|
type: "active" | "passive";
|
|
163
175
|
scaling?: "linear" | "fixed" | "sqrt";
|
|
164
176
|
}
|
|
@@ -207,46 +219,43 @@ interface NutritionFacts {
|
|
|
207
219
|
[key: string]: string | number | null | string[] | undefined;
|
|
208
220
|
}
|
|
209
221
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
metadata: {
|
|
216
|
-
targetYield: number;
|
|
217
|
-
baseYield: number;
|
|
218
|
-
multiplier: number;
|
|
219
|
-
};
|
|
220
|
-
ingredients: ComputedIngredient[];
|
|
221
|
-
instructions: ComputedInstruction[];
|
|
222
|
-
timing: {
|
|
223
|
-
active: number;
|
|
224
|
-
passive: number;
|
|
225
|
-
total: number;
|
|
222
|
+
interface ScaleRecipeOptions {
|
|
223
|
+
multiplier?: number;
|
|
224
|
+
targetYield?: {
|
|
225
|
+
amount: number;
|
|
226
|
+
unit?: string;
|
|
226
227
|
};
|
|
227
228
|
}
|
|
228
|
-
|
|
229
|
-
id: string;
|
|
230
|
-
name: string;
|
|
231
|
-
amount: number;
|
|
232
|
-
unit: string | null;
|
|
233
|
-
text: string;
|
|
234
|
-
notes?: string;
|
|
235
|
-
}
|
|
236
|
-
interface ComputedInstruction {
|
|
237
|
-
id: string;
|
|
238
|
-
text: string;
|
|
239
|
-
durationMinutes: number;
|
|
240
|
-
type: 'active' | 'passive';
|
|
241
|
-
}
|
|
242
|
-
declare function scaleRecipe(recipe: Recipe, targetYieldAmount: number): ComputedRecipe;
|
|
229
|
+
declare function scaleRecipe(recipe: Recipe, options?: ScaleRecipeOptions): Recipe;
|
|
243
230
|
|
|
244
|
-
|
|
231
|
+
type ProfileName = "base" | "cookable" | "scalable" | "quantified" | "illustrated" | "schedulable";
|
|
232
|
+
interface NormalizedError {
|
|
233
|
+
path: string;
|
|
234
|
+
message: string;
|
|
235
|
+
keyword?: string;
|
|
236
|
+
}
|
|
237
|
+
interface NormalizedWarning {
|
|
238
|
+
path: string;
|
|
239
|
+
message: string;
|
|
240
|
+
}
|
|
241
|
+
interface ValidateOptions {
|
|
242
|
+
profile?: ProfileName;
|
|
243
|
+
schema?: string;
|
|
244
|
+
collectAllErrors?: boolean;
|
|
245
|
+
}
|
|
246
|
+
interface ValidationResult {
|
|
247
|
+
valid: boolean;
|
|
248
|
+
errors: NormalizedError[];
|
|
249
|
+
warnings: NormalizedWarning[];
|
|
250
|
+
normalized?: Recipe;
|
|
251
|
+
}
|
|
252
|
+
declare function validateRecipe(input: any, options?: ValidateOptions): ValidationResult;
|
|
253
|
+
declare function detectProfiles(recipe: any): ProfileName[];
|
|
245
254
|
|
|
246
255
|
declare function fromSchemaOrg(input: unknown): Recipe | null;
|
|
247
256
|
|
|
248
257
|
interface SchemaOrgRecipe$1 {
|
|
249
|
-
'@context'?: string
|
|
258
|
+
'@context'?: string | Array<string | Record<string, unknown>> | Record<string, unknown>;
|
|
250
259
|
'@type'?: string | string[];
|
|
251
260
|
name: string;
|
|
252
261
|
description?: string;
|
|
@@ -275,6 +284,9 @@ interface SchemaOrgImageObject {
|
|
|
275
284
|
'@type'?: string;
|
|
276
285
|
url?: string;
|
|
277
286
|
contentUrl?: string;
|
|
287
|
+
width?: number;
|
|
288
|
+
height?: number;
|
|
289
|
+
[key: string]: unknown;
|
|
278
290
|
}
|
|
279
291
|
type SchemaOrgImage = string | SchemaOrgImageObject | Array<string | SchemaOrgImageObject>;
|
|
280
292
|
interface SchemaOrgYield {
|
|
@@ -287,7 +299,13 @@ interface HowToStep$1 {
|
|
|
287
299
|
text?: string;
|
|
288
300
|
name?: string;
|
|
289
301
|
url?: string;
|
|
290
|
-
image?:
|
|
302
|
+
image?: SchemaOrgImage;
|
|
303
|
+
'@id'?: string;
|
|
304
|
+
id?: string;
|
|
305
|
+
totalTime?: string;
|
|
306
|
+
performTime?: string;
|
|
307
|
+
prepTime?: string;
|
|
308
|
+
duration?: string;
|
|
291
309
|
}
|
|
292
310
|
interface HowToSection {
|
|
293
311
|
'@type': 'HowToSection';
|
|
@@ -327,102 +345,9 @@ interface SchemaOrgRecipe {
|
|
|
327
345
|
aggregateRating?: unknown;
|
|
328
346
|
[key: string]: unknown;
|
|
329
347
|
}
|
|
330
|
-
interface FetchRequestInit {
|
|
331
|
-
headers?: Record<string, string>;
|
|
332
|
-
signal?: AbortSignal;
|
|
333
|
-
redirect?: 'follow' | 'error' | 'manual';
|
|
334
|
-
}
|
|
335
|
-
interface FetchResponse {
|
|
336
|
-
ok: boolean;
|
|
337
|
-
status: number;
|
|
338
|
-
statusText: string;
|
|
339
|
-
text(): Promise<string>;
|
|
340
|
-
}
|
|
341
|
-
type FetchImplementation = (url: string, init?: FetchRequestInit) => Promise<FetchResponse>;
|
|
342
|
-
interface FetchOptions {
|
|
343
|
-
timeout?: number;
|
|
344
|
-
userAgent?: string;
|
|
345
|
-
maxRetries?: number;
|
|
346
|
-
fetchFn?: FetchImplementation;
|
|
347
|
-
}
|
|
348
|
-
interface ScrapeRecipeOptions extends FetchOptions {
|
|
349
|
-
}
|
|
350
348
|
|
|
351
|
-
/**
|
|
352
|
-
* Scrapes a recipe from a URL (Node.js only).
|
|
353
|
-
*
|
|
354
|
-
* ⚠️ Not available in browser environments due to CORS restrictions.
|
|
355
|
-
* For browser usage, fetch the HTML yourself and use extractRecipeFromHTML().
|
|
356
|
-
*
|
|
357
|
-
* @param url - The URL of the recipe page to scrape
|
|
358
|
-
* @param options - Fetch options (timeout, userAgent, maxRetries)
|
|
359
|
-
* @returns A Soustack recipe object
|
|
360
|
-
* @throws Error if no recipe is found
|
|
361
|
-
*/
|
|
362
|
-
declare function scrapeRecipe(url: string, options?: ScrapeRecipeOptions): Promise<Recipe>;
|
|
363
|
-
/**
|
|
364
|
-
* Extracts a recipe from HTML string (browser and Node.js compatible).
|
|
365
|
-
*
|
|
366
|
-
* This function works in both environments and doesn't require network access.
|
|
367
|
-
* Perfect for browser usage where you fetch HTML yourself (with cookies/session).
|
|
368
|
-
*
|
|
369
|
-
* @example
|
|
370
|
-
* ```ts
|
|
371
|
-
* // In browser:
|
|
372
|
-
* const response = await fetch('https://example.com/recipe');
|
|
373
|
-
* const html = await response.text();
|
|
374
|
-
* const recipe = extractRecipeFromHTML(html);
|
|
375
|
-
* ```
|
|
376
|
-
*
|
|
377
|
-
* @param html - The HTML string containing Schema.org recipe data
|
|
378
|
-
* @returns A Soustack recipe object
|
|
379
|
-
* @throws Error if no recipe is found
|
|
380
|
-
*/
|
|
381
|
-
declare function extractRecipeFromHTML(html: string): Recipe;
|
|
382
|
-
/**
|
|
383
|
-
* Extract Schema.org recipe data from HTML string (browser-compatible).
|
|
384
|
-
*
|
|
385
|
-
* Returns the raw Schema.org recipe object, which can then be converted
|
|
386
|
-
* to Soustack format using fromSchemaOrg(). This gives you access to the
|
|
387
|
-
* original Schema.org data for inspection, debugging, or custom transformations.
|
|
388
|
-
*
|
|
389
|
-
* @param html - HTML string containing Schema.org recipe data
|
|
390
|
-
* @returns Schema.org recipe object, or null if not found
|
|
391
|
-
*
|
|
392
|
-
* @example
|
|
393
|
-
* ```ts
|
|
394
|
-
* // In browser:
|
|
395
|
-
* const response = await fetch('https://example.com/recipe');
|
|
396
|
-
* const html = await response.text();
|
|
397
|
-
* const schemaOrgRecipe = extractSchemaOrgRecipeFromHTML(html);
|
|
398
|
-
*
|
|
399
|
-
* if (schemaOrgRecipe) {
|
|
400
|
-
* // Inspect or modify Schema.org data before converting
|
|
401
|
-
* console.log('Found recipe:', schemaOrgRecipe.name);
|
|
402
|
-
*
|
|
403
|
-
* // Convert to Soustack format
|
|
404
|
-
* const soustackRecipe = fromSchemaOrg(schemaOrgRecipe);
|
|
405
|
-
* }
|
|
406
|
-
* ```
|
|
407
|
-
*/
|
|
408
349
|
declare function extractSchemaOrgRecipeFromHTML(html: string): SchemaOrgRecipe | null;
|
|
409
350
|
|
|
410
|
-
declare
|
|
411
|
-
declare function parseIngredient(text: string): ParsedIngredient;
|
|
412
|
-
declare function parseIngredientLine(text: string): ParsedIngredient;
|
|
413
|
-
declare function parseIngredients(texts: string[]): ParsedIngredient[];
|
|
414
|
-
|
|
415
|
-
declare function parseDuration(iso: string): number | null;
|
|
416
|
-
declare function parseDuration(iso: string | null | undefined): number | null;
|
|
417
|
-
declare function formatDuration(minutes: number): string;
|
|
418
|
-
declare function formatDuration(minutes: number | null | undefined): string;
|
|
419
|
-
declare function parseHumanDuration(text: string): number | null;
|
|
420
|
-
declare function parseHumanDuration(text: string | null | undefined): number | null;
|
|
421
|
-
declare function smartParseDuration(input: string): number | null;
|
|
422
|
-
declare function smartParseDuration(input: string | null | undefined): number | null;
|
|
423
|
-
|
|
424
|
-
declare function normalizeYield(text: string): string;
|
|
425
|
-
declare function parseYield(text: string): ParsedYield | null;
|
|
426
|
-
declare function formatYield(value: ParsedYield): string;
|
|
351
|
+
declare const SOUSTACK_SPEC_VERSION = "0.2.1";
|
|
427
352
|
|
|
428
|
-
export { type Alternative, type
|
|
353
|
+
export { type Alternative, type Equipment, type FrozenStorageMethod, type Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type MakeAheadComponent, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity, type Recipe, SOUSTACK_SPEC_VERSION, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingProportional, type SimpleTime, type Source, type SoustackInstruction, type SoustackRecipe, type StepTiming, type Storage, type StorageMethod, type StructuredTime, type Substitution, type Time, type Yield, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, scaleRecipe, toSchemaOrg, validateRecipe };
|