@tmlmt/cooklang-parser 3.0.0-alpha.8 → 3.0.0-elpha.22
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/dist/index.cjs +2716 -585
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +952 -141
- package/dist/index.d.ts +952 -141
- package/dist/index.js +2697 -584
- package/dist/index.js.map +1 -1
- package/package.json +21 -21
package/dist/index.d.ts
CHANGED
|
@@ -16,11 +16,17 @@ declare class Section {
|
|
|
16
16
|
name: string;
|
|
17
17
|
/** An array of steps and notes that make up the content of the section. */
|
|
18
18
|
content: (Step | Note)[];
|
|
19
|
+
/** Optional list of variant names this section belongs to. */
|
|
20
|
+
variants?: string[];
|
|
21
|
+
/** Whether the section has been marked as optional ([?]) */
|
|
22
|
+
optional?: boolean;
|
|
19
23
|
/**
|
|
20
24
|
* Creates an instance of Section.
|
|
21
25
|
* @param name - The name of the section. Defaults to an empty string.
|
|
26
|
+
* @param variants - Optional variant names for this section.
|
|
27
|
+
* @param optional - Whether the section is optional.
|
|
22
28
|
*/
|
|
23
|
-
constructor(name?: string);
|
|
29
|
+
constructor(name?: string, variants?: string[], optional?: boolean);
|
|
24
30
|
/**
|
|
25
31
|
* Checks if the section is blank (has no name and no content).
|
|
26
32
|
* Used during recipe parsing
|
|
@@ -66,8 +72,7 @@ declare class Recipe {
|
|
|
66
72
|
*/
|
|
67
73
|
metadata: Metadata;
|
|
68
74
|
/**
|
|
69
|
-
* The
|
|
70
|
-
* Contains the full context including alternatives list and active selection index.
|
|
75
|
+
* The possible choices of alternative ingredients for this recipe.
|
|
71
76
|
*/
|
|
72
77
|
choices: RecipeAlternatives;
|
|
73
78
|
/**
|
|
@@ -98,11 +103,28 @@ declare class Recipe {
|
|
|
98
103
|
* @see {@link Recipe.scaleBy | scaleBy()} and {@link Recipe.scaleTo | scaleTo()} methods
|
|
99
104
|
*/
|
|
100
105
|
servings?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Gets the unit system specified in the recipe metadata.
|
|
108
|
+
* Used for resolving ambiguous units like tsp, tbsp, cup, etc.
|
|
109
|
+
*
|
|
110
|
+
* @returns The unit system if specified, or undefined to use defaults
|
|
111
|
+
*/
|
|
112
|
+
get unitSystem(): SpecificUnitSystem | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* External storage for unit system (not a property on instances).
|
|
115
|
+
* Used for resolving ambiguous units during quantity addition.
|
|
116
|
+
*/
|
|
117
|
+
private static unitSystems;
|
|
101
118
|
/**
|
|
102
119
|
* External storage for item count (not a property on instances).
|
|
103
120
|
* Used for giving ID numbers to items during parsing.
|
|
104
121
|
*/
|
|
105
122
|
private static itemCounts;
|
|
123
|
+
/**
|
|
124
|
+
* External storage for subgroup index tracking during parsing.
|
|
125
|
+
* Maps groupKey → subgroupKey → index within the subgroups array.
|
|
126
|
+
*/
|
|
127
|
+
private static subgroupIndices;
|
|
106
128
|
/**
|
|
107
129
|
* Gets the current item count for this recipe.
|
|
108
130
|
*/
|
|
@@ -143,16 +165,73 @@ declare class Recipe {
|
|
|
143
165
|
* Quantities are grouped by their alternative signature and summed using addEquivalentsAndSimplify.
|
|
144
166
|
* @internal
|
|
145
167
|
*/
|
|
146
|
-
private
|
|
168
|
+
private _populateIngredientQuantities;
|
|
169
|
+
/** @internal */
|
|
170
|
+
private collectQuantityGroups;
|
|
147
171
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
172
|
+
* Gets the raw (unprocessed) quantity groups for each ingredient, before
|
|
173
|
+
* any summation or equivalents simplification. This is useful for cross-recipe
|
|
174
|
+
* aggregation (e.g., in {@link ShoppingList}), where quantities from multiple
|
|
175
|
+
* recipes should be combined before processing.
|
|
150
176
|
*
|
|
151
|
-
* @param
|
|
152
|
-
*
|
|
153
|
-
*
|
|
177
|
+
* @param options - Options for filtering and choice selection (same as {@link getIngredientQuantities}).
|
|
178
|
+
* @returns Array of {@link RawQuantityGroup} objects, one per ingredient with quantities.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const rawGroups = recipe.getRawQuantityGroups();
|
|
183
|
+
* // Each group has: name, usedAsPrimary, flags, quantities[]
|
|
184
|
+
* // quantities are the raw QuantityWithExtendedUnit or FlatOrGroup entries
|
|
185
|
+
* ```
|
|
154
186
|
*/
|
|
155
|
-
|
|
187
|
+
getRawQuantityGroups(options?: GetIngredientQuantitiesOptions): RawQuantityGroup[];
|
|
188
|
+
/**
|
|
189
|
+
* Gets ingredients with their quantities populated, optionally filtered by section/step
|
|
190
|
+
* and respecting user choices for alternatives.
|
|
191
|
+
*
|
|
192
|
+
* When no options are provided, returns all recipe ingredients with quantities
|
|
193
|
+
* calculated using primary alternatives (same as after parsing).
|
|
194
|
+
*
|
|
195
|
+
* @param options - Options for filtering and choice selection:
|
|
196
|
+
* - `section`: Filter to a specific section (Section object or 0-based index)
|
|
197
|
+
* - `step`: Filter to a specific step (Step object or 0-based index)
|
|
198
|
+
* - `choices`: Choices for alternative ingredients (defaults to primary)
|
|
199
|
+
* @returns Array of Ingredient objects with quantities populated
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* // Get all ingredients with primary alternatives
|
|
204
|
+
* const ingredients = recipe.getIngredientQuantities();
|
|
205
|
+
*
|
|
206
|
+
* // Get ingredients for a specific section
|
|
207
|
+
* const sectionIngredients = recipe.getIngredientQuantities({ section: 0 });
|
|
208
|
+
*
|
|
209
|
+
* // Get ingredients with specific choices applied
|
|
210
|
+
* const withChoices = recipe.getIngredientQuantities({
|
|
211
|
+
* choices: { ingredientItems: new Map([['ingredient-item-2', 1]]) }
|
|
212
|
+
* });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
getIngredientQuantities(options?: GetIngredientQuantitiesOptions): Ingredient[];
|
|
216
|
+
/**
|
|
217
|
+
* Returns the list of cookware items that are used in the active variant.
|
|
218
|
+
* Cookware in steps/sections not matching the active variant are excluded.
|
|
219
|
+
* Hidden cookware is always excluded.
|
|
220
|
+
*
|
|
221
|
+
* @param options - Options for filtering:
|
|
222
|
+
* - `choices`: The choices to apply (only `variant` is used)
|
|
223
|
+
* @returns Array of Cookware objects referenced by active steps
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```typescript
|
|
227
|
+
* // Get all cookware for the default variant
|
|
228
|
+
* const cookware = recipe.getCookwareForVariant();
|
|
229
|
+
*
|
|
230
|
+
* // Get cookware for a specific variant
|
|
231
|
+
* const veganCookware = recipe.getCookwareForVariant({ choices: { variant: 'vegan' } });
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
getCookwareForVariant(options?: Pick<GetIngredientQuantitiesOptions, "choices">): Cookware[];
|
|
156
235
|
/**
|
|
157
236
|
* Parses a recipe from a string.
|
|
158
237
|
* @param content - The recipe content to parse.
|
|
@@ -174,6 +253,26 @@ declare class Recipe {
|
|
|
174
253
|
* @returns A new Recipe instance with the scaled ingredients.
|
|
175
254
|
*/
|
|
176
255
|
scaleBy(factor: number | Big): Recipe;
|
|
256
|
+
/**
|
|
257
|
+
* Converts all ingredient quantities in the recipe to a target unit system.
|
|
258
|
+
*
|
|
259
|
+
* @param system - The target unit system to convert to (metric, US, UK, JP)
|
|
260
|
+
* @param method - How to handle existing quantities:
|
|
261
|
+
* - "keep": Keep all existing equivalents (swap if needed, or add converted)
|
|
262
|
+
* - "replace": Replace primary with target system quantity, discard equivalent used for conversion
|
|
263
|
+
* - "remove": Only keep target system quantity, delete all equivalents
|
|
264
|
+
* @returns A new Recipe instance with converted quantities
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* // Convert a recipe to metric, keeping original units as equivalents
|
|
269
|
+
* const metricRecipe = recipe.convertTo("metric", "keep");
|
|
270
|
+
*
|
|
271
|
+
* // Convert to US units, removing all other equivalents
|
|
272
|
+
* const usRecipe = recipe.convertTo("US", "remove");
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
convertTo(system: SpecificUnitSystem, method: "keep" | "replace" | "remove"): Recipe;
|
|
177
276
|
/**
|
|
178
277
|
* Gets the number of servings for the recipe.
|
|
179
278
|
* @private
|
|
@@ -187,6 +286,55 @@ declare class Recipe {
|
|
|
187
286
|
clone(): Recipe;
|
|
188
287
|
}
|
|
189
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Represents source attribution information for a recipe.
|
|
291
|
+
* @category Types
|
|
292
|
+
*/
|
|
293
|
+
interface MetadataSource {
|
|
294
|
+
/** The name of the source (e.g., "New York Times Cooking"). */
|
|
295
|
+
name?: string;
|
|
296
|
+
/** The URL of the source recipe. */
|
|
297
|
+
url?: string;
|
|
298
|
+
/** The author at the source. */
|
|
299
|
+
author?: string;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Represents a yield metadata value for a recipe.
|
|
303
|
+
* Supports plain quantities (e.g. `yield: 300%g`), complex format with
|
|
304
|
+
* surrounding text (e.g. `yield: about {{300%g}} of bread`), or simple
|
|
305
|
+
* numbers (e.g. `yield: 2`).
|
|
306
|
+
* @category Types
|
|
307
|
+
*/
|
|
308
|
+
interface Yield extends QuantityWithPlainUnit {
|
|
309
|
+
/** The text before the scaling variable (complex `{{}}` format). */
|
|
310
|
+
textBefore?: string;
|
|
311
|
+
/** The text after the scaling variable (complex `{{}}` format). */
|
|
312
|
+
textAfter?: string;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Represents time information for a recipe.
|
|
316
|
+
* @category Types
|
|
317
|
+
*/
|
|
318
|
+
interface MetadataTime {
|
|
319
|
+
/** The preparation time (not parsed into DateTime format). */
|
|
320
|
+
prep?: string;
|
|
321
|
+
/** The cooking time (not parsed into DateTime format). */
|
|
322
|
+
cook?: string;
|
|
323
|
+
/** The total time required (not parsed into DateTime format). */
|
|
324
|
+
total?: string;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Represents a nested metadata object with arbitrary keys.
|
|
328
|
+
* @category Types
|
|
329
|
+
*/
|
|
330
|
+
interface MetadataObject {
|
|
331
|
+
[key: string]: MetadataValue;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Represents any value that can appear in recipe metadata.
|
|
335
|
+
* @category Types
|
|
336
|
+
*/
|
|
337
|
+
type MetadataValue = string | number | (string | number)[] | MetadataObject | MetadataSource | MetadataTime | Yield | undefined;
|
|
190
338
|
/**
|
|
191
339
|
* Represents the metadata of a recipe.
|
|
192
340
|
* @category Types
|
|
@@ -196,56 +344,60 @@ interface Metadata {
|
|
|
196
344
|
title?: string;
|
|
197
345
|
/** The tags of the recipe. */
|
|
198
346
|
tags?: string[];
|
|
199
|
-
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
/** The source author of the recipe. */
|
|
206
|
-
"source.author"?: string;
|
|
207
|
-
/** The author of the recipe. */
|
|
347
|
+
/**
|
|
348
|
+
* The source of the recipe. Can be a simple URL string or structured attribution.
|
|
349
|
+
* When parsed from YAML, `source.name`, `source.url`, `source.author` keys are merged here.
|
|
350
|
+
*/
|
|
351
|
+
source?: string | MetadataSource;
|
|
352
|
+
/** The author of the recipe (separate from source author). */
|
|
208
353
|
author?: string;
|
|
209
354
|
/** The number of servings the recipe makes.
|
|
210
|
-
*
|
|
211
|
-
* (
|
|
212
|
-
* whatever you want.
|
|
355
|
+
* Stored as a number when the value is numeric, or as a string when non-numeric
|
|
356
|
+
* (e.g. `servings: two`). Non-numeric values default the internal scaling baseline to 1.
|
|
213
357
|
*
|
|
214
|
-
* Interchangeable with `yield` or `serves
|
|
215
|
-
*
|
|
216
|
-
* is `servings` \> `
|
|
358
|
+
* Interchangeable with `yield` or `serves` for the purpose of setting
|
|
359
|
+
* {@link Recipe.servings}. If multiple ones are defined, the prevalence
|
|
360
|
+
* order is `servings` \> `serves` \> `yield`.
|
|
217
361
|
*
|
|
218
362
|
* @example
|
|
219
363
|
* ```yaml
|
|
220
364
|
* servings: 4
|
|
221
365
|
* ```
|
|
366
|
+
*/
|
|
367
|
+
servings?: number | string;
|
|
368
|
+
/** The yield of the recipe.
|
|
369
|
+
* Can be given as:
|
|
370
|
+
* - a plain quantity with optional unit: `yield: 300%g` or `yield: 2`
|
|
371
|
+
* - a complex format with `{{}}` and optional surrounding text:
|
|
372
|
+
* `yield: about {{300%g}} of bread`
|
|
373
|
+
*
|
|
374
|
+
* Interchangeable with `servings` or `serves` for the purpose of setting
|
|
375
|
+
* {@link Recipe.servings}. If multiple ones are defined, the prevalence
|
|
376
|
+
* order is `servings` \> `serves` \> `yield`.
|
|
222
377
|
*
|
|
223
378
|
* @example
|
|
224
379
|
* ```yaml
|
|
225
|
-
*
|
|
380
|
+
* yield: 300%g
|
|
226
381
|
* ```
|
|
227
|
-
*/
|
|
228
|
-
servings?: number | string;
|
|
229
|
-
/** The yield of the recipe.
|
|
230
|
-
* Should be either a number or a string which starts with a number
|
|
231
|
-
* (which will be used for scaling) followed by a comma and then
|
|
232
|
-
* whatever you want.
|
|
233
382
|
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```yaml
|
|
385
|
+
* yield: about {{300%g}} of bread
|
|
386
|
+
* ```
|
|
238
387
|
*/
|
|
239
|
-
yield?:
|
|
388
|
+
yield?: Yield;
|
|
240
389
|
/** The number of people the recipe serves.
|
|
241
|
-
*
|
|
242
|
-
* (
|
|
243
|
-
*
|
|
390
|
+
* Stored as a number when the value is numeric, or as a string when non-numeric
|
|
391
|
+
* (e.g. `serves: two`). Non-numeric values default the internal scaling baseline to 1.
|
|
392
|
+
*
|
|
393
|
+
* Interchangeable with `servings` or `yield` for the purpose of setting
|
|
394
|
+
* {@link Recipe.servings}. If multiple ones are defined, the prevalence
|
|
395
|
+
* order is `servings` \> `serves` \> `yield`.
|
|
244
396
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```yaml
|
|
399
|
+
* serves: 4
|
|
400
|
+
* ```
|
|
249
401
|
*/
|
|
250
402
|
serves?: number | string;
|
|
251
403
|
/** The course of the recipe. */
|
|
@@ -255,30 +407,11 @@ interface Metadata {
|
|
|
255
407
|
/** The locale of the recipe. */
|
|
256
408
|
locale?: string;
|
|
257
409
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
|
|
261
|
-
"prep time"?: string;
|
|
262
|
-
/**
|
|
263
|
-
* Alias of `prep time`
|
|
264
|
-
*/
|
|
265
|
-
"time.prep"?: string;
|
|
266
|
-
/**
|
|
267
|
-
* The cooking time of the recipe.
|
|
268
|
-
* Will not be further parsed into any DateTime format nor normalize
|
|
269
|
-
*/
|
|
270
|
-
"cook time"?: string;
|
|
271
|
-
/**
|
|
272
|
-
* Alias of `cook time`
|
|
410
|
+
* Time information for the recipe.
|
|
411
|
+
* When parsed from YAML, `prep time`, `time.prep`, `cook time`, `time.cook`,
|
|
412
|
+
* `time required`, `time`, `duration` keys are merged here.
|
|
273
413
|
*/
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* The total time of the recipe.
|
|
277
|
-
* Will not be further parsed into any DateTime format nor normalize
|
|
278
|
-
*/
|
|
279
|
-
"time required"?: string;
|
|
280
|
-
time?: string;
|
|
281
|
-
duration?: string;
|
|
414
|
+
time?: MetadataTime;
|
|
282
415
|
/** The difficulty of the recipe. */
|
|
283
416
|
difficulty?: string;
|
|
284
417
|
/** The cuisine of the recipe. */
|
|
@@ -287,16 +420,25 @@ interface Metadata {
|
|
|
287
420
|
diet?: string;
|
|
288
421
|
/** The description of the recipe. */
|
|
289
422
|
description?: string;
|
|
290
|
-
/** The images of the recipe.
|
|
423
|
+
/** The images of the recipe. */
|
|
291
424
|
images?: string[];
|
|
292
|
-
/** The
|
|
293
|
-
pictures?: string[];
|
|
294
|
-
/** The picture of the recipe. Alias of `picture` */
|
|
425
|
+
/** The primary image of the recipe. */
|
|
295
426
|
image?: string;
|
|
296
|
-
/** The picture of the recipe. Alias of `image` */
|
|
297
|
-
picture?: string;
|
|
298
427
|
/** The introduction of the recipe. */
|
|
299
428
|
introduction?: string;
|
|
429
|
+
/**
|
|
430
|
+
* The unit system used in the recipe for ambiguous units like tsp, tbsp, cup.
|
|
431
|
+
* See [Unit Conversion Guide](/guide-unit-conversion) for more information.
|
|
432
|
+
* This stores the original value as written by the user.
|
|
433
|
+
*/
|
|
434
|
+
unitSystem?: string;
|
|
435
|
+
/** The list of available variant names for this recipe. */
|
|
436
|
+
variants?: string[];
|
|
437
|
+
/**
|
|
438
|
+
* Index signature for additional metadata fields not explicitly typed.
|
|
439
|
+
* Any metadata key in the frontmatter will be captured here.
|
|
440
|
+
*/
|
|
441
|
+
[key: string]: MetadataValue;
|
|
300
442
|
}
|
|
301
443
|
/**
|
|
302
444
|
* Represents a quantity described by text, e.g. "a pinch"
|
|
@@ -367,7 +509,7 @@ interface IngredientExtras {
|
|
|
367
509
|
* Used if: the ingredient is a recipe
|
|
368
510
|
*
|
|
369
511
|
* @example
|
|
370
|
-
* ```
|
|
512
|
+
* ```yaml
|
|
371
513
|
* Take @./essentials/doughs/pizza dough{1} out of the freezer and let it unfreeze overnight
|
|
372
514
|
* ```
|
|
373
515
|
* Would lead to:
|
|
@@ -399,30 +541,31 @@ interface AlternativeIngredientRef {
|
|
|
399
541
|
interface IngredientQuantityGroup extends QuantityWithPlainUnit {
|
|
400
542
|
/**
|
|
401
543
|
* References to alternative ingredients for this quantity group.
|
|
544
|
+
* Each inner array represents one alternative choice option (subgroup).
|
|
545
|
+
* Items within the same inner array are combined with "+" (AND),
|
|
546
|
+
* while different inner arrays represent "or" alternatives.
|
|
402
547
|
* If undefined, this group has no alternatives.
|
|
403
548
|
*/
|
|
404
|
-
alternatives?: AlternativeIngredientRef[];
|
|
549
|
+
alternatives?: AlternativeIngredientRef[][];
|
|
405
550
|
}
|
|
406
551
|
/**
|
|
407
552
|
* Represents an AND group of quantities when primary units are incompatible but equivalents can be summed.
|
|
408
|
-
* For example: 1 large carrot + 2 small carrots, both with cup equivalents that sum to 5 cups.
|
|
553
|
+
* For example: 1 large carrot + 2 small carrots, both with cup equivalents (resp. 2 cup and 1.5 cup) that sum to 5 cups.
|
|
409
554
|
* @category Types
|
|
410
555
|
*/
|
|
411
|
-
interface IngredientQuantityAndGroup {
|
|
412
|
-
type: "and";
|
|
413
|
-
/**
|
|
414
|
-
* The incompatible primary quantities (e.g., "1 large" and "2 small").
|
|
415
|
-
*/
|
|
416
|
-
entries: QuantityWithPlainUnit[];
|
|
556
|
+
interface IngredientQuantityAndGroup extends FlatAndGroup<QuantityWithPlainUnit> {
|
|
417
557
|
/**
|
|
418
558
|
* The summed equivalent quantities (e.g., "5 cups" from summing "1.5 cup + 2 cup + 1.5 cup").
|
|
419
559
|
*/
|
|
420
560
|
equivalents?: QuantityWithPlainUnit[];
|
|
421
561
|
/**
|
|
422
562
|
* References to alternative ingredients for this quantity group.
|
|
563
|
+
* Each inner array represents one alternative choice option (subgroup).
|
|
564
|
+
* Items within the same inner array are combined with "+" (AND),
|
|
565
|
+
* while different inner arrays represent "or" alternatives.
|
|
423
566
|
* If undefined, this group has no alternatives.
|
|
424
567
|
*/
|
|
425
|
-
alternatives?: AlternativeIngredientRef[];
|
|
568
|
+
alternatives?: AlternativeIngredientRef[][];
|
|
426
569
|
}
|
|
427
570
|
/**
|
|
428
571
|
* Represents an ingredient in a recipe.
|
|
@@ -458,49 +601,40 @@ interface Ingredient {
|
|
|
458
601
|
extras?: IngredientExtras;
|
|
459
602
|
}
|
|
460
603
|
/**
|
|
461
|
-
* Represents a
|
|
462
|
-
*
|
|
604
|
+
* Represents a quantity with extended unit and additional information
|
|
605
|
+
* about its scalability and potential equivalents
|
|
606
|
+
*
|
|
463
607
|
* @category Types
|
|
464
608
|
*/
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
/** The list of ingredients mentioned in the preparation as alternatives to this ingredient */
|
|
473
|
-
alternatives?: Set<number>;
|
|
474
|
-
/** A list of potential state modifiers or other flags for the ingredient */
|
|
475
|
-
flags?: IngredientFlag[];
|
|
476
|
-
/** The collection of potential additional metadata for the ingredient */
|
|
477
|
-
extras?: IngredientExtras;
|
|
478
|
-
}
|
|
609
|
+
type MaybeScalableQuantity = QuantityWithExtendedUnit & {
|
|
610
|
+
/** Indicates whether this quantity should be scaled when the recipe serving size changes. */
|
|
611
|
+
scalable: boolean;
|
|
612
|
+
/** A list of equivalent quantities/units for this ingredient mention besides the primary quantity.
|
|
613
|
+
* For `@salt{1%tsp|5%g}`, the main quantity is 1 tsp and the equivalents will contain 5 g. */
|
|
614
|
+
equivalents?: QuantityWithExtendedUnit[];
|
|
615
|
+
};
|
|
479
616
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
617
|
+
* Defines a type containing an optional {@link QuantityWithExtendedUnit} with scalability and potential info about equivalents
|
|
618
|
+
*
|
|
619
|
+
* Used in {@link IngredientAlternative}
|
|
620
|
+
*
|
|
621
|
+
* @param T - The base type to which the optional quantity properties will be added.
|
|
622
|
+
*
|
|
483
623
|
* @category Types
|
|
484
624
|
*/
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
/** Indicates whether this quantity should be scaled when the recipe serving size changes. */
|
|
492
|
-
scalable: boolean;
|
|
493
|
-
}
|
|
625
|
+
type WithOptionalQuantity<T> = (T & MaybeScalableQuantity) | (T & {
|
|
626
|
+
quantity?: undefined;
|
|
627
|
+
scalable?: never;
|
|
628
|
+
unit?: never;
|
|
629
|
+
equivalents?: never;
|
|
630
|
+
});
|
|
494
631
|
/**
|
|
495
|
-
*
|
|
496
|
-
* to a specific ingredient and its corresponding quantity information.
|
|
632
|
+
* Base type of {@link IngredientAlternative}
|
|
497
633
|
* @category Types
|
|
498
634
|
*/
|
|
499
|
-
|
|
635
|
+
type IngredientAlternativeBase = {
|
|
500
636
|
/** The index of the ingredient within the {@link Recipe.ingredients} array. */
|
|
501
637
|
index: number;
|
|
502
|
-
/** The quantity of this specific mention of the ingredient */
|
|
503
|
-
itemQuantity?: IngredientItemQuantity;
|
|
504
638
|
/** The alias/name of the ingredient as it should be displayed for this occurrence. */
|
|
505
639
|
displayName: string;
|
|
506
640
|
/** An optional note for this specific choice (e.g., "for a vegan version"). */
|
|
@@ -509,7 +643,16 @@ interface IngredientAlternative {
|
|
|
509
643
|
* with group keys: the id of the corresponding ingredient item (e.g. "ingredient-item-2").
|
|
510
644
|
* Can be useful for creating alternative selection UI elements with anchor links */
|
|
511
645
|
itemId?: string;
|
|
512
|
-
}
|
|
646
|
+
};
|
|
647
|
+
/**
|
|
648
|
+
* Represents a single ingredient choice within a single or a group of `IngredientItem`s. It points
|
|
649
|
+
* to a specific ingredient and its corresponding quantity information.
|
|
650
|
+
*
|
|
651
|
+
* Used in {@link IngredientItem} and for the various maps of {@link RecipeAlternatives}
|
|
652
|
+
*
|
|
653
|
+
* @category Types
|
|
654
|
+
*/
|
|
655
|
+
type IngredientAlternative = WithOptionalQuantity<IngredientAlternativeBase>;
|
|
513
656
|
/**
|
|
514
657
|
* Represents an ingredient item in a recipe step.
|
|
515
658
|
* @category Types
|
|
@@ -530,6 +673,12 @@ interface IngredientItem {
|
|
|
530
673
|
* `@|group|...` syntax), they represent a single logical choice.
|
|
531
674
|
*/
|
|
532
675
|
group?: string;
|
|
676
|
+
/**
|
|
677
|
+
* An optional subgroup identifier for binding multiple ingredients together
|
|
678
|
+
* within a group. Ingredients sharing the same `group` and `subgroup` are
|
|
679
|
+
* selected together as a unit (e.g., from `@|group/1|...` syntax).
|
|
680
|
+
*/
|
|
681
|
+
subgroup?: string;
|
|
533
682
|
}
|
|
534
683
|
/**
|
|
535
684
|
* Represents the choices one can make in a recipe
|
|
@@ -543,9 +692,18 @@ interface RecipeAlternatives {
|
|
|
543
692
|
ingredientItems: Map<string, IngredientAlternative[]>;
|
|
544
693
|
/** Map of choices that can be made for Grouped Ingredient StepItem's
|
|
545
694
|
* - Keys are the Group IDs (e.g. "eggs" for `@|eggs|...`)
|
|
546
|
-
* - Values are arrays of
|
|
695
|
+
* - Values are arrays of subgroups, where each subgroup is an array of
|
|
696
|
+
* bound IngredientAlternative objects that are selected together.
|
|
697
|
+
* Items sharing the same subgroup key (e.g., `@|group/1|...`) are
|
|
698
|
+
* in the same inner array. Items without a subgroup key each form
|
|
699
|
+
* their own single-element subgroup.
|
|
700
|
+
*/
|
|
701
|
+
ingredientGroups: Map<string, IngredientAlternative[][]>;
|
|
702
|
+
/**
|
|
703
|
+
* All variant names discovered in the recipe (from metadata, step tags,
|
|
704
|
+
* and section tags). Includes `*` if any step/section uses the default tag.
|
|
547
705
|
*/
|
|
548
|
-
|
|
706
|
+
variants: string[];
|
|
549
707
|
}
|
|
550
708
|
/**
|
|
551
709
|
* Represents the choices to apply when computing ingredient quantities.
|
|
@@ -557,6 +715,46 @@ interface RecipeChoices {
|
|
|
557
715
|
ingredientItems?: Map<string, number>;
|
|
558
716
|
/** Map of choices that can be made for Grouped Ingredient StepItem's */
|
|
559
717
|
ingredientGroups?: Map<string, number>;
|
|
718
|
+
/** The selected variant name */
|
|
719
|
+
variant?: string;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Options for the {@link Recipe.getIngredientQuantities | getIngredientQuantities()} method.
|
|
723
|
+
* @category Types
|
|
724
|
+
*/
|
|
725
|
+
interface GetIngredientQuantitiesOptions {
|
|
726
|
+
/**
|
|
727
|
+
* Filter ingredients to only those appearing in a specific section.
|
|
728
|
+
* Can be a Section object or section index (0-based).
|
|
729
|
+
*/
|
|
730
|
+
section?: Section | number;
|
|
731
|
+
/**
|
|
732
|
+
* Filter ingredients to only those appearing in a specific step.
|
|
733
|
+
* Can be a Step object or step index (0-based within the section, or global if no section specified).
|
|
734
|
+
*/
|
|
735
|
+
step?: Step | number;
|
|
736
|
+
/**
|
|
737
|
+
* The choices to apply when computing quantities.
|
|
738
|
+
* If not provided, uses primary alternatives (index 0 for all).
|
|
739
|
+
*/
|
|
740
|
+
choices?: RecipeChoices;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Represents a raw (unprocessed) group of quantities for a single ingredient.
|
|
744
|
+
* Returned by {@link Recipe.getRawQuantityGroups},
|
|
745
|
+
* these are the pre-addition quantities that are fed internally
|
|
746
|
+
* to another non-public helper function for cross-recipe aggregation.
|
|
747
|
+
* @category Types
|
|
748
|
+
*/
|
|
749
|
+
interface RawQuantityGroup {
|
|
750
|
+
/** The name of the ingredient. */
|
|
751
|
+
name: string;
|
|
752
|
+
/** Whether this ingredient is used as a primary choice. */
|
|
753
|
+
usedAsPrimary?: boolean;
|
|
754
|
+
/** Flags on the ingredient (e.g., "hidden", "optional"). */
|
|
755
|
+
flags?: IngredientFlag[];
|
|
756
|
+
/** The raw, unprocessed quantities for this ingredient across all its mentions. */
|
|
757
|
+
quantities: (QuantityWithExtendedUnit | FlatOrGroup<QuantityWithExtendedUnit>)[];
|
|
560
758
|
}
|
|
561
759
|
/**
|
|
562
760
|
* Represents a cookware item in a recipe step.
|
|
@@ -592,6 +790,11 @@ interface Timer {
|
|
|
592
790
|
/** The unit of the timer. */
|
|
593
791
|
unit: string;
|
|
594
792
|
}
|
|
793
|
+
/**
|
|
794
|
+
* Represents a formatting attribute for a {@link TextItem}.
|
|
795
|
+
* @category Types
|
|
796
|
+
*/
|
|
797
|
+
type TextAttribute = "bold" | "italic" | "bold+italic" | "link" | "code";
|
|
595
798
|
/**
|
|
596
799
|
* Represents a text item in a recipe step.
|
|
597
800
|
* @category Types
|
|
@@ -601,6 +804,10 @@ interface TextItem {
|
|
|
601
804
|
type: "text";
|
|
602
805
|
/** The content of the text item. */
|
|
603
806
|
value: string;
|
|
807
|
+
/** The formatting attribute of the text item, if any. */
|
|
808
|
+
attribute?: TextAttribute;
|
|
809
|
+
/** The URL target, only present when attribute is "link". */
|
|
810
|
+
href?: string;
|
|
604
811
|
}
|
|
605
812
|
/**
|
|
606
813
|
* Represents an arbitrary scalable quantity in a recipe.
|
|
@@ -637,6 +844,10 @@ interface Step {
|
|
|
637
844
|
type: "step";
|
|
638
845
|
/** The items in the step. */
|
|
639
846
|
items: StepItem[];
|
|
847
|
+
/** Optional list of variant names this step belongs to */
|
|
848
|
+
variants?: string[];
|
|
849
|
+
/** Whether the step has been marked as optional ("[?]") */
|
|
850
|
+
optional?: boolean;
|
|
640
851
|
}
|
|
641
852
|
/**
|
|
642
853
|
* Represents an item in a note (can be text or arbitrary scalable).
|
|
@@ -707,6 +918,9 @@ interface RecipeWithServings {
|
|
|
707
918
|
type AddedRecipe = RecipeWithFactor | RecipeWithServings;
|
|
708
919
|
/**
|
|
709
920
|
* Options for adding a recipe to a shopping list
|
|
921
|
+
*
|
|
922
|
+
* Used in {@link ShoppingList.addRecipe}
|
|
923
|
+
*
|
|
710
924
|
* @category Types
|
|
711
925
|
*/
|
|
712
926
|
type AddedRecipeOptions = {
|
|
@@ -723,7 +937,7 @@ type AddedRecipeOptions = {
|
|
|
723
937
|
* Represents an ingredient that has been added to a shopping list
|
|
724
938
|
* @category Types
|
|
725
939
|
*/
|
|
726
|
-
type AddedIngredient = Pick<
|
|
940
|
+
type AddedIngredient = Pick<Ingredient, "name" | "quantities">;
|
|
727
941
|
/**
|
|
728
942
|
* Represents an ingredient in a category.
|
|
729
943
|
* @category Types
|
|
@@ -783,6 +997,48 @@ type ProductOption = ProductOptionBase & {
|
|
|
783
997
|
/** The size(s) of the product. Multiple sizes allow equivalent expressions (e.g., "1%dozen" and "12") */
|
|
784
998
|
sizes: ProductSize[];
|
|
785
999
|
};
|
|
1000
|
+
/**
|
|
1001
|
+
* Represents a pantry item entry in the TOML file.
|
|
1002
|
+
* Can be a simple quantity string (e.g. `"500%g"`) or an object with details.
|
|
1003
|
+
* @category Types
|
|
1004
|
+
*/
|
|
1005
|
+
type PantryItemToml = string | {
|
|
1006
|
+
quantity?: string;
|
|
1007
|
+
bought?: string;
|
|
1008
|
+
expire?: string;
|
|
1009
|
+
low?: string;
|
|
1010
|
+
};
|
|
1011
|
+
/**
|
|
1012
|
+
* Represents a parsed pantry item.
|
|
1013
|
+
* @category Types
|
|
1014
|
+
*/
|
|
1015
|
+
interface PantryItem {
|
|
1016
|
+
/** The name of the item. */
|
|
1017
|
+
name: string;
|
|
1018
|
+
/** The storage location (TOML section name, e.g. "freezer", "fridge"). */
|
|
1019
|
+
location: string;
|
|
1020
|
+
/** The quantity value of the item. */
|
|
1021
|
+
quantity?: FixedValue | Range;
|
|
1022
|
+
/** The unit of the item's quantity. */
|
|
1023
|
+
unit?: string;
|
|
1024
|
+
/** The date when the item was purchased. */
|
|
1025
|
+
bought?: Date;
|
|
1026
|
+
/** The expiration date of the item. */
|
|
1027
|
+
expire?: Date;
|
|
1028
|
+
/** The low stock threshold value. */
|
|
1029
|
+
low?: FixedValue | Range;
|
|
1030
|
+
/** The unit of the low stock threshold. */
|
|
1031
|
+
lowUnit?: string;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Options for configuring a {@link Pantry}.
|
|
1035
|
+
* @category Types
|
|
1036
|
+
*/
|
|
1037
|
+
interface PantryOptions {
|
|
1038
|
+
/** Date format pattern for parsing date strings (e.g. `"DD.MM.YYYY"`, `"MM/DD/YYYY"`, `"YYYY-MM-DD"`).
|
|
1039
|
+
* If not provided, dates are parsed with fuzzy detection defaulting to day-first when ambiguous. */
|
|
1040
|
+
dateFormat?: string;
|
|
1041
|
+
}
|
|
786
1042
|
/**
|
|
787
1043
|
* Represents a product selection in a {@link ShoppingCart}
|
|
788
1044
|
* @category Types
|
|
@@ -835,12 +1091,23 @@ type CartMisMatch = ProductMisMatch[];
|
|
|
835
1091
|
* Represents the type category of a unit used for quantities
|
|
836
1092
|
* @category Types
|
|
837
1093
|
*/
|
|
838
|
-
type UnitType = "mass" | "volume" | "count";
|
|
1094
|
+
type UnitType = "mass" | "volume" | "count" | "other";
|
|
1095
|
+
/**
|
|
1096
|
+
* Represents the specific measurement systems
|
|
1097
|
+
* @category Types
|
|
1098
|
+
*/
|
|
1099
|
+
type SpecificUnitSystem = "metric" | "US" | "UK" | "JP";
|
|
839
1100
|
/**
|
|
840
1101
|
* Represents the measurement system a unit belongs to
|
|
841
1102
|
* @category Types
|
|
842
1103
|
*/
|
|
843
|
-
type UnitSystem =
|
|
1104
|
+
type UnitSystem = SpecificUnitSystem | "ambiguous";
|
|
1105
|
+
/**
|
|
1106
|
+
* Conversion factors for ambiguous units that can belong to multiple systems.
|
|
1107
|
+
* Maps each possible system to its toBase conversion factor.
|
|
1108
|
+
* @category Types
|
|
1109
|
+
*/
|
|
1110
|
+
type ToBaseBySystem = Partial<Record<SpecificUnitSystem, number>>;
|
|
844
1111
|
/**
|
|
845
1112
|
* Represents a unit used to describe quantities
|
|
846
1113
|
* @category Types
|
|
@@ -860,8 +1127,28 @@ interface UnitDefinition extends Unit {
|
|
|
860
1127
|
system: UnitSystem;
|
|
861
1128
|
/** e.g. ['gram', 'grams'] */
|
|
862
1129
|
aliases: string[];
|
|
863
|
-
/** Conversion factor to the base unit of its type */
|
|
1130
|
+
/** Conversion factor to the base unit of its type (uses default system for ambiguous units) */
|
|
864
1131
|
toBase: number;
|
|
1132
|
+
/** For ambiguous units: conversion factors for each possible system */
|
|
1133
|
+
toBaseBySystem?: ToBaseBySystem;
|
|
1134
|
+
/** Whether this unit is a candidate for "best unit" selection (default: true) */
|
|
1135
|
+
isBestUnit?: boolean;
|
|
1136
|
+
/** Maximum value before upgrading to a larger unit (default: 999) */
|
|
1137
|
+
maxValue?: number;
|
|
1138
|
+
/** Fraction display configuration */
|
|
1139
|
+
fractions?: UnitFractionConfig;
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Configuration for fraction display on a unit
|
|
1143
|
+
* @category Types
|
|
1144
|
+
*/
|
|
1145
|
+
interface UnitFractionConfig {
|
|
1146
|
+
/** Whether to approximate decimals as fractions for this unit */
|
|
1147
|
+
enabled: boolean;
|
|
1148
|
+
/** Allowed denominators (default: [2, 3, 4, 8]) */
|
|
1149
|
+
denominators?: number[];
|
|
1150
|
+
/** Maximum whole number in mixed fraction before falling back to decimal (default: 4) */
|
|
1151
|
+
maxWhole?: number;
|
|
865
1152
|
}
|
|
866
1153
|
/**
|
|
867
1154
|
* Represents a resolved unit definition or a lightweight placeholder for non-standard units
|
|
@@ -908,27 +1195,59 @@ interface QuantityWithUnitDef extends QuantityBase {
|
|
|
908
1195
|
* @category Types
|
|
909
1196
|
*/
|
|
910
1197
|
type QuantityWithUnitLike = QuantityWithPlainUnit | QuantityWithExtendedUnit | QuantityWithUnitDef;
|
|
1198
|
+
/**
|
|
1199
|
+
* Represents a flat "or" group of alternative quantities (for alternative units)
|
|
1200
|
+
* @category Types
|
|
1201
|
+
*/
|
|
1202
|
+
interface FlatOrGroup<T = QuantityWithUnitLike> {
|
|
1203
|
+
or: T[];
|
|
1204
|
+
}
|
|
911
1205
|
/**
|
|
912
1206
|
* Represents an "or" group of alternative quantities that may contain nested groups (alternatives with nested structure)
|
|
913
1207
|
* @category Types
|
|
914
1208
|
*/
|
|
915
1209
|
interface MaybeNestedOrGroup<T = QuantityWithUnitLike> {
|
|
916
|
-
|
|
917
|
-
|
|
1210
|
+
or: (T | MaybeNestedGroup<T>)[];
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Represents a flat "and" group of quantities (combined quantities)
|
|
1214
|
+
* @category Types
|
|
1215
|
+
*/
|
|
1216
|
+
interface FlatAndGroup<T = QuantityWithUnitLike> {
|
|
1217
|
+
and: T[];
|
|
918
1218
|
}
|
|
919
1219
|
/**
|
|
920
1220
|
* Represents an "and" group of quantities that may contain nested groups (combinations with nested structure)
|
|
921
1221
|
* @category Types
|
|
922
1222
|
*/
|
|
923
1223
|
interface MaybeNestedAndGroup<T = QuantityWithUnitLike> {
|
|
924
|
-
|
|
925
|
-
entries: (T | MaybeNestedGroup<T>)[];
|
|
1224
|
+
and: (T | MaybeNestedGroup<T>)[];
|
|
926
1225
|
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Represents any flat group type ("and" or "or")
|
|
1228
|
+
* @category Types
|
|
1229
|
+
*/
|
|
1230
|
+
type FlatGroup<T = QuantityWithUnitLike> = FlatAndGroup<T> | FlatOrGroup<T>;
|
|
927
1231
|
/**
|
|
928
1232
|
* Represents any group type that may include nested groups
|
|
929
1233
|
* @category Types
|
|
930
1234
|
*/
|
|
931
1235
|
type MaybeNestedGroup<T = QuantityWithUnitLike> = MaybeNestedAndGroup<T> | MaybeNestedOrGroup<T>;
|
|
1236
|
+
/**
|
|
1237
|
+
* Represents any group type (flat or nested)
|
|
1238
|
+
* @category Types
|
|
1239
|
+
*/
|
|
1240
|
+
type Group<T = QuantityWithUnitLike> = MaybeNestedGroup<T> | FlatGroup<T>;
|
|
1241
|
+
/**
|
|
1242
|
+
* Represents any "or" group (flat or nested)
|
|
1243
|
+
* @category Types
|
|
1244
|
+
*/
|
|
1245
|
+
type OrGroup<T = QuantityWithUnitLike> = MaybeNestedOrGroup<T> | FlatOrGroup<T>;
|
|
1246
|
+
/**
|
|
1247
|
+
* Represents any "and" group (flat or nested)
|
|
1248
|
+
* @category Types
|
|
1249
|
+
*/
|
|
1250
|
+
type AndGroup<T = QuantityWithUnitLike> = MaybeNestedAndGroup<T> | FlatAndGroup<T>;
|
|
932
1251
|
|
|
933
1252
|
/**
|
|
934
1253
|
* Parser for category configurations specified à-la-cooklang.
|
|
@@ -979,6 +1298,127 @@ declare class CategoryConfig {
|
|
|
979
1298
|
parse(config: string): void;
|
|
980
1299
|
}
|
|
981
1300
|
|
|
1301
|
+
/**
|
|
1302
|
+
* Pantry Inventory Manager: parses and queries a pantry inventory file.
|
|
1303
|
+
*
|
|
1304
|
+
* ## Usage
|
|
1305
|
+
*
|
|
1306
|
+
* Create a new Pantry instance with optional TOML content and options
|
|
1307
|
+
* (see {@link Pantry."constructor" | constructor}), then query items
|
|
1308
|
+
* using {@link Pantry.getDepletedItems | getDepletedItems()},
|
|
1309
|
+
* {@link Pantry.getExpiredItems | getExpiredItems()},
|
|
1310
|
+
* {@link Pantry.isLow | isLow()}, or {@link Pantry.isExpired | isExpired()}.
|
|
1311
|
+
*
|
|
1312
|
+
* A Pantry can also be attached to a {@link ShoppingList} via
|
|
1313
|
+
* {@link ShoppingList.addPantry | addPantry()} so that on-hand stock
|
|
1314
|
+
* is subtracted from recipe ingredient needs.
|
|
1315
|
+
*
|
|
1316
|
+
* @example
|
|
1317
|
+
* ```typescript
|
|
1318
|
+
* import { Pantry } from "@tmlmt/cooklang-parser";
|
|
1319
|
+
*
|
|
1320
|
+
* const pantryToml = `
|
|
1321
|
+
* [fridge]
|
|
1322
|
+
* milk = { expire = "10.05.2024", quantity = "1%L" }
|
|
1323
|
+
*
|
|
1324
|
+
* [freezer]
|
|
1325
|
+
* spinach = { quantity = "1%kg", low = "200%g" }
|
|
1326
|
+
* `;
|
|
1327
|
+
*
|
|
1328
|
+
* const pantry = new Pantry(pantryToml);
|
|
1329
|
+
* console.log(pantry.getExpiredItems());
|
|
1330
|
+
* console.log(pantry.isLow("spinach"));
|
|
1331
|
+
* ```
|
|
1332
|
+
*
|
|
1333
|
+
* @see [Pantry Configuration](https://cooklang.org/docs/spec/#pantry-configuration) section of the cooklang specs
|
|
1334
|
+
*
|
|
1335
|
+
* @category Classes
|
|
1336
|
+
*/
|
|
1337
|
+
declare class Pantry {
|
|
1338
|
+
/**
|
|
1339
|
+
* The parsed pantry items.
|
|
1340
|
+
*/
|
|
1341
|
+
items: PantryItem[];
|
|
1342
|
+
/**
|
|
1343
|
+
* Options for date parsing and other configuration.
|
|
1344
|
+
*/
|
|
1345
|
+
private options;
|
|
1346
|
+
/**
|
|
1347
|
+
* Optional category configuration for alias-based lookups.
|
|
1348
|
+
*/
|
|
1349
|
+
private categoryConfig?;
|
|
1350
|
+
/**
|
|
1351
|
+
* Creates a new Pantry instance.
|
|
1352
|
+
* @param tomlContent - Optional TOML content to parse.
|
|
1353
|
+
* @param options - Optional configuration options.
|
|
1354
|
+
*/
|
|
1355
|
+
constructor(tomlContent?: string, options?: PantryOptions);
|
|
1356
|
+
/**
|
|
1357
|
+
* Parses a TOML string into pantry items.
|
|
1358
|
+
* @param tomlContent - The TOML string to parse.
|
|
1359
|
+
* @returns The parsed list of pantry items.
|
|
1360
|
+
*/
|
|
1361
|
+
parse(tomlContent: string): PantryItem[];
|
|
1362
|
+
/**
|
|
1363
|
+
* Parses a single pantry item from its TOML representation.
|
|
1364
|
+
*/
|
|
1365
|
+
private parseItem;
|
|
1366
|
+
/**
|
|
1367
|
+
* Parses a date string using the configured format or fuzzy detection.
|
|
1368
|
+
*/
|
|
1369
|
+
private parseDate;
|
|
1370
|
+
/**
|
|
1371
|
+
* Sets a category configuration for alias-based item lookups.
|
|
1372
|
+
* @param config - The category configuration to use.
|
|
1373
|
+
*/
|
|
1374
|
+
setCategoryConfig(config: CategoryConfig): void;
|
|
1375
|
+
/**
|
|
1376
|
+
* Finds a pantry item by name, using exact match first, then alias lookup
|
|
1377
|
+
* via the stored CategoryConfig.
|
|
1378
|
+
* @param name - The name to search for.
|
|
1379
|
+
* @returns The matching pantry item, or undefined if not found.
|
|
1380
|
+
*/
|
|
1381
|
+
findItem(name: string): PantryItem | undefined;
|
|
1382
|
+
/**
|
|
1383
|
+
* Gets the numeric value of a pantry item's quantity, optionally converted to base units.
|
|
1384
|
+
* Returns undefined if the quantity has a text value or is not set.
|
|
1385
|
+
*/
|
|
1386
|
+
private getItemNumericValue;
|
|
1387
|
+
/**
|
|
1388
|
+
* Returns all items that are depleted (quantity = 0) or below their low threshold.
|
|
1389
|
+
* @returns An array of depleted pantry items.
|
|
1390
|
+
*/
|
|
1391
|
+
getDepletedItems(): PantryItem[];
|
|
1392
|
+
/**
|
|
1393
|
+
* Returns all items whose expiration date is within `nbDays` days from today
|
|
1394
|
+
* (or already passed).
|
|
1395
|
+
* @param nbDays - Number of days ahead to check. Defaults to 0 (already expired).
|
|
1396
|
+
* @returns An array of expired pantry items.
|
|
1397
|
+
*/
|
|
1398
|
+
getExpiredItems(nbDays?: number): PantryItem[];
|
|
1399
|
+
/**
|
|
1400
|
+
* Checks if a specific item is low (quantity = 0 or below `low` threshold).
|
|
1401
|
+
* @param itemName - The name of the item to check (supports aliases if CategoryConfig is set).
|
|
1402
|
+
* @returns true if the item is low, false otherwise. Returns false if item not found.
|
|
1403
|
+
*/
|
|
1404
|
+
isLow(itemName: string): boolean;
|
|
1405
|
+
/**
|
|
1406
|
+
* Checks if a specific item is expired or expires within `nbDays` days.
|
|
1407
|
+
* @param itemName - The name of the item to check (supports aliases if CategoryConfig is set).
|
|
1408
|
+
* @param nbDays - Number of days ahead to check. Defaults to 0.
|
|
1409
|
+
* @returns true if the item is expired, false otherwise. Returns false if item not found.
|
|
1410
|
+
*/
|
|
1411
|
+
isExpired(itemName: string, nbDays?: number): boolean;
|
|
1412
|
+
/**
|
|
1413
|
+
* Internal: checks if a pantry item is low.
|
|
1414
|
+
*/
|
|
1415
|
+
private isItemLow;
|
|
1416
|
+
/**
|
|
1417
|
+
* Internal: checks if a pantry item is expired.
|
|
1418
|
+
*/
|
|
1419
|
+
private isItemExpired;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
982
1422
|
/**
|
|
983
1423
|
* Product Catalog Manager: used in conjunction with {@link ShoppingCart}
|
|
984
1424
|
*
|
|
@@ -1005,7 +1445,7 @@ declare class CategoryConfig {
|
|
|
1005
1445
|
* 14141 = { name = "Big pack", size = "6%kg", price = 10 }
|
|
1006
1446
|
* `
|
|
1007
1447
|
* const catalog = new ProductCatalog(catalog);
|
|
1008
|
-
* const eggs = catalog.find("
|
|
1448
|
+
* const eggs = catalog.products.find(p => p.ingredientName === "eggs");
|
|
1009
1449
|
* ```
|
|
1010
1450
|
*/
|
|
1011
1451
|
declare class ProductCatalog {
|
|
@@ -1041,7 +1481,7 @@ declare class ProductCatalog {
|
|
|
1041
1481
|
* ## Usage
|
|
1042
1482
|
*
|
|
1043
1483
|
* - Create a new ShoppingList instance with an optional category configuration (see {@link ShoppingList."constructor" | constructor})
|
|
1044
|
-
* - Add recipes, scaling them as needed (see {@link ShoppingList.
|
|
1484
|
+
* - Add recipes, scaling them as needed (see {@link ShoppingList.addRecipe | addRecipe()})
|
|
1045
1485
|
* - Categorize the ingredients (see {@link ShoppingList.categorize | categorize()})
|
|
1046
1486
|
*
|
|
1047
1487
|
* @example
|
|
@@ -1053,10 +1493,10 @@ declare class ProductCatalog {
|
|
|
1053
1493
|
* const categoryConfig = fs.readFileSync("./myconfig.txt", "utf-8")
|
|
1054
1494
|
* const recipe1 = new Recipe(fs.readFileSync("./myrecipe.cook", "utf-8"));
|
|
1055
1495
|
* const shoppingList = new ShoppingList();
|
|
1056
|
-
* shoppingList.
|
|
1496
|
+
* shoppingList.setCategoryConfig(categoryConfig);
|
|
1057
1497
|
* // Quantities are automatically calculated and ingredients categorized
|
|
1058
1498
|
* // when adding a recipe
|
|
1059
|
-
* shoppingList.
|
|
1499
|
+
* shoppingList.addRecipe(recipe1);
|
|
1060
1500
|
* ```
|
|
1061
1501
|
*
|
|
1062
1502
|
* @category Classes
|
|
@@ -1073,36 +1513,84 @@ declare class ShoppingList {
|
|
|
1073
1513
|
/**
|
|
1074
1514
|
* The category configuration for the shopping list.
|
|
1075
1515
|
*/
|
|
1076
|
-
|
|
1516
|
+
categoryConfig?: CategoryConfig;
|
|
1077
1517
|
/**
|
|
1078
1518
|
* The categorized ingredients in the shopping list.
|
|
1079
1519
|
*/
|
|
1080
1520
|
categories?: CategorizedIngredients;
|
|
1521
|
+
/**
|
|
1522
|
+
* The unit system to use for quantity simplification.
|
|
1523
|
+
* When set, overrides per-recipe unit systems.
|
|
1524
|
+
*/
|
|
1525
|
+
unitSystem?: SpecificUnitSystem;
|
|
1526
|
+
/**
|
|
1527
|
+
* Per-ingredient equivalence ratio maps for recomputing equivalents
|
|
1528
|
+
* after pantry subtraction. Keyed by ingredient name.
|
|
1529
|
+
* @internal
|
|
1530
|
+
*/
|
|
1531
|
+
private equivalenceRatios;
|
|
1532
|
+
/**
|
|
1533
|
+
* The original pantry (never mutated by recipe calculations).
|
|
1534
|
+
*/
|
|
1535
|
+
pantry?: Pantry;
|
|
1536
|
+
/**
|
|
1537
|
+
* The pantry with quantities updated after subtracting recipe needs.
|
|
1538
|
+
* Recomputed on every {@link ShoppingList.calculateIngredients | calculateIngredients()} call.
|
|
1539
|
+
*/
|
|
1540
|
+
private resultingPantry?;
|
|
1081
1541
|
/**
|
|
1082
1542
|
* Creates a new ShoppingList instance
|
|
1083
|
-
* @param
|
|
1543
|
+
* @param categoryConfigStr - The category configuration to parse.
|
|
1084
1544
|
*/
|
|
1085
|
-
constructor(
|
|
1086
|
-
private
|
|
1545
|
+
constructor(categoryConfigStr?: string | CategoryConfig);
|
|
1546
|
+
private calculateIngredients;
|
|
1547
|
+
/**
|
|
1548
|
+
* Subtracts pantry item quantities from calculated ingredient quantities
|
|
1549
|
+
* and updates the resultingPantry to reflect consumed stock.
|
|
1550
|
+
*/
|
|
1551
|
+
private applyPantrySubtraction;
|
|
1087
1552
|
/**
|
|
1088
1553
|
* Adds a recipe to the shopping list, then automatically
|
|
1089
1554
|
* recalculates the quantities and recategorize the ingredients.
|
|
1090
1555
|
* @param recipe - The recipe to add.
|
|
1091
1556
|
* @param options - Options for adding the recipe.
|
|
1557
|
+
* @throws Error if the recipe has alternatives without corresponding choices.
|
|
1558
|
+
*/
|
|
1559
|
+
addRecipe(recipe: Recipe, options?: AddedRecipeOptions): void;
|
|
1560
|
+
/**
|
|
1561
|
+
* Checks if a recipe has unresolved alternatives (alternatives without provided choices).
|
|
1562
|
+
* @param recipe - The recipe to check.
|
|
1563
|
+
* @param choices - The choices provided for the recipe.
|
|
1564
|
+
* @returns An error message if there are unresolved alternatives, undefined otherwise.
|
|
1092
1565
|
*/
|
|
1093
|
-
|
|
1566
|
+
private getUnresolvedAlternativesError;
|
|
1094
1567
|
/**
|
|
1095
1568
|
* Removes a recipe from the shopping list, then automatically
|
|
1096
|
-
* recalculates the quantities and recategorize the ingredients.
|
|
1569
|
+
* recalculates the quantities and recategorize the ingredients.
|
|
1097
1570
|
* @param index - The index of the recipe to remove.
|
|
1098
1571
|
*/
|
|
1099
|
-
|
|
1572
|
+
removeRecipe(index: number): void;
|
|
1573
|
+
/**
|
|
1574
|
+
* Adds a pantry to the shopping list. On-hand pantry quantities will be
|
|
1575
|
+
* subtracted from recipe ingredient needs on each recalculation.
|
|
1576
|
+
* @param pantry - A Pantry instance or a TOML string to parse.
|
|
1577
|
+
* @param options - Options for pantry parsing (only used when providing a TOML string).
|
|
1578
|
+
*/
|
|
1579
|
+
addPantry(pantry: Pantry | string, options?: PantryOptions): void;
|
|
1580
|
+
/**
|
|
1581
|
+
* Returns the resulting pantry with quantities updated to reflect
|
|
1582
|
+
* what was consumed by the shopping list's recipes.
|
|
1583
|
+
* Returns undefined if no pantry was added.
|
|
1584
|
+
* @returns The resulting Pantry, or undefined.
|
|
1585
|
+
*/
|
|
1586
|
+
getPantry(): Pantry | undefined;
|
|
1100
1587
|
/**
|
|
1101
1588
|
* Sets the category configuration for the shopping list
|
|
1102
1589
|
* and automatically categorize current ingredients from the list.
|
|
1590
|
+
* Also propagates the configuration to the pantry if one is set.
|
|
1103
1591
|
* @param config - The category configuration to parse.
|
|
1104
1592
|
*/
|
|
1105
|
-
|
|
1593
|
+
setCategoryConfig(config: string | CategoryConfig): void;
|
|
1106
1594
|
/**
|
|
1107
1595
|
* Categorizes the ingredients in the shopping list
|
|
1108
1596
|
* Will use the category config if any, otherwise all ingredients will be placed in the "other" category
|
|
@@ -1145,7 +1633,7 @@ interface ShoppingCartSummary {
|
|
|
1145
1633
|
* ```ts
|
|
1146
1634
|
* const shoppingList = new ShoppingList();
|
|
1147
1635
|
* const recipe = new Recipe("@flour{600%g}");
|
|
1148
|
-
* shoppingList.
|
|
1636
|
+
* shoppingList.addRecipe(recipe);
|
|
1149
1637
|
*
|
|
1150
1638
|
* const catalog = new ProductCatalog();
|
|
1151
1639
|
* catalog.products = [
|
|
@@ -1255,6 +1743,329 @@ declare class ShoppingCart {
|
|
|
1255
1743
|
summarize(): ShoppingCartSummary;
|
|
1256
1744
|
}
|
|
1257
1745
|
|
|
1746
|
+
/**
|
|
1747
|
+
* Render a fraction using Unicode vulgar fraction characters when available.
|
|
1748
|
+
* Handles improper fractions by extracting the whole part (e.g., 5/4 → "1¼").
|
|
1749
|
+
*
|
|
1750
|
+
* @param num - The numerator
|
|
1751
|
+
* @param den - The denominator
|
|
1752
|
+
* @returns The fraction as a string, using vulgar characters if available
|
|
1753
|
+
* @category Helpers
|
|
1754
|
+
*
|
|
1755
|
+
* @example
|
|
1756
|
+
* ```typescript
|
|
1757
|
+
* renderFractionAsVulgar(1, 2); // "½"
|
|
1758
|
+
* renderFractionAsVulgar(3, 4); // "¾"
|
|
1759
|
+
* renderFractionAsVulgar(5, 4); // "1¼"
|
|
1760
|
+
* renderFractionAsVulgar(7, 3); // "2⅓"
|
|
1761
|
+
* renderFractionAsVulgar(2, 5); // "2/5" (no vulgar character available)
|
|
1762
|
+
* ```
|
|
1763
|
+
*/
|
|
1764
|
+
declare function renderFractionAsVulgar(num: number, den: number): string;
|
|
1765
|
+
/**
|
|
1766
|
+
* Format a numeric value (decimal or fraction) to a string.
|
|
1767
|
+
*
|
|
1768
|
+
* @param value - The decimal or fraction value to format
|
|
1769
|
+
* @param useVulgar - Whether to use Unicode vulgar fraction characters (default: true)
|
|
1770
|
+
* @returns The formatted string representation
|
|
1771
|
+
* @category Helpers
|
|
1772
|
+
*
|
|
1773
|
+
* @example
|
|
1774
|
+
* ```typescript
|
|
1775
|
+
* formatNumericValue({ type: "decimal", decimal: 1.5 }); // "1.5"
|
|
1776
|
+
* formatNumericValue({ type: "fraction", num: 1, den: 2 }); // "½"
|
|
1777
|
+
* formatNumericValue({ type: "fraction", num: 1, den: 2 }, false); // "1/2"
|
|
1778
|
+
* formatNumericValue({ type: "fraction", num: 5, den: 4 }, true); // "1¼"
|
|
1779
|
+
* ```
|
|
1780
|
+
*/
|
|
1781
|
+
declare function formatNumericValue(value: DecimalValue | FractionValue, useVulgar?: boolean): string;
|
|
1782
|
+
/**
|
|
1783
|
+
* Format a single value (text, decimal, or fraction) to a string.
|
|
1784
|
+
*
|
|
1785
|
+
* @param value - The value to format
|
|
1786
|
+
* @returns The formatted string representation
|
|
1787
|
+
* @category Helpers
|
|
1788
|
+
*
|
|
1789
|
+
* @example
|
|
1790
|
+
* ```typescript
|
|
1791
|
+
* formatSingleValue({ type: "text", text: "a pinch" }); // "a pinch"
|
|
1792
|
+
* formatSingleValue({ type: "decimal", decimal: 2 }); // "2"
|
|
1793
|
+
* formatSingleValue({ type: "fraction", num: 3, den: 4 }); // "3/4"
|
|
1794
|
+
* ```
|
|
1795
|
+
*/
|
|
1796
|
+
declare function formatSingleValue(value: TextValue | DecimalValue | FractionValue): string;
|
|
1797
|
+
/**
|
|
1798
|
+
* Format a quantity (fixed value or range) to a string.
|
|
1799
|
+
*
|
|
1800
|
+
* @param quantity - The quantity to format
|
|
1801
|
+
* @returns The formatted string representation
|
|
1802
|
+
* @category Helpers
|
|
1803
|
+
*
|
|
1804
|
+
* @example
|
|
1805
|
+
* ```typescript
|
|
1806
|
+
* formatQuantity({ type: "fixed", value: { type: "decimal", decimal: 100 } }); // "100"
|
|
1807
|
+
* formatQuantity({ type: "range", min: { type: "decimal", decimal: 1 }, max: { type: "decimal", decimal: 2 } }); // "1-2"
|
|
1808
|
+
* ```
|
|
1809
|
+
*/
|
|
1810
|
+
declare function formatQuantity(quantity: FixedValue | Range): string;
|
|
1811
|
+
/**
|
|
1812
|
+
* Format a unit to a string. Handles both plain string units and Unit objects.
|
|
1813
|
+
*
|
|
1814
|
+
* @param unit - The unit to format (string, Unit object, or undefined)
|
|
1815
|
+
* @returns The formatted unit string, or empty string if undefined
|
|
1816
|
+
* @category Helpers
|
|
1817
|
+
*
|
|
1818
|
+
* @example
|
|
1819
|
+
* ```typescript
|
|
1820
|
+
* formatUnit("g"); // "g"
|
|
1821
|
+
* formatUnit({ name: "grams" }); // "grams"
|
|
1822
|
+
* formatUnit(undefined); // ""
|
|
1823
|
+
* ```
|
|
1824
|
+
*/
|
|
1825
|
+
declare function formatUnit(unit: string | Unit | undefined): string;
|
|
1826
|
+
/**
|
|
1827
|
+
* Format a quantity with its unit to a string.
|
|
1828
|
+
*
|
|
1829
|
+
* @param quantity - The quantity to format
|
|
1830
|
+
* @param unit - The unit to append (string, Unit object, or undefined)
|
|
1831
|
+
* @returns The formatted string with quantity and unit
|
|
1832
|
+
* @category Helpers
|
|
1833
|
+
*
|
|
1834
|
+
* @example
|
|
1835
|
+
* ```typescript
|
|
1836
|
+
* formatQuantityWithUnit({ type: "fixed", value: { type: "decimal", decimal: 100 } }, "g"); // "100 g"
|
|
1837
|
+
* formatQuantityWithUnit({ type: "fixed", value: { type: "decimal", decimal: 2 } }, undefined); // "2"
|
|
1838
|
+
* ```
|
|
1839
|
+
*/
|
|
1840
|
+
declare function formatQuantityWithUnit(quantity: FixedValue | Range | undefined, unit: string | Unit | undefined): string;
|
|
1841
|
+
/**
|
|
1842
|
+
* Format a QuantityWithExtendedUnit to a string.
|
|
1843
|
+
*
|
|
1844
|
+
* @param item - The quantity with extended unit to format
|
|
1845
|
+
* @returns The formatted string
|
|
1846
|
+
* @category Helpers
|
|
1847
|
+
*/
|
|
1848
|
+
declare function formatExtendedQuantity(item: QuantityWithExtendedUnit): string;
|
|
1849
|
+
/**
|
|
1850
|
+
* Format an IngredientItemQuantity with all its equivalents to a string.
|
|
1851
|
+
*
|
|
1852
|
+
* @param itemQuantity - The ingredient item quantity to format
|
|
1853
|
+
* @param separator - The separator between primary and equivalent quantities (default: " | ")
|
|
1854
|
+
* @returns The formatted string with all quantities
|
|
1855
|
+
* @category Helpers
|
|
1856
|
+
*
|
|
1857
|
+
* @example
|
|
1858
|
+
* ```typescript
|
|
1859
|
+
* // For an ingredient like @flour{100%g|3.5%oz}
|
|
1860
|
+
* formatItemQuantity(itemQuantity); // "100 g | 3.5 oz"
|
|
1861
|
+
* formatItemQuantity(itemQuantity, " / "); // "100 g / 3.5 oz"
|
|
1862
|
+
* ```
|
|
1863
|
+
*/
|
|
1864
|
+
declare function formatItemQuantity(itemQuantity: MaybeScalableQuantity, separator?: string): string;
|
|
1865
|
+
/**
|
|
1866
|
+
* Check if an ingredient item is a grouped alternative (vs inline alternative).
|
|
1867
|
+
*
|
|
1868
|
+
* Grouped alternatives are ingredients that share a group key (e.g., `@|milk|...`)
|
|
1869
|
+
* and are distributed across multiple tokens in the recipe.
|
|
1870
|
+
*
|
|
1871
|
+
* @param item - The ingredient item to check
|
|
1872
|
+
* @returns true if this is a grouped alternative
|
|
1873
|
+
* @category Helpers
|
|
1874
|
+
*
|
|
1875
|
+
* @example
|
|
1876
|
+
* ```typescript
|
|
1877
|
+
* for (const item of step.items) {
|
|
1878
|
+
* if (item.type === 'ingredient') {
|
|
1879
|
+
* if (isGroupedItem(item)) {
|
|
1880
|
+
* // Handle grouped alternative (e.g., show with strikethrough if not selected)
|
|
1881
|
+
* } else {
|
|
1882
|
+
* // Handle inline alternative (e.g., hide if not selected)
|
|
1883
|
+
* }
|
|
1884
|
+
* }
|
|
1885
|
+
* }
|
|
1886
|
+
* ```
|
|
1887
|
+
*/
|
|
1888
|
+
declare function isGroupedItem(item: IngredientItem): boolean;
|
|
1889
|
+
/**
|
|
1890
|
+
* Determines if a specific alternative in an IngredientItem is selected
|
|
1891
|
+
* based on the applied choices.
|
|
1892
|
+
*
|
|
1893
|
+
* Use this in renderers to determine how an ingredient alternative should be displayed.
|
|
1894
|
+
*
|
|
1895
|
+
* @param recipe - The Recipe instance containing choices
|
|
1896
|
+
* @param choices - The choices that have been made
|
|
1897
|
+
* @param item - The IngredientItem to check
|
|
1898
|
+
* @param alternativeIndex - The index within item.alternatives to check (for inline alternatives only)
|
|
1899
|
+
* @returns true if this alternative is the selected one
|
|
1900
|
+
* @category Helpers
|
|
1901
|
+
*
|
|
1902
|
+
* @example
|
|
1903
|
+
* ```typescript
|
|
1904
|
+
* const recipe = new Recipe(cooklangText);
|
|
1905
|
+
* for (const item of step.items) {
|
|
1906
|
+
* if (item.type === 'ingredient') {
|
|
1907
|
+
* item.alternatives.forEach((alt, idx) => {
|
|
1908
|
+
* const isSelected = isAlternativeSelected(recipe, choices, item, idx);
|
|
1909
|
+
* // Render differently based on isSelected
|
|
1910
|
+
* });
|
|
1911
|
+
* }
|
|
1912
|
+
* }
|
|
1913
|
+
* ```
|
|
1914
|
+
*/
|
|
1915
|
+
declare function isAlternativeSelected(recipe: Recipe, choices: RecipeChoices, item: IngredientItem, alternativeIndex?: number): boolean;
|
|
1916
|
+
/**
|
|
1917
|
+
* Determines if a section is active (should be displayed or processed) for a given variant.
|
|
1918
|
+
*
|
|
1919
|
+
* - Sections with no `variants` property are always active.
|
|
1920
|
+
* - When no variant is selected (default), sections tagged `[*]` are active,
|
|
1921
|
+
* and sections tagged with named variants are not.
|
|
1922
|
+
* - When a named variant is selected, sections whose `variants` array includes
|
|
1923
|
+
* that name are active.
|
|
1924
|
+
*
|
|
1925
|
+
* @param section - The Section to check
|
|
1926
|
+
* @param variant - The active variant name, or `undefined`/`*` for the default variant
|
|
1927
|
+
* @returns `true` if the section should be displayed
|
|
1928
|
+
* @category Helpers
|
|
1929
|
+
*
|
|
1930
|
+
* @example
|
|
1931
|
+
* ```typescript
|
|
1932
|
+
* const recipe = new Recipe(cooklangText);
|
|
1933
|
+
* for (const section of recipe.sections) {
|
|
1934
|
+
* if (isSectionActive(section, choices.variant)) {
|
|
1935
|
+
* // render section
|
|
1936
|
+
* }
|
|
1937
|
+
* }
|
|
1938
|
+
* ```
|
|
1939
|
+
*/
|
|
1940
|
+
declare function isSectionActive(section: Section, variant?: string): boolean;
|
|
1941
|
+
/**
|
|
1942
|
+
* Determines if a step is active (should be displayed) for a given variant.
|
|
1943
|
+
*
|
|
1944
|
+
* - Steps with no `variants` property are always active.
|
|
1945
|
+
* - When no variant is selected (default), steps tagged `[*]` are active,
|
|
1946
|
+
* and steps tagged with named variants are not.
|
|
1947
|
+
* - When a named variant is selected, steps whose `variants` array includes
|
|
1948
|
+
* that name are active.
|
|
1949
|
+
*
|
|
1950
|
+
* @param step - The Step to check
|
|
1951
|
+
* @param variant - The active variant name, or `undefined`/`*` for the default variant
|
|
1952
|
+
* @returns `true` if the step should be displayed
|
|
1953
|
+
* @category Helpers
|
|
1954
|
+
*
|
|
1955
|
+
* @example
|
|
1956
|
+
* ```typescript
|
|
1957
|
+
* for (const item of section.content) {
|
|
1958
|
+
* if (item.type === 'step' && isStepActive(item, choices.variant)) {
|
|
1959
|
+
* // render step
|
|
1960
|
+
* }
|
|
1961
|
+
* }
|
|
1962
|
+
* ```
|
|
1963
|
+
*/
|
|
1964
|
+
declare function isStepActive(step: Step, variant?: string): boolean;
|
|
1965
|
+
/**
|
|
1966
|
+
* Returns the effective choices for a recipe given a variant selection.
|
|
1967
|
+
*
|
|
1968
|
+
* When a named variant is active, this scans ingredient alternatives whose
|
|
1969
|
+
* `note` contains the variant name (case-insensitive substring match) and
|
|
1970
|
+
* returns a `RecipeChoices` object with auto-selected alternatives.
|
|
1971
|
+
*
|
|
1972
|
+
* For inline alternatives: auto-selects the first alternative whose note
|
|
1973
|
+
* matches the variant name.
|
|
1974
|
+
*
|
|
1975
|
+
* For grouped alternatives: auto-selects the first subgroup that has any
|
|
1976
|
+
* alternative whose note matches the variant name.
|
|
1977
|
+
*
|
|
1978
|
+
* @param recipe - The Recipe instance
|
|
1979
|
+
* @param variant - The active variant name, or `undefined`/`*` for defaults
|
|
1980
|
+
* @returns A `RecipeChoices` with the `variant` set and auto-selected alternatives
|
|
1981
|
+
* @category Helpers
|
|
1982
|
+
*
|
|
1983
|
+
* @example
|
|
1984
|
+
* ```typescript
|
|
1985
|
+
* const recipe = new Recipe(cooklangText);
|
|
1986
|
+
* const choices = getEffectiveChoices(recipe, "vegan");
|
|
1987
|
+
* const ingredients = recipe.getIngredientQuantities({ choices });
|
|
1988
|
+
* ```
|
|
1989
|
+
*/
|
|
1990
|
+
declare function getEffectiveChoices(recipe: Recipe, variant?: string): RecipeChoices;
|
|
1991
|
+
|
|
1992
|
+
/**
|
|
1993
|
+
* Type guard to check if an ingredient quantity-like object is an AND group.
|
|
1994
|
+
* *
|
|
1995
|
+
* @param x - The quantity-like entry to check
|
|
1996
|
+
* @returns true if this is an AND group (has `and` property)
|
|
1997
|
+
* @category Helpers
|
|
1998
|
+
*
|
|
1999
|
+
* @example
|
|
2000
|
+
* ```typescript
|
|
2001
|
+
* for (const entry of ingredient.quantities) {
|
|
2002
|
+
* if (isAndGroup(entry)) {
|
|
2003
|
+
* // entry.and contains the list of quantities in the AND group
|
|
2004
|
+
* }
|
|
2005
|
+
* }
|
|
2006
|
+
* ```
|
|
2007
|
+
*/
|
|
2008
|
+
declare function isAndGroup(x: IngredientQuantityGroup | IngredientQuantityAndGroup): x is IngredientQuantityAndGroup;
|
|
2009
|
+
declare function isAndGroup(x: QuantityWithUnitLike | Group): x is AndGroup;
|
|
2010
|
+
/**
|
|
2011
|
+
* Type guard to check if an ingredient quantity entry is a simple group.
|
|
2012
|
+
*
|
|
2013
|
+
* Simple groups have a single quantity with optional unit and equivalents.
|
|
2014
|
+
*
|
|
2015
|
+
* @param entry - The quantity entry to check
|
|
2016
|
+
* @returns true if this is a simple group (has `quantity` property)
|
|
2017
|
+
* @category Helpers
|
|
2018
|
+
*
|
|
2019
|
+
* @example
|
|
2020
|
+
* ```typescript
|
|
2021
|
+
* for (const entry of ingredient.quantities) {
|
|
2022
|
+
* if (isSimpleGroup(entry)) {
|
|
2023
|
+
* // entry.quantity is available
|
|
2024
|
+
* // entry.unit is available
|
|
2025
|
+
* }
|
|
2026
|
+
* }
|
|
2027
|
+
* ```
|
|
2028
|
+
*/
|
|
2029
|
+
declare function isSimpleGroup(entry: IngredientQuantityGroup | IngredientQuantityAndGroup): entry is IngredientQuantityGroup;
|
|
2030
|
+
/**
|
|
2031
|
+
* Type guard to check if an ingredient quantity entry has alternatives.
|
|
2032
|
+
*
|
|
2033
|
+
* @param entry - The quantity entry to check
|
|
2034
|
+
* @returns true if this entry has alternatives
|
|
2035
|
+
* @category Helpers
|
|
2036
|
+
*
|
|
2037
|
+
* @example
|
|
2038
|
+
* ```typescript
|
|
2039
|
+
* for (const entry of ingredient.quantities) {
|
|
2040
|
+
* if (hasAlternatives(entry)) {
|
|
2041
|
+
* // entry.alternatives is available and non-empty
|
|
2042
|
+
* for (const subgroup of entry.alternatives) {
|
|
2043
|
+
* // Each subgroup is one "or" choice; items within are combined with "+"
|
|
2044
|
+
* for (const alt of subgroup) {
|
|
2045
|
+
* console.log(`Alternative ingredient index: ${alt.index}`);
|
|
2046
|
+
* }
|
|
2047
|
+
* }
|
|
2048
|
+
* }
|
|
2049
|
+
* }
|
|
2050
|
+
* ```
|
|
2051
|
+
*/
|
|
2052
|
+
declare function hasAlternatives(entry: IngredientQuantityGroup | IngredientQuantityAndGroup): entry is (IngredientQuantityGroup | IngredientQuantityAndGroup) & {
|
|
2053
|
+
alternatives: AlternativeIngredientRef[][];
|
|
2054
|
+
};
|
|
2055
|
+
|
|
2056
|
+
/**
|
|
2057
|
+
* Converts a quantity to the best unit in a target system.
|
|
2058
|
+
* Returns the converted quantity, or undefined if the unit type is "other" or not convertible.
|
|
2059
|
+
*
|
|
2060
|
+
* @category Helpers
|
|
2061
|
+
*
|
|
2062
|
+
* @param quantity - The quantity to convert
|
|
2063
|
+
* @param system - The target unit system
|
|
2064
|
+
* @returns The converted quantity, or undefined if conversion not possible
|
|
2065
|
+
*/
|
|
2066
|
+
declare function convertQuantityToSystem(quantity: QuantityWithPlainUnit, system: SpecificUnitSystem): QuantityWithPlainUnit | undefined;
|
|
2067
|
+
declare function convertQuantityToSystem(quantity: QuantityWithExtendedUnit, system: SpecificUnitSystem): QuantityWithExtendedUnit | undefined;
|
|
2068
|
+
|
|
1258
2069
|
/**
|
|
1259
2070
|
* Error thrown when trying to build a shopping cart without a product catalog
|
|
1260
2071
|
* @category Errors
|
|
@@ -1270,4 +2081,4 @@ declare class NoShoppingListForCartError extends Error {
|
|
|
1270
2081
|
constructor();
|
|
1271
2082
|
}
|
|
1272
2083
|
|
|
1273
|
-
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type ArbitraryScalable, type ArbitraryScalableItem, type CartContent, type CartMatch, type CartMisMatch, type CategorizedIngredients, type Category, CategoryConfig, type CategoryIngredient, type
|
|
2084
|
+
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type AndGroup, type ArbitraryScalable, type ArbitraryScalableItem, type CartContent, type CartMatch, type CartMisMatch, type CategorizedIngredients, type Category, CategoryConfig, type CategoryIngredient, type Cookware, type CookwareFlag, type CookwareItem, type DecimalValue, type FixedNumericValue, type FixedValue, type FlatAndGroup, type FlatGroup, type FlatOrGroup, type FractionValue, type GetIngredientQuantitiesOptions, type Group, type Ingredient, type IngredientAlternative, type IngredientAlternativeBase, type IngredientExtras, type IngredientFlag, type IngredientItem, type IngredientQuantityAndGroup, type IngredientQuantityGroup, type MaybeNestedAndGroup, type MaybeNestedGroup, type MaybeNestedOrGroup, type MaybeScalableQuantity, type Metadata, type MetadataObject, type MetadataSource, type MetadataTime, type MetadataValue, NoProductCatalogForCartError, type NoProductMatchErrorCode, NoShoppingListForCartError, type Note, type NoteItem, type OrGroup, Pantry, type PantryItem, type PantryItemToml, type PantryOptions, ProductCatalog, type ProductMatch, type ProductMisMatch, type ProductOption, type ProductOptionBase, type ProductOptionCore, type ProductSelection, type ProductSize, type QuantityBase, type QuantityWithExtendedUnit, type QuantityWithPlainUnit, type QuantityWithUnitDef, type QuantityWithUnitLike, type Range, type RawQuantityGroup, Recipe, type RecipeAlternatives, type RecipeChoices, type RecipeWithFactor, type RecipeWithServings, Section, ShoppingCart, type ShoppingCartOptions, type ShoppingCartSummary, ShoppingList, type SpecificUnitSystem, type Step, type StepItem, type TextAttribute, type TextItem, type TextValue, type Timer, type TimerItem, type ToBaseBySystem, type Unit, type UnitDefinition, type UnitDefinitionLike, type UnitFractionConfig, type UnitSystem, type UnitType, type WithOptionalQuantity, type Yield, convertQuantityToSystem, formatExtendedQuantity, formatItemQuantity, formatNumericValue, formatQuantity, formatQuantityWithUnit, formatSingleValue, formatUnit, getEffectiveChoices, hasAlternatives, isAlternativeSelected, isAndGroup, isGroupedItem, isSectionActive, isSimpleGroup, isStepActive, renderFractionAsVulgar };
|