@tmlmt/cooklang-parser 3.0.0-alpha.9 → 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 +2520 -420
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +868 -129
- package/dist/index.d.ts +868 -129
- package/dist/index.js +2502 -419
- package/dist/index.js.map +1 -1
- package/package.json +17 -17
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
|
|
@@ -97,11 +103,28 @@ declare class Recipe {
|
|
|
97
103
|
* @see {@link Recipe.scaleBy | scaleBy()} and {@link Recipe.scaleTo | scaleTo()} methods
|
|
98
104
|
*/
|
|
99
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;
|
|
100
118
|
/**
|
|
101
119
|
* External storage for item count (not a property on instances).
|
|
102
120
|
* Used for giving ID numbers to items during parsing.
|
|
103
121
|
*/
|
|
104
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;
|
|
105
128
|
/**
|
|
106
129
|
* Gets the current item count for this recipe.
|
|
107
130
|
*/
|
|
@@ -142,7 +165,26 @@ declare class Recipe {
|
|
|
142
165
|
* Quantities are grouped by their alternative signature and summed using addEquivalentsAndSimplify.
|
|
143
166
|
* @internal
|
|
144
167
|
*/
|
|
145
|
-
private
|
|
168
|
+
private _populateIngredientQuantities;
|
|
169
|
+
/** @internal */
|
|
170
|
+
private collectQuantityGroups;
|
|
171
|
+
/**
|
|
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.
|
|
176
|
+
*
|
|
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
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
getRawQuantityGroups(options?: GetIngredientQuantitiesOptions): RawQuantityGroup[];
|
|
146
188
|
/**
|
|
147
189
|
* Gets ingredients with their quantities populated, optionally filtered by section/step
|
|
148
190
|
* and respecting user choices for alternatives.
|
|
@@ -171,6 +213,25 @@ declare class Recipe {
|
|
|
171
213
|
* ```
|
|
172
214
|
*/
|
|
173
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[];
|
|
174
235
|
/**
|
|
175
236
|
* Parses a recipe from a string.
|
|
176
237
|
* @param content - The recipe content to parse.
|
|
@@ -192,6 +253,26 @@ declare class Recipe {
|
|
|
192
253
|
* @returns A new Recipe instance with the scaled ingredients.
|
|
193
254
|
*/
|
|
194
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;
|
|
195
276
|
/**
|
|
196
277
|
* Gets the number of servings for the recipe.
|
|
197
278
|
* @private
|
|
@@ -205,6 +286,55 @@ declare class Recipe {
|
|
|
205
286
|
clone(): Recipe;
|
|
206
287
|
}
|
|
207
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;
|
|
208
338
|
/**
|
|
209
339
|
* Represents the metadata of a recipe.
|
|
210
340
|
* @category Types
|
|
@@ -214,56 +344,60 @@ interface Metadata {
|
|
|
214
344
|
title?: string;
|
|
215
345
|
/** The tags of the recipe. */
|
|
216
346
|
tags?: string[];
|
|
217
|
-
/**
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
/** The source author of the recipe. */
|
|
224
|
-
"source.author"?: string;
|
|
225
|
-
/** 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). */
|
|
226
353
|
author?: string;
|
|
227
354
|
/** The number of servings the recipe makes.
|
|
228
|
-
*
|
|
229
|
-
* (
|
|
230
|
-
* 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.
|
|
231
357
|
*
|
|
232
|
-
* Interchangeable with `yield` or `serves
|
|
233
|
-
*
|
|
234
|
-
* 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`.
|
|
235
361
|
*
|
|
236
362
|
* @example
|
|
237
363
|
* ```yaml
|
|
238
364
|
* servings: 4
|
|
239
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`.
|
|
240
377
|
*
|
|
241
378
|
* @example
|
|
242
379
|
* ```yaml
|
|
243
|
-
*
|
|
380
|
+
* yield: 300%g
|
|
244
381
|
* ```
|
|
245
|
-
*/
|
|
246
|
-
servings?: number | string;
|
|
247
|
-
/** The yield of the recipe.
|
|
248
|
-
* Should be either a number or a string which starts with a number
|
|
249
|
-
* (which will be used for scaling) followed by a comma and then
|
|
250
|
-
* whatever you want.
|
|
251
382
|
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```yaml
|
|
385
|
+
* yield: about {{300%g}} of bread
|
|
386
|
+
* ```
|
|
256
387
|
*/
|
|
257
|
-
yield?:
|
|
388
|
+
yield?: Yield;
|
|
258
389
|
/** The number of people the recipe serves.
|
|
259
|
-
*
|
|
260
|
-
* (
|
|
261
|
-
*
|
|
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`.
|
|
262
396
|
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```yaml
|
|
399
|
+
* serves: 4
|
|
400
|
+
* ```
|
|
267
401
|
*/
|
|
268
402
|
serves?: number | string;
|
|
269
403
|
/** The course of the recipe. */
|
|
@@ -273,30 +407,11 @@ interface Metadata {
|
|
|
273
407
|
/** The locale of the recipe. */
|
|
274
408
|
locale?: string;
|
|
275
409
|
/**
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
|
|
279
|
-
"prep time"?: string;
|
|
280
|
-
/**
|
|
281
|
-
* Alias of `prep time`
|
|
282
|
-
*/
|
|
283
|
-
"time.prep"?: string;
|
|
284
|
-
/**
|
|
285
|
-
* The cooking time of the recipe.
|
|
286
|
-
* Will not be further parsed into any DateTime format nor normalize
|
|
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.
|
|
287
413
|
*/
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Alias of `cook time`
|
|
291
|
-
*/
|
|
292
|
-
"time.cook"?: string;
|
|
293
|
-
/**
|
|
294
|
-
* The total time of the recipe.
|
|
295
|
-
* Will not be further parsed into any DateTime format nor normalize
|
|
296
|
-
*/
|
|
297
|
-
"time required"?: string;
|
|
298
|
-
time?: string;
|
|
299
|
-
duration?: string;
|
|
414
|
+
time?: MetadataTime;
|
|
300
415
|
/** The difficulty of the recipe. */
|
|
301
416
|
difficulty?: string;
|
|
302
417
|
/** The cuisine of the recipe. */
|
|
@@ -305,16 +420,25 @@ interface Metadata {
|
|
|
305
420
|
diet?: string;
|
|
306
421
|
/** The description of the recipe. */
|
|
307
422
|
description?: string;
|
|
308
|
-
/** The images of the recipe.
|
|
423
|
+
/** The images of the recipe. */
|
|
309
424
|
images?: string[];
|
|
310
|
-
/** The
|
|
311
|
-
pictures?: string[];
|
|
312
|
-
/** The picture of the recipe. Alias of `picture` */
|
|
425
|
+
/** The primary image of the recipe. */
|
|
313
426
|
image?: string;
|
|
314
|
-
/** The picture of the recipe. Alias of `image` */
|
|
315
|
-
picture?: string;
|
|
316
427
|
/** The introduction of the recipe. */
|
|
317
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;
|
|
318
442
|
}
|
|
319
443
|
/**
|
|
320
444
|
* Represents a quantity described by text, e.g. "a pinch"
|
|
@@ -385,7 +509,7 @@ interface IngredientExtras {
|
|
|
385
509
|
* Used if: the ingredient is a recipe
|
|
386
510
|
*
|
|
387
511
|
* @example
|
|
388
|
-
* ```
|
|
512
|
+
* ```yaml
|
|
389
513
|
* Take @./essentials/doughs/pizza dough{1} out of the freezer and let it unfreeze overnight
|
|
390
514
|
* ```
|
|
391
515
|
* Would lead to:
|
|
@@ -417,29 +541,31 @@ interface AlternativeIngredientRef {
|
|
|
417
541
|
interface IngredientQuantityGroup extends QuantityWithPlainUnit {
|
|
418
542
|
/**
|
|
419
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.
|
|
420
547
|
* If undefined, this group has no alternatives.
|
|
421
548
|
*/
|
|
422
|
-
alternatives?: AlternativeIngredientRef[];
|
|
549
|
+
alternatives?: AlternativeIngredientRef[][];
|
|
423
550
|
}
|
|
424
551
|
/**
|
|
425
552
|
* Represents an AND group of quantities when primary units are incompatible but equivalents can be summed.
|
|
426
|
-
* 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.
|
|
427
554
|
* @category Types
|
|
428
555
|
*/
|
|
429
|
-
interface IngredientQuantityAndGroup {
|
|
430
|
-
/**
|
|
431
|
-
* The incompatible primary quantities (e.g., "1 large" and "2 small").
|
|
432
|
-
*/
|
|
433
|
-
and: QuantityWithPlainUnit[];
|
|
556
|
+
interface IngredientQuantityAndGroup extends FlatAndGroup<QuantityWithPlainUnit> {
|
|
434
557
|
/**
|
|
435
558
|
* The summed equivalent quantities (e.g., "5 cups" from summing "1.5 cup + 2 cup + 1.5 cup").
|
|
436
559
|
*/
|
|
437
560
|
equivalents?: QuantityWithPlainUnit[];
|
|
438
561
|
/**
|
|
439
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.
|
|
440
566
|
* If undefined, this group has no alternatives.
|
|
441
567
|
*/
|
|
442
|
-
alternatives?: AlternativeIngredientRef[];
|
|
568
|
+
alternatives?: AlternativeIngredientRef[][];
|
|
443
569
|
}
|
|
444
570
|
/**
|
|
445
571
|
* Represents an ingredient in a recipe.
|
|
@@ -475,49 +601,40 @@ interface Ingredient {
|
|
|
475
601
|
extras?: IngredientExtras;
|
|
476
602
|
}
|
|
477
603
|
/**
|
|
478
|
-
* Represents a
|
|
479
|
-
*
|
|
604
|
+
* Represents a quantity with extended unit and additional information
|
|
605
|
+
* about its scalability and potential equivalents
|
|
606
|
+
*
|
|
480
607
|
* @category Types
|
|
481
608
|
*/
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
/** The list of ingredients mentioned in the preparation as alternatives to this ingredient */
|
|
490
|
-
alternatives?: Set<number>;
|
|
491
|
-
/** A list of potential state modifiers or other flags for the ingredient */
|
|
492
|
-
flags?: IngredientFlag[];
|
|
493
|
-
/** The collection of potential additional metadata for the ingredient */
|
|
494
|
-
extras?: IngredientExtras;
|
|
495
|
-
}
|
|
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
|
+
};
|
|
496
616
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
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
|
+
*
|
|
500
623
|
* @category Types
|
|
501
624
|
*/
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
/** Indicates whether this quantity should be scaled when the recipe serving size changes. */
|
|
509
|
-
scalable: boolean;
|
|
510
|
-
}
|
|
625
|
+
type WithOptionalQuantity<T> = (T & MaybeScalableQuantity) | (T & {
|
|
626
|
+
quantity?: undefined;
|
|
627
|
+
scalable?: never;
|
|
628
|
+
unit?: never;
|
|
629
|
+
equivalents?: never;
|
|
630
|
+
});
|
|
511
631
|
/**
|
|
512
|
-
*
|
|
513
|
-
* to a specific ingredient and its corresponding quantity information.
|
|
632
|
+
* Base type of {@link IngredientAlternative}
|
|
514
633
|
* @category Types
|
|
515
634
|
*/
|
|
516
|
-
|
|
635
|
+
type IngredientAlternativeBase = {
|
|
517
636
|
/** The index of the ingredient within the {@link Recipe.ingredients} array. */
|
|
518
637
|
index: number;
|
|
519
|
-
/** The quantity of this specific mention of the ingredient */
|
|
520
|
-
itemQuantity?: IngredientItemQuantity;
|
|
521
638
|
/** The alias/name of the ingredient as it should be displayed for this occurrence. */
|
|
522
639
|
displayName: string;
|
|
523
640
|
/** An optional note for this specific choice (e.g., "for a vegan version"). */
|
|
@@ -526,7 +643,16 @@ interface IngredientAlternative {
|
|
|
526
643
|
* with group keys: the id of the corresponding ingredient item (e.g. "ingredient-item-2").
|
|
527
644
|
* Can be useful for creating alternative selection UI elements with anchor links */
|
|
528
645
|
itemId?: string;
|
|
529
|
-
}
|
|
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>;
|
|
530
656
|
/**
|
|
531
657
|
* Represents an ingredient item in a recipe step.
|
|
532
658
|
* @category Types
|
|
@@ -547,6 +673,12 @@ interface IngredientItem {
|
|
|
547
673
|
* `@|group|...` syntax), they represent a single logical choice.
|
|
548
674
|
*/
|
|
549
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;
|
|
550
682
|
}
|
|
551
683
|
/**
|
|
552
684
|
* Represents the choices one can make in a recipe
|
|
@@ -560,9 +692,18 @@ interface RecipeAlternatives {
|
|
|
560
692
|
ingredientItems: Map<string, IngredientAlternative[]>;
|
|
561
693
|
/** Map of choices that can be made for Grouped Ingredient StepItem's
|
|
562
694
|
* - Keys are the Group IDs (e.g. "eggs" for `@|eggs|...`)
|
|
563
|
-
* - 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.
|
|
564
705
|
*/
|
|
565
|
-
|
|
706
|
+
variants: string[];
|
|
566
707
|
}
|
|
567
708
|
/**
|
|
568
709
|
* Represents the choices to apply when computing ingredient quantities.
|
|
@@ -574,6 +715,8 @@ interface RecipeChoices {
|
|
|
574
715
|
ingredientItems?: Map<string, number>;
|
|
575
716
|
/** Map of choices that can be made for Grouped Ingredient StepItem's */
|
|
576
717
|
ingredientGroups?: Map<string, number>;
|
|
718
|
+
/** The selected variant name */
|
|
719
|
+
variant?: string;
|
|
577
720
|
}
|
|
578
721
|
/**
|
|
579
722
|
* Options for the {@link Recipe.getIngredientQuantities | getIngredientQuantities()} method.
|
|
@@ -596,6 +739,23 @@ interface GetIngredientQuantitiesOptions {
|
|
|
596
739
|
*/
|
|
597
740
|
choices?: RecipeChoices;
|
|
598
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>)[];
|
|
758
|
+
}
|
|
599
759
|
/**
|
|
600
760
|
* Represents a cookware item in a recipe step.
|
|
601
761
|
* @category Types
|
|
@@ -630,6 +790,11 @@ interface Timer {
|
|
|
630
790
|
/** The unit of the timer. */
|
|
631
791
|
unit: string;
|
|
632
792
|
}
|
|
793
|
+
/**
|
|
794
|
+
* Represents a formatting attribute for a {@link TextItem}.
|
|
795
|
+
* @category Types
|
|
796
|
+
*/
|
|
797
|
+
type TextAttribute = "bold" | "italic" | "bold+italic" | "link" | "code";
|
|
633
798
|
/**
|
|
634
799
|
* Represents a text item in a recipe step.
|
|
635
800
|
* @category Types
|
|
@@ -639,6 +804,10 @@ interface TextItem {
|
|
|
639
804
|
type: "text";
|
|
640
805
|
/** The content of the text item. */
|
|
641
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;
|
|
642
811
|
}
|
|
643
812
|
/**
|
|
644
813
|
* Represents an arbitrary scalable quantity in a recipe.
|
|
@@ -675,6 +844,10 @@ interface Step {
|
|
|
675
844
|
type: "step";
|
|
676
845
|
/** The items in the step. */
|
|
677
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;
|
|
678
851
|
}
|
|
679
852
|
/**
|
|
680
853
|
* Represents an item in a note (can be text or arbitrary scalable).
|
|
@@ -745,6 +918,9 @@ interface RecipeWithServings {
|
|
|
745
918
|
type AddedRecipe = RecipeWithFactor | RecipeWithServings;
|
|
746
919
|
/**
|
|
747
920
|
* Options for adding a recipe to a shopping list
|
|
921
|
+
*
|
|
922
|
+
* Used in {@link ShoppingList.addRecipe}
|
|
923
|
+
*
|
|
748
924
|
* @category Types
|
|
749
925
|
*/
|
|
750
926
|
type AddedRecipeOptions = {
|
|
@@ -761,7 +937,7 @@ type AddedRecipeOptions = {
|
|
|
761
937
|
* Represents an ingredient that has been added to a shopping list
|
|
762
938
|
* @category Types
|
|
763
939
|
*/
|
|
764
|
-
type AddedIngredient = Pick<
|
|
940
|
+
type AddedIngredient = Pick<Ingredient, "name" | "quantities">;
|
|
765
941
|
/**
|
|
766
942
|
* Represents an ingredient in a category.
|
|
767
943
|
* @category Types
|
|
@@ -821,6 +997,48 @@ type ProductOption = ProductOptionBase & {
|
|
|
821
997
|
/** The size(s) of the product. Multiple sizes allow equivalent expressions (e.g., "1%dozen" and "12") */
|
|
822
998
|
sizes: ProductSize[];
|
|
823
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
|
+
}
|
|
824
1042
|
/**
|
|
825
1043
|
* Represents a product selection in a {@link ShoppingCart}
|
|
826
1044
|
* @category Types
|
|
@@ -873,12 +1091,23 @@ type CartMisMatch = ProductMisMatch[];
|
|
|
873
1091
|
* Represents the type category of a unit used for quantities
|
|
874
1092
|
* @category Types
|
|
875
1093
|
*/
|
|
876
|
-
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";
|
|
877
1100
|
/**
|
|
878
1101
|
* Represents the measurement system a unit belongs to
|
|
879
1102
|
* @category Types
|
|
880
1103
|
*/
|
|
881
|
-
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>>;
|
|
882
1111
|
/**
|
|
883
1112
|
* Represents a unit used to describe quantities
|
|
884
1113
|
* @category Types
|
|
@@ -898,8 +1127,28 @@ interface UnitDefinition extends Unit {
|
|
|
898
1127
|
system: UnitSystem;
|
|
899
1128
|
/** e.g. ['gram', 'grams'] */
|
|
900
1129
|
aliases: string[];
|
|
901
|
-
/** 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) */
|
|
902
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;
|
|
903
1152
|
}
|
|
904
1153
|
/**
|
|
905
1154
|
* Represents a resolved unit definition or a lightweight placeholder for non-standard units
|
|
@@ -946,6 +1195,13 @@ interface QuantityWithUnitDef extends QuantityBase {
|
|
|
946
1195
|
* @category Types
|
|
947
1196
|
*/
|
|
948
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
|
+
}
|
|
949
1205
|
/**
|
|
950
1206
|
* Represents an "or" group of alternative quantities that may contain nested groups (alternatives with nested structure)
|
|
951
1207
|
* @category Types
|
|
@@ -953,6 +1209,13 @@ type QuantityWithUnitLike = QuantityWithPlainUnit | QuantityWithExtendedUnit | Q
|
|
|
953
1209
|
interface MaybeNestedOrGroup<T = QuantityWithUnitLike> {
|
|
954
1210
|
or: (T | MaybeNestedGroup<T>)[];
|
|
955
1211
|
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Represents a flat "and" group of quantities (combined quantities)
|
|
1214
|
+
* @category Types
|
|
1215
|
+
*/
|
|
1216
|
+
interface FlatAndGroup<T = QuantityWithUnitLike> {
|
|
1217
|
+
and: T[];
|
|
1218
|
+
}
|
|
956
1219
|
/**
|
|
957
1220
|
* Represents an "and" group of quantities that may contain nested groups (combinations with nested structure)
|
|
958
1221
|
* @category Types
|
|
@@ -960,11 +1223,31 @@ interface MaybeNestedOrGroup<T = QuantityWithUnitLike> {
|
|
|
960
1223
|
interface MaybeNestedAndGroup<T = QuantityWithUnitLike> {
|
|
961
1224
|
and: (T | MaybeNestedGroup<T>)[];
|
|
962
1225
|
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Represents any flat group type ("and" or "or")
|
|
1228
|
+
* @category Types
|
|
1229
|
+
*/
|
|
1230
|
+
type FlatGroup<T = QuantityWithUnitLike> = FlatAndGroup<T> | FlatOrGroup<T>;
|
|
963
1231
|
/**
|
|
964
1232
|
* Represents any group type that may include nested groups
|
|
965
1233
|
* @category Types
|
|
966
1234
|
*/
|
|
967
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>;
|
|
968
1251
|
|
|
969
1252
|
/**
|
|
970
1253
|
* Parser for category configurations specified à-la-cooklang.
|
|
@@ -1015,6 +1298,127 @@ declare class CategoryConfig {
|
|
|
1015
1298
|
parse(config: string): void;
|
|
1016
1299
|
}
|
|
1017
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
|
+
|
|
1018
1422
|
/**
|
|
1019
1423
|
* Product Catalog Manager: used in conjunction with {@link ShoppingCart}
|
|
1020
1424
|
*
|
|
@@ -1041,7 +1445,7 @@ declare class CategoryConfig {
|
|
|
1041
1445
|
* 14141 = { name = "Big pack", size = "6%kg", price = 10 }
|
|
1042
1446
|
* `
|
|
1043
1447
|
* const catalog = new ProductCatalog(catalog);
|
|
1044
|
-
* const eggs = catalog.find("
|
|
1448
|
+
* const eggs = catalog.products.find(p => p.ingredientName === "eggs");
|
|
1045
1449
|
* ```
|
|
1046
1450
|
*/
|
|
1047
1451
|
declare class ProductCatalog {
|
|
@@ -1077,7 +1481,7 @@ declare class ProductCatalog {
|
|
|
1077
1481
|
* ## Usage
|
|
1078
1482
|
*
|
|
1079
1483
|
* - Create a new ShoppingList instance with an optional category configuration (see {@link ShoppingList."constructor" | constructor})
|
|
1080
|
-
* - Add recipes, scaling them as needed (see {@link ShoppingList.
|
|
1484
|
+
* - Add recipes, scaling them as needed (see {@link ShoppingList.addRecipe | addRecipe()})
|
|
1081
1485
|
* - Categorize the ingredients (see {@link ShoppingList.categorize | categorize()})
|
|
1082
1486
|
*
|
|
1083
1487
|
* @example
|
|
@@ -1089,10 +1493,10 @@ declare class ProductCatalog {
|
|
|
1089
1493
|
* const categoryConfig = fs.readFileSync("./myconfig.txt", "utf-8")
|
|
1090
1494
|
* const recipe1 = new Recipe(fs.readFileSync("./myrecipe.cook", "utf-8"));
|
|
1091
1495
|
* const shoppingList = new ShoppingList();
|
|
1092
|
-
* shoppingList.
|
|
1496
|
+
* shoppingList.setCategoryConfig(categoryConfig);
|
|
1093
1497
|
* // Quantities are automatically calculated and ingredients categorized
|
|
1094
1498
|
* // when adding a recipe
|
|
1095
|
-
* shoppingList.
|
|
1499
|
+
* shoppingList.addRecipe(recipe1);
|
|
1096
1500
|
* ```
|
|
1097
1501
|
*
|
|
1098
1502
|
* @category Classes
|
|
@@ -1109,17 +1513,42 @@ declare class ShoppingList {
|
|
|
1109
1513
|
/**
|
|
1110
1514
|
* The category configuration for the shopping list.
|
|
1111
1515
|
*/
|
|
1112
|
-
|
|
1516
|
+
categoryConfig?: CategoryConfig;
|
|
1113
1517
|
/**
|
|
1114
1518
|
* The categorized ingredients in the shopping list.
|
|
1115
1519
|
*/
|
|
1116
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?;
|
|
1117
1541
|
/**
|
|
1118
1542
|
* Creates a new ShoppingList instance
|
|
1119
|
-
* @param
|
|
1543
|
+
* @param categoryConfigStr - The category configuration to parse.
|
|
1120
1544
|
*/
|
|
1121
|
-
constructor(
|
|
1122
|
-
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;
|
|
1123
1552
|
/**
|
|
1124
1553
|
* Adds a recipe to the shopping list, then automatically
|
|
1125
1554
|
* recalculates the quantities and recategorize the ingredients.
|
|
@@ -1127,7 +1556,7 @@ declare class ShoppingList {
|
|
|
1127
1556
|
* @param options - Options for adding the recipe.
|
|
1128
1557
|
* @throws Error if the recipe has alternatives without corresponding choices.
|
|
1129
1558
|
*/
|
|
1130
|
-
|
|
1559
|
+
addRecipe(recipe: Recipe, options?: AddedRecipeOptions): void;
|
|
1131
1560
|
/**
|
|
1132
1561
|
* Checks if a recipe has unresolved alternatives (alternatives without provided choices).
|
|
1133
1562
|
* @param recipe - The recipe to check.
|
|
@@ -1137,16 +1566,31 @@ declare class ShoppingList {
|
|
|
1137
1566
|
private getUnresolvedAlternativesError;
|
|
1138
1567
|
/**
|
|
1139
1568
|
* Removes a recipe from the shopping list, then automatically
|
|
1140
|
-
* recalculates the quantities and recategorize the ingredients.
|
|
1569
|
+
* recalculates the quantities and recategorize the ingredients.
|
|
1141
1570
|
* @param index - The index of the recipe to remove.
|
|
1142
1571
|
*/
|
|
1143
|
-
|
|
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;
|
|
1144
1587
|
/**
|
|
1145
1588
|
* Sets the category configuration for the shopping list
|
|
1146
1589
|
* and automatically categorize current ingredients from the list.
|
|
1590
|
+
* Also propagates the configuration to the pantry if one is set.
|
|
1147
1591
|
* @param config - The category configuration to parse.
|
|
1148
1592
|
*/
|
|
1149
|
-
|
|
1593
|
+
setCategoryConfig(config: string | CategoryConfig): void;
|
|
1150
1594
|
/**
|
|
1151
1595
|
* Categorizes the ingredients in the shopping list
|
|
1152
1596
|
* Will use the category config if any, otherwise all ingredients will be placed in the "other" category
|
|
@@ -1189,7 +1633,7 @@ interface ShoppingCartSummary {
|
|
|
1189
1633
|
* ```ts
|
|
1190
1634
|
* const shoppingList = new ShoppingList();
|
|
1191
1635
|
* const recipe = new Recipe("@flour{600%g}");
|
|
1192
|
-
* shoppingList.
|
|
1636
|
+
* shoppingList.addRecipe(recipe);
|
|
1193
1637
|
*
|
|
1194
1638
|
* const catalog = new ProductCatalog();
|
|
1195
1639
|
* catalog.products = [
|
|
@@ -1299,6 +1743,149 @@ declare class ShoppingCart {
|
|
|
1299
1743
|
summarize(): ShoppingCartSummary;
|
|
1300
1744
|
}
|
|
1301
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;
|
|
1302
1889
|
/**
|
|
1303
1890
|
* Determines if a specific alternative in an IngredientItem is selected
|
|
1304
1891
|
* based on the applied choices.
|
|
@@ -1318,7 +1905,7 @@ declare class ShoppingCart {
|
|
|
1318
1905
|
* for (const item of step.items) {
|
|
1319
1906
|
* if (item.type === 'ingredient') {
|
|
1320
1907
|
* item.alternatives.forEach((alt, idx) => {
|
|
1321
|
-
* const isSelected = isAlternativeSelected(
|
|
1908
|
+
* const isSelected = isAlternativeSelected(recipe, choices, item, idx);
|
|
1322
1909
|
* // Render differently based on isSelected
|
|
1323
1910
|
* });
|
|
1324
1911
|
* }
|
|
@@ -1326,6 +1913,158 @@ declare class ShoppingCart {
|
|
|
1326
1913
|
* ```
|
|
1327
1914
|
*/
|
|
1328
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;
|
|
1329
2068
|
|
|
1330
2069
|
/**
|
|
1331
2070
|
* Error thrown when trying to build a shopping cart without a product catalog
|
|
@@ -1342,4 +2081,4 @@ declare class NoShoppingListForCartError extends Error {
|
|
|
1342
2081
|
constructor();
|
|
1343
2082
|
}
|
|
1344
2083
|
|
|
1345
|
-
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 };
|