soustack 0.1.0

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.
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Soustack Recipe Schema v0.1
3
+ * A portable, scalable, interoperable recipe format.
4
+ */
5
+ interface Recipe {
6
+ /** Unique identifier (slug or UUID) */
7
+ id?: string;
8
+ /** The title of the recipe */
9
+ name: string;
10
+ /** Semantic versioning (e.g., 1.0.0) */
11
+ version?: string;
12
+ description?: string;
13
+ /** Primary category (e.g., "Main Course") */
14
+ category?: string;
15
+ /** Additional tags for filtering */
16
+ tags?: string[];
17
+ /** URL to recipe image */
18
+ image?: string;
19
+ /** ISO 8601 date string */
20
+ dateAdded?: string;
21
+ /** Last updated timestamp */
22
+ dateModified?: string;
23
+ source?: Source;
24
+ yield?: Yield;
25
+ time?: Time;
26
+ equipment?: Equipment[];
27
+ ingredients: IngredientItem[];
28
+ instructions: InstructionItem[];
29
+ storage?: Storage;
30
+ substitutions?: Substitution[];
31
+ nutrition?: NutritionFacts;
32
+ }
33
+ interface Source {
34
+ author?: string;
35
+ url?: string;
36
+ name?: string;
37
+ adapted?: boolean;
38
+ }
39
+ interface Yield {
40
+ amount: number;
41
+ unit: string;
42
+ servings?: number;
43
+ description?: string;
44
+ }
45
+ interface ParsedYield {
46
+ amount: number;
47
+ unit: string;
48
+ servings?: number;
49
+ description?: string;
50
+ }
51
+ /**
52
+ * Time can be structured (machine-readable) or simple (strings).
53
+ * Structured time takes precedence if both exist.
54
+ */
55
+ type Time = StructuredTime | SimpleTime;
56
+ interface StructuredTime {
57
+ prep?: number;
58
+ active?: number;
59
+ passive?: number;
60
+ total?: number;
61
+ }
62
+ interface SimpleTime {
63
+ prepTime?: string;
64
+ cookTime?: string;
65
+ }
66
+ interface Equipment {
67
+ id?: string;
68
+ name: string;
69
+ required?: boolean;
70
+ label?: string;
71
+ capacity?: Quantity;
72
+ scalingLimit?: number;
73
+ alternatives?: string[];
74
+ }
75
+ interface Quantity {
76
+ amount: number;
77
+ /** Unit string (e.g. "g", "cup") or null for count-based items (e.g. "2 eggs") */
78
+ unit: string | null;
79
+ }
80
+ type IngredientItem = string | Ingredient | IngredientSubsection;
81
+ interface IngredientSubsection {
82
+ subsection: string;
83
+ items: (string | Ingredient)[];
84
+ }
85
+ interface Ingredient {
86
+ id?: string;
87
+ /** Full human-readable text (e.g. "2 cups flour") */
88
+ item: string;
89
+ quantity?: Quantity;
90
+ name?: string;
91
+ aisle?: string;
92
+ /** Required prep state (e.g. "diced") */
93
+ prep?: string;
94
+ prepAction?: string;
95
+ prepTime?: number;
96
+ /** ID of equipment where this ingredient goes */
97
+ destination?: string;
98
+ scaling?: Scaling;
99
+ critical?: boolean;
100
+ optional?: boolean;
101
+ notes?: string;
102
+ }
103
+ interface ParsedIngredient {
104
+ item: string;
105
+ quantity?: {
106
+ amount: number | null;
107
+ unit: string | null;
108
+ };
109
+ name?: string;
110
+ prep?: string;
111
+ optional?: boolean;
112
+ notes?: string;
113
+ scaling?: Scaling;
114
+ }
115
+ /**
116
+ * Intelligent Scaling Logic
117
+ * Defines how an ingredient behaves when the recipe yield changes.
118
+ */
119
+ type Scaling = ScalingLinear | ScalingDiscrete | ScalingProportional | ScalingFixed | ScalingBakersPercentage;
120
+ interface ScalingBase {
121
+ min?: number;
122
+ max?: number;
123
+ }
124
+ interface ScalingLinear extends ScalingBase {
125
+ type: "linear";
126
+ }
127
+ interface ScalingDiscrete extends ScalingBase {
128
+ type: "discrete";
129
+ roundTo?: number;
130
+ }
131
+ interface ScalingProportional extends ScalingBase {
132
+ type: "proportional";
133
+ factor?: number;
134
+ }
135
+ interface ScalingFixed extends ScalingBase {
136
+ type: "fixed";
137
+ }
138
+ interface ScalingBakersPercentage extends ScalingBase {
139
+ type: 'bakers_percentage';
140
+ /** The ID of the flour/base ingredient this is relative to */
141
+ referenceId: string;
142
+ /** The percentage relative to the reference (e.g. 0.02 for 2%) */
143
+ factor?: number;
144
+ }
145
+ type InstructionItem = string | Instruction | InstructionSubsection;
146
+ interface InstructionSubsection {
147
+ subsection: string;
148
+ items: (string | Instruction)[];
149
+ }
150
+ interface Instruction {
151
+ id?: string;
152
+ text: string;
153
+ destination?: string;
154
+ /** IDs of steps that must complete before this one starts */
155
+ dependsOn?: string[];
156
+ /** IDs of ingredients used in this step */
157
+ inputs?: string[];
158
+ timing?: StepTiming;
159
+ }
160
+ interface StepTiming {
161
+ duration: number;
162
+ type: "active" | "passive";
163
+ scaling?: "linear" | "fixed" | "sqrt";
164
+ }
165
+ interface Storage {
166
+ roomTemp?: StorageMethod;
167
+ refrigerated?: StorageMethod;
168
+ frozen?: FrozenStorageMethod;
169
+ reheating?: string;
170
+ makeAhead?: MakeAheadComponent[];
171
+ }
172
+ interface StorageMethod {
173
+ /** ISO 8601 duration (e.g. P3D) */
174
+ duration: string;
175
+ method?: string;
176
+ notes?: string;
177
+ }
178
+ interface FrozenStorageMethod extends StorageMethod {
179
+ thawing?: string;
180
+ }
181
+ interface MakeAheadComponent extends StorageMethod {
182
+ component: string;
183
+ storage: "roomTemp" | "refrigerated" | "frozen";
184
+ }
185
+ interface Substitution {
186
+ ingredient: string;
187
+ critical?: boolean;
188
+ notes?: string;
189
+ alternatives?: Alternative[];
190
+ }
191
+ interface Alternative {
192
+ name: string;
193
+ ratio: string;
194
+ notes?: string;
195
+ impact?: string;
196
+ dietary?: string[];
197
+ }
198
+ interface NutritionFacts {
199
+ calories?: string;
200
+ fatContent?: string;
201
+ carbohydrateContent?: string;
202
+ proteinContent?: string;
203
+ fiberContent?: string;
204
+ sugarContent?: string;
205
+ sodiumContent?: string;
206
+ servingSize?: string;
207
+ [key: string]: string | number | null | string[] | undefined;
208
+ }
209
+
210
+ /**
211
+ * A "Computed Recipe" is the result of running the parser.
212
+ * It is flat, strict, and ready for the UI to render.
213
+ */
214
+ interface ComputedRecipe {
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;
226
+ };
227
+ }
228
+ interface ComputedIngredient {
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;
243
+
244
+ declare function validateRecipe(data: any): data is Recipe;
245
+
246
+ declare function fromSchemaOrg(input: unknown): Recipe | null;
247
+
248
+ interface SchemaOrgRecipe {
249
+ '@context'?: string;
250
+ '@type'?: string | string[];
251
+ name: string;
252
+ description?: string;
253
+ image?: SchemaOrgImage;
254
+ recipeIngredient?: SchemaOrgIngredientList;
255
+ recipeInstructions?: SchemaOrgInstructionList;
256
+ recipeYield?: string | number | SchemaOrgYield | Array<string | number | SchemaOrgYield>;
257
+ prepTime?: string;
258
+ cookTime?: string;
259
+ totalTime?: string;
260
+ recipeCategory?: string | string[];
261
+ recipeCuisine?: string | string[];
262
+ keywords?: string;
263
+ author?: SchemaOrgPersonOrOrganization | SchemaOrgPersonOrOrganization[] | string | string[];
264
+ publisher?: SchemaOrgPersonOrOrganization | SchemaOrgPersonOrOrganization[] | string | string[];
265
+ url?: string;
266
+ mainEntityOfPage?: string;
267
+ datePublished?: string;
268
+ dateModified?: string;
269
+ nutrition?: NutritionInformation;
270
+ '@graph'?: unknown;
271
+ }
272
+ type SchemaOrgIngredientList = string | string[];
273
+ type SchemaOrgInstructionList = string | HowToStep | HowToSection | Array<string | HowToStep | HowToSection>;
274
+ interface SchemaOrgImageObject {
275
+ '@type'?: string;
276
+ url?: string;
277
+ contentUrl?: string;
278
+ }
279
+ type SchemaOrgImage = string | SchemaOrgImageObject | Array<string | SchemaOrgImageObject>;
280
+ interface SchemaOrgYield {
281
+ amount?: number;
282
+ unit?: string;
283
+ description?: string;
284
+ }
285
+ interface HowToStep {
286
+ '@type': 'HowToStep';
287
+ text?: string;
288
+ name?: string;
289
+ url?: string;
290
+ image?: string;
291
+ }
292
+ interface HowToSection {
293
+ '@type': 'HowToSection';
294
+ name: string;
295
+ itemListElement: Array<string | HowToStep | HowToSection>;
296
+ }
297
+ interface SchemaOrgPersonOrOrganization {
298
+ '@type'?: 'Person' | 'Organization';
299
+ name?: string;
300
+ url?: string;
301
+ }
302
+ interface NutritionInformation {
303
+ [key: string]: string | number | null | undefined;
304
+ }
305
+
306
+ declare function toSchemaOrg(recipe: Recipe): SchemaOrgRecipe;
307
+
308
+ interface FetchOptions {
309
+ timeout?: number;
310
+ userAgent?: string;
311
+ maxRetries?: number;
312
+ }
313
+ interface ScrapeRecipeOptions extends FetchOptions {
314
+ }
315
+
316
+ declare function scrapeRecipe(url: string, options?: ScrapeRecipeOptions): Promise<Recipe>;
317
+
318
+ declare function normalizeIngredientInput(input: string): string;
319
+ declare function parseIngredient(text: string): ParsedIngredient;
320
+ declare function parseIngredientLine(text: string): ParsedIngredient;
321
+ declare function parseIngredients(texts: string[]): ParsedIngredient[];
322
+
323
+ declare function parseDuration(iso: string): number | null;
324
+ declare function parseDuration(iso: string | null | undefined): number | null;
325
+ declare function formatDuration(minutes: number): string;
326
+ declare function formatDuration(minutes: number | null | undefined): string;
327
+ declare function parseHumanDuration(text: string): number | null;
328
+ declare function parseHumanDuration(text: string | null | undefined): number | null;
329
+ declare function smartParseDuration(input: string): number | null;
330
+ declare function smartParseDuration(input: string | null | undefined): number | null;
331
+
332
+ declare function normalizeYield(text: string): string;
333
+ declare function parseYield(text: string): ParsedYield | null;
334
+ declare function formatYield(value: ParsedYield): string;
335
+
336
+ export { type Alternative, type ComputedIngredient, type ComputedInstruction, type ComputedRecipe, 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, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingProportional, type SimpleTime, type Source, type StepTiming, type Storage, type StorageMethod, type StructuredTime, type Substitution, type Time, type Yield, formatDuration, formatYield, fromSchemaOrg, normalizeIngredientInput, normalizeYield, parseDuration, parseHumanDuration, parseIngredient, parseIngredientLine, parseIngredients, parseYield, scaleRecipe, scrapeRecipe, smartParseDuration, toSchemaOrg, validateRecipe };
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Soustack Recipe Schema v0.1
3
+ * A portable, scalable, interoperable recipe format.
4
+ */
5
+ interface Recipe {
6
+ /** Unique identifier (slug or UUID) */
7
+ id?: string;
8
+ /** The title of the recipe */
9
+ name: string;
10
+ /** Semantic versioning (e.g., 1.0.0) */
11
+ version?: string;
12
+ description?: string;
13
+ /** Primary category (e.g., "Main Course") */
14
+ category?: string;
15
+ /** Additional tags for filtering */
16
+ tags?: string[];
17
+ /** URL to recipe image */
18
+ image?: string;
19
+ /** ISO 8601 date string */
20
+ dateAdded?: string;
21
+ /** Last updated timestamp */
22
+ dateModified?: string;
23
+ source?: Source;
24
+ yield?: Yield;
25
+ time?: Time;
26
+ equipment?: Equipment[];
27
+ ingredients: IngredientItem[];
28
+ instructions: InstructionItem[];
29
+ storage?: Storage;
30
+ substitutions?: Substitution[];
31
+ nutrition?: NutritionFacts;
32
+ }
33
+ interface Source {
34
+ author?: string;
35
+ url?: string;
36
+ name?: string;
37
+ adapted?: boolean;
38
+ }
39
+ interface Yield {
40
+ amount: number;
41
+ unit: string;
42
+ servings?: number;
43
+ description?: string;
44
+ }
45
+ interface ParsedYield {
46
+ amount: number;
47
+ unit: string;
48
+ servings?: number;
49
+ description?: string;
50
+ }
51
+ /**
52
+ * Time can be structured (machine-readable) or simple (strings).
53
+ * Structured time takes precedence if both exist.
54
+ */
55
+ type Time = StructuredTime | SimpleTime;
56
+ interface StructuredTime {
57
+ prep?: number;
58
+ active?: number;
59
+ passive?: number;
60
+ total?: number;
61
+ }
62
+ interface SimpleTime {
63
+ prepTime?: string;
64
+ cookTime?: string;
65
+ }
66
+ interface Equipment {
67
+ id?: string;
68
+ name: string;
69
+ required?: boolean;
70
+ label?: string;
71
+ capacity?: Quantity;
72
+ scalingLimit?: number;
73
+ alternatives?: string[];
74
+ }
75
+ interface Quantity {
76
+ amount: number;
77
+ /** Unit string (e.g. "g", "cup") or null for count-based items (e.g. "2 eggs") */
78
+ unit: string | null;
79
+ }
80
+ type IngredientItem = string | Ingredient | IngredientSubsection;
81
+ interface IngredientSubsection {
82
+ subsection: string;
83
+ items: (string | Ingredient)[];
84
+ }
85
+ interface Ingredient {
86
+ id?: string;
87
+ /** Full human-readable text (e.g. "2 cups flour") */
88
+ item: string;
89
+ quantity?: Quantity;
90
+ name?: string;
91
+ aisle?: string;
92
+ /** Required prep state (e.g. "diced") */
93
+ prep?: string;
94
+ prepAction?: string;
95
+ prepTime?: number;
96
+ /** ID of equipment where this ingredient goes */
97
+ destination?: string;
98
+ scaling?: Scaling;
99
+ critical?: boolean;
100
+ optional?: boolean;
101
+ notes?: string;
102
+ }
103
+ interface ParsedIngredient {
104
+ item: string;
105
+ quantity?: {
106
+ amount: number | null;
107
+ unit: string | null;
108
+ };
109
+ name?: string;
110
+ prep?: string;
111
+ optional?: boolean;
112
+ notes?: string;
113
+ scaling?: Scaling;
114
+ }
115
+ /**
116
+ * Intelligent Scaling Logic
117
+ * Defines how an ingredient behaves when the recipe yield changes.
118
+ */
119
+ type Scaling = ScalingLinear | ScalingDiscrete | ScalingProportional | ScalingFixed | ScalingBakersPercentage;
120
+ interface ScalingBase {
121
+ min?: number;
122
+ max?: number;
123
+ }
124
+ interface ScalingLinear extends ScalingBase {
125
+ type: "linear";
126
+ }
127
+ interface ScalingDiscrete extends ScalingBase {
128
+ type: "discrete";
129
+ roundTo?: number;
130
+ }
131
+ interface ScalingProportional extends ScalingBase {
132
+ type: "proportional";
133
+ factor?: number;
134
+ }
135
+ interface ScalingFixed extends ScalingBase {
136
+ type: "fixed";
137
+ }
138
+ interface ScalingBakersPercentage extends ScalingBase {
139
+ type: 'bakers_percentage';
140
+ /** The ID of the flour/base ingredient this is relative to */
141
+ referenceId: string;
142
+ /** The percentage relative to the reference (e.g. 0.02 for 2%) */
143
+ factor?: number;
144
+ }
145
+ type InstructionItem = string | Instruction | InstructionSubsection;
146
+ interface InstructionSubsection {
147
+ subsection: string;
148
+ items: (string | Instruction)[];
149
+ }
150
+ interface Instruction {
151
+ id?: string;
152
+ text: string;
153
+ destination?: string;
154
+ /** IDs of steps that must complete before this one starts */
155
+ dependsOn?: string[];
156
+ /** IDs of ingredients used in this step */
157
+ inputs?: string[];
158
+ timing?: StepTiming;
159
+ }
160
+ interface StepTiming {
161
+ duration: number;
162
+ type: "active" | "passive";
163
+ scaling?: "linear" | "fixed" | "sqrt";
164
+ }
165
+ interface Storage {
166
+ roomTemp?: StorageMethod;
167
+ refrigerated?: StorageMethod;
168
+ frozen?: FrozenStorageMethod;
169
+ reheating?: string;
170
+ makeAhead?: MakeAheadComponent[];
171
+ }
172
+ interface StorageMethod {
173
+ /** ISO 8601 duration (e.g. P3D) */
174
+ duration: string;
175
+ method?: string;
176
+ notes?: string;
177
+ }
178
+ interface FrozenStorageMethod extends StorageMethod {
179
+ thawing?: string;
180
+ }
181
+ interface MakeAheadComponent extends StorageMethod {
182
+ component: string;
183
+ storage: "roomTemp" | "refrigerated" | "frozen";
184
+ }
185
+ interface Substitution {
186
+ ingredient: string;
187
+ critical?: boolean;
188
+ notes?: string;
189
+ alternatives?: Alternative[];
190
+ }
191
+ interface Alternative {
192
+ name: string;
193
+ ratio: string;
194
+ notes?: string;
195
+ impact?: string;
196
+ dietary?: string[];
197
+ }
198
+ interface NutritionFacts {
199
+ calories?: string;
200
+ fatContent?: string;
201
+ carbohydrateContent?: string;
202
+ proteinContent?: string;
203
+ fiberContent?: string;
204
+ sugarContent?: string;
205
+ sodiumContent?: string;
206
+ servingSize?: string;
207
+ [key: string]: string | number | null | string[] | undefined;
208
+ }
209
+
210
+ /**
211
+ * A "Computed Recipe" is the result of running the parser.
212
+ * It is flat, strict, and ready for the UI to render.
213
+ */
214
+ interface ComputedRecipe {
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;
226
+ };
227
+ }
228
+ interface ComputedIngredient {
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;
243
+
244
+ declare function validateRecipe(data: any): data is Recipe;
245
+
246
+ declare function fromSchemaOrg(input: unknown): Recipe | null;
247
+
248
+ interface SchemaOrgRecipe {
249
+ '@context'?: string;
250
+ '@type'?: string | string[];
251
+ name: string;
252
+ description?: string;
253
+ image?: SchemaOrgImage;
254
+ recipeIngredient?: SchemaOrgIngredientList;
255
+ recipeInstructions?: SchemaOrgInstructionList;
256
+ recipeYield?: string | number | SchemaOrgYield | Array<string | number | SchemaOrgYield>;
257
+ prepTime?: string;
258
+ cookTime?: string;
259
+ totalTime?: string;
260
+ recipeCategory?: string | string[];
261
+ recipeCuisine?: string | string[];
262
+ keywords?: string;
263
+ author?: SchemaOrgPersonOrOrganization | SchemaOrgPersonOrOrganization[] | string | string[];
264
+ publisher?: SchemaOrgPersonOrOrganization | SchemaOrgPersonOrOrganization[] | string | string[];
265
+ url?: string;
266
+ mainEntityOfPage?: string;
267
+ datePublished?: string;
268
+ dateModified?: string;
269
+ nutrition?: NutritionInformation;
270
+ '@graph'?: unknown;
271
+ }
272
+ type SchemaOrgIngredientList = string | string[];
273
+ type SchemaOrgInstructionList = string | HowToStep | HowToSection | Array<string | HowToStep | HowToSection>;
274
+ interface SchemaOrgImageObject {
275
+ '@type'?: string;
276
+ url?: string;
277
+ contentUrl?: string;
278
+ }
279
+ type SchemaOrgImage = string | SchemaOrgImageObject | Array<string | SchemaOrgImageObject>;
280
+ interface SchemaOrgYield {
281
+ amount?: number;
282
+ unit?: string;
283
+ description?: string;
284
+ }
285
+ interface HowToStep {
286
+ '@type': 'HowToStep';
287
+ text?: string;
288
+ name?: string;
289
+ url?: string;
290
+ image?: string;
291
+ }
292
+ interface HowToSection {
293
+ '@type': 'HowToSection';
294
+ name: string;
295
+ itemListElement: Array<string | HowToStep | HowToSection>;
296
+ }
297
+ interface SchemaOrgPersonOrOrganization {
298
+ '@type'?: 'Person' | 'Organization';
299
+ name?: string;
300
+ url?: string;
301
+ }
302
+ interface NutritionInformation {
303
+ [key: string]: string | number | null | undefined;
304
+ }
305
+
306
+ declare function toSchemaOrg(recipe: Recipe): SchemaOrgRecipe;
307
+
308
+ interface FetchOptions {
309
+ timeout?: number;
310
+ userAgent?: string;
311
+ maxRetries?: number;
312
+ }
313
+ interface ScrapeRecipeOptions extends FetchOptions {
314
+ }
315
+
316
+ declare function scrapeRecipe(url: string, options?: ScrapeRecipeOptions): Promise<Recipe>;
317
+
318
+ declare function normalizeIngredientInput(input: string): string;
319
+ declare function parseIngredient(text: string): ParsedIngredient;
320
+ declare function parseIngredientLine(text: string): ParsedIngredient;
321
+ declare function parseIngredients(texts: string[]): ParsedIngredient[];
322
+
323
+ declare function parseDuration(iso: string): number | null;
324
+ declare function parseDuration(iso: string | null | undefined): number | null;
325
+ declare function formatDuration(minutes: number): string;
326
+ declare function formatDuration(minutes: number | null | undefined): string;
327
+ declare function parseHumanDuration(text: string): number | null;
328
+ declare function parseHumanDuration(text: string | null | undefined): number | null;
329
+ declare function smartParseDuration(input: string): number | null;
330
+ declare function smartParseDuration(input: string | null | undefined): number | null;
331
+
332
+ declare function normalizeYield(text: string): string;
333
+ declare function parseYield(text: string): ParsedYield | null;
334
+ declare function formatYield(value: ParsedYield): string;
335
+
336
+ export { type Alternative, type ComputedIngredient, type ComputedInstruction, type ComputedRecipe, 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, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingProportional, type SimpleTime, type Source, type StepTiming, type Storage, type StorageMethod, type StructuredTime, type Substitution, type Time, type Yield, formatDuration, formatYield, fromSchemaOrg, normalizeIngredientInput, normalizeYield, parseDuration, parseHumanDuration, parseIngredient, parseIngredientLine, parseIngredients, parseYield, scaleRecipe, scrapeRecipe, smartParseDuration, toSchemaOrg, validateRecipe };