@tmlmt/cooklang-parser 3.0.0-alpha.15 → 3.0.0-alpha.16
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 +119 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -14
- package/dist/index.d.ts +34 -14
- package/dist/index.js +119 -65
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.d.cts
CHANGED
|
@@ -268,6 +268,18 @@ interface MetadataSource {
|
|
|
268
268
|
/** The author at the source. */
|
|
269
269
|
author?: string;
|
|
270
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Represents scaling variable information for a recipe.
|
|
273
|
+
* @category Types
|
|
274
|
+
*/
|
|
275
|
+
interface MetadataScalingVar extends QuantityWithPlainUnit {
|
|
276
|
+
/** The text before the scaling variable. */
|
|
277
|
+
textBefore?: string;
|
|
278
|
+
/** The text after the scaling variable. */
|
|
279
|
+
textAfter?: string;
|
|
280
|
+
/** The text precising a numerical scaling variable. */
|
|
281
|
+
text?: string;
|
|
282
|
+
}
|
|
271
283
|
/**
|
|
272
284
|
* Represents time information for a recipe.
|
|
273
285
|
* @category Types
|
|
@@ -291,7 +303,7 @@ interface MetadataObject {
|
|
|
291
303
|
* Represents any value that can appear in recipe metadata.
|
|
292
304
|
* @category Types
|
|
293
305
|
*/
|
|
294
|
-
type MetadataValue = string | number | (string | number)[] | MetadataObject | MetadataSource | MetadataTime | undefined;
|
|
306
|
+
type MetadataValue = string | number | (string | number)[] | MetadataObject | MetadataSource | MetadataTime | MetadataScalingVar | undefined;
|
|
295
307
|
/**
|
|
296
308
|
* Represents the metadata of a recipe.
|
|
297
309
|
* @category Types
|
|
@@ -309,9 +321,10 @@ interface Metadata {
|
|
|
309
321
|
/** The author of the recipe (separate from source author). */
|
|
310
322
|
author?: string;
|
|
311
323
|
/** The number of servings the recipe makes.
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* whatever you want
|
|
324
|
+
* Can be given either as:
|
|
325
|
+
* - a number
|
|
326
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
327
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
315
328
|
*
|
|
316
329
|
* Interchangeable with `yield` or `serves`. If multiple ones are defined,
|
|
317
330
|
* the prevailance order for the number which will used for scaling
|
|
@@ -326,30 +339,37 @@ interface Metadata {
|
|
|
326
339
|
* ```yaml
|
|
327
340
|
* servings: 2, a few
|
|
328
341
|
* ```
|
|
342
|
+
*
|
|
343
|
+
* * @example
|
|
344
|
+
* ```yaml
|
|
345
|
+
* servings: {{1.5%kg}} of bread
|
|
346
|
+
* ```
|
|
329
347
|
*/
|
|
330
|
-
servings?:
|
|
348
|
+
servings?: MetadataScalingVar;
|
|
331
349
|
/** The yield of the recipe.
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* whatever you want
|
|
350
|
+
* Can be given either as:
|
|
351
|
+
* - a number
|
|
352
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
353
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
335
354
|
*
|
|
336
355
|
* Interchangeable with `servings` or `serves`. If multiple ones are defined,
|
|
337
356
|
* the prevailance order for the number which will used for scaling
|
|
338
357
|
* is `servings` \> `yield` \> `serves`. See {@link Metadata.servings | servings}
|
|
339
358
|
* for examples.
|
|
340
359
|
*/
|
|
341
|
-
yield?:
|
|
360
|
+
yield?: MetadataScalingVar;
|
|
342
361
|
/** The number of people the recipe serves.
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* whatever you want
|
|
362
|
+
* Can be given either as:
|
|
363
|
+
* - a number
|
|
364
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
365
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
346
366
|
*
|
|
347
367
|
* Interchangeable with `servings` or `yield`. If multiple ones are defined,
|
|
348
368
|
* the prevailance order for the number which will used for scaling
|
|
349
369
|
* is `servings` \> `yield` \> `serves`. See {@link Metadata.servings | servings}
|
|
350
370
|
* for examples.
|
|
351
371
|
*/
|
|
352
|
-
serves?:
|
|
372
|
+
serves?: MetadataScalingVar;
|
|
353
373
|
/** The course of the recipe. */
|
|
354
374
|
course?: string;
|
|
355
375
|
/** The category of the recipe. */
|
|
@@ -1918,4 +1938,4 @@ declare class BadIndentationError extends Error {
|
|
|
1918
1938
|
constructor();
|
|
1919
1939
|
}
|
|
1920
1940
|
|
|
1921
|
-
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type AndGroup, type ArbitraryScalable, type ArbitraryScalableItem, BadIndentationError, 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, NoTabAsIndentError, 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, convertQuantityToSystem, formatExtendedQuantity, formatItemQuantity, formatNumericValue, formatQuantity, formatQuantityWithUnit, formatSingleValue, formatUnit, hasAlternatives, isAlternativeSelected, isAndGroup, isGroupedItem, isSimpleGroup, renderFractionAsVulgar };
|
|
1941
|
+
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type AndGroup, type ArbitraryScalable, type ArbitraryScalableItem, BadIndentationError, 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 MetadataScalingVar, type MetadataSource, type MetadataTime, type MetadataValue, NoProductCatalogForCartError, type NoProductMatchErrorCode, NoShoppingListForCartError, NoTabAsIndentError, 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, convertQuantityToSystem, formatExtendedQuantity, formatItemQuantity, formatNumericValue, formatQuantity, formatQuantityWithUnit, formatSingleValue, formatUnit, hasAlternatives, isAlternativeSelected, isAndGroup, isGroupedItem, isSimpleGroup, renderFractionAsVulgar };
|
package/dist/index.d.ts
CHANGED
|
@@ -268,6 +268,18 @@ interface MetadataSource {
|
|
|
268
268
|
/** The author at the source. */
|
|
269
269
|
author?: string;
|
|
270
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Represents scaling variable information for a recipe.
|
|
273
|
+
* @category Types
|
|
274
|
+
*/
|
|
275
|
+
interface MetadataScalingVar extends QuantityWithPlainUnit {
|
|
276
|
+
/** The text before the scaling variable. */
|
|
277
|
+
textBefore?: string;
|
|
278
|
+
/** The text after the scaling variable. */
|
|
279
|
+
textAfter?: string;
|
|
280
|
+
/** The text precising a numerical scaling variable. */
|
|
281
|
+
text?: string;
|
|
282
|
+
}
|
|
271
283
|
/**
|
|
272
284
|
* Represents time information for a recipe.
|
|
273
285
|
* @category Types
|
|
@@ -291,7 +303,7 @@ interface MetadataObject {
|
|
|
291
303
|
* Represents any value that can appear in recipe metadata.
|
|
292
304
|
* @category Types
|
|
293
305
|
*/
|
|
294
|
-
type MetadataValue = string | number | (string | number)[] | MetadataObject | MetadataSource | MetadataTime | undefined;
|
|
306
|
+
type MetadataValue = string | number | (string | number)[] | MetadataObject | MetadataSource | MetadataTime | MetadataScalingVar | undefined;
|
|
295
307
|
/**
|
|
296
308
|
* Represents the metadata of a recipe.
|
|
297
309
|
* @category Types
|
|
@@ -309,9 +321,10 @@ interface Metadata {
|
|
|
309
321
|
/** The author of the recipe (separate from source author). */
|
|
310
322
|
author?: string;
|
|
311
323
|
/** The number of servings the recipe makes.
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* whatever you want
|
|
324
|
+
* Can be given either as:
|
|
325
|
+
* - a number
|
|
326
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
327
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
315
328
|
*
|
|
316
329
|
* Interchangeable with `yield` or `serves`. If multiple ones are defined,
|
|
317
330
|
* the prevailance order for the number which will used for scaling
|
|
@@ -326,30 +339,37 @@ interface Metadata {
|
|
|
326
339
|
* ```yaml
|
|
327
340
|
* servings: 2, a few
|
|
328
341
|
* ```
|
|
342
|
+
*
|
|
343
|
+
* * @example
|
|
344
|
+
* ```yaml
|
|
345
|
+
* servings: {{1.5%kg}} of bread
|
|
346
|
+
* ```
|
|
329
347
|
*/
|
|
330
|
-
servings?:
|
|
348
|
+
servings?: MetadataScalingVar;
|
|
331
349
|
/** The yield of the recipe.
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* whatever you want
|
|
350
|
+
* Can be given either as:
|
|
351
|
+
* - a number
|
|
352
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
353
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
335
354
|
*
|
|
336
355
|
* Interchangeable with `servings` or `serves`. If multiple ones are defined,
|
|
337
356
|
* the prevailance order for the number which will used for scaling
|
|
338
357
|
* is `servings` \> `yield` \> `serves`. See {@link Metadata.servings | servings}
|
|
339
358
|
* for examples.
|
|
340
359
|
*/
|
|
341
|
-
yield?:
|
|
360
|
+
yield?: MetadataScalingVar;
|
|
342
361
|
/** The number of people the recipe serves.
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* whatever you want
|
|
362
|
+
* Can be given either as:
|
|
363
|
+
* - a number
|
|
364
|
+
* - a string which starts with a number (which will be used for scaling) followed by a comma and then whatever you want
|
|
365
|
+
* - or an arbitrary scalable number, optionally preceded and/or followed by text.
|
|
346
366
|
*
|
|
347
367
|
* Interchangeable with `servings` or `yield`. If multiple ones are defined,
|
|
348
368
|
* the prevailance order for the number which will used for scaling
|
|
349
369
|
* is `servings` \> `yield` \> `serves`. See {@link Metadata.servings | servings}
|
|
350
370
|
* for examples.
|
|
351
371
|
*/
|
|
352
|
-
serves?:
|
|
372
|
+
serves?: MetadataScalingVar;
|
|
353
373
|
/** The course of the recipe. */
|
|
354
374
|
course?: string;
|
|
355
375
|
/** The category of the recipe. */
|
|
@@ -1918,4 +1938,4 @@ declare class BadIndentationError extends Error {
|
|
|
1918
1938
|
constructor();
|
|
1919
1939
|
}
|
|
1920
1940
|
|
|
1921
|
-
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type AndGroup, type ArbitraryScalable, type ArbitraryScalableItem, BadIndentationError, 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, NoTabAsIndentError, 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, convertQuantityToSystem, formatExtendedQuantity, formatItemQuantity, formatNumericValue, formatQuantity, formatQuantityWithUnit, formatSingleValue, formatUnit, hasAlternatives, isAlternativeSelected, isAndGroup, isGroupedItem, isSimpleGroup, renderFractionAsVulgar };
|
|
1941
|
+
export { type AddedIngredient, type AddedRecipe, type AddedRecipeOptions, type AlternativeIngredientRef, type AndGroup, type ArbitraryScalable, type ArbitraryScalableItem, BadIndentationError, 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 MetadataScalingVar, type MetadataSource, type MetadataTime, type MetadataValue, NoProductCatalogForCartError, type NoProductMatchErrorCode, NoShoppingListForCartError, NoTabAsIndentError, 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, convertQuantityToSystem, formatExtendedQuantity, formatItemQuantity, formatNumericValue, formatQuantity, formatQuantityWithUnit, formatSingleValue, formatUnit, hasAlternatives, isAlternativeSelected, isAndGroup, isGroupedItem, isSimpleGroup, renderFractionAsVulgar };
|
package/dist/index.js
CHANGED
|
@@ -272,7 +272,6 @@ var nestedMetaVarRegex = (varName) => new RegExp(
|
|
|
272
272
|
"m"
|
|
273
273
|
);
|
|
274
274
|
var metadataRegex = d().literal("---").newline().startCaptureGroup().anyCharacter().zeroOrMore().optional().endGroup().newline().literal("---").dotAll().toRegExp();
|
|
275
|
-
var scalingMetaValueRegex = (varName) => d().startAnchor().literal(varName).literal(":").anyOf("\\t ").zeroOrMore().startCaptureGroup().startCaptureGroup().notAnyOf(",\\n").oneOrMore().endGroup().startGroup().literal(",").whitespace().zeroOrMore().startCaptureGroup().anyCharacter().oneOrMore().endGroup().endGroup().optional().endGroup().endAnchor().multiline().toRegExp();
|
|
276
275
|
var nonWordChar = "\\s@#~\\[\\]{(,;:!?";
|
|
277
276
|
var nonWordCharStrict = "\\s@#~\\[\\]{(,;:!?|";
|
|
278
277
|
var ingredientWithAlternativeRegex = d().literal("@").startNamedGroup("ingredientModifiers").anyOf("@\\-&?").zeroOrMore().endGroup().optional().startNamedGroup("ingredientRecipeAnchor").literal("./").endGroup().optional().startGroup().startGroup().startNamedGroup("mIngredientName").notAnyOf(nonWordChar).oneOrMore().startGroup().whitespace().oneOrMore().notAnyOf(nonWordChar).oneOrMore().endGroup().oneOrMore().endGroup().positiveLookahead("\\s*(?:\\{[^\\}]*\\}|\\([^)]*\\))").endGroup().or().startNamedGroup("sIngredientName").notAnyOf(nonWordChar).zeroOrMore().notAnyOf("\\." + nonWordChar).endGroup().endGroup().startGroup().literal("{").startNamedGroup("ingredientQuantityModifier").literal("=").exactly(1).endGroup().optional().startNamedGroup("ingredientQuantity").startGroup().notAnyOf("}|%").oneOrMore().endGroup().optional().startGroup().literal("%").notAnyOf("|}").oneOrMore().lazy().endGroup().optional().startGroup().literal("|").notAnyOf("}").oneOrMore().lazy().endGroup().zeroOrMore().endGroup().literal("}").endGroup().optional().startGroup().literal("(").startNamedGroup("ingredientPreparation").notAnyOf(")").oneOrMore().lazy().endGroup().literal(")").endGroup().optional().startGroup().literal("[").startNamedGroup("ingredientNote").notAnyOf("\\]").oneOrMore().lazy().endGroup().literal("]").endGroup().optional().startNamedGroup("ingredientAlternative").startGroup().literal("|").startGroup().anyOf("@\\-&?").zeroOrMore().endGroup().optional().startGroup().literal("./").endGroup().optional().startGroup().startGroup().startGroup().notAnyOf(nonWordChar).oneOrMore().startGroup().whitespace().oneOrMore().notAnyOf(nonWordChar).oneOrMore().endGroup().oneOrMore().endGroup().positiveLookahead("\\s*(?:\\{[^\\}]*\\}|\\([^)]*\\))").endGroup().or().startGroup().notAnyOf(nonWordChar).oneOrMore().endGroup().endGroup().startGroup().literal("{").startGroup().literal("=").exactly(1).endGroup().optional().startGroup().notAnyOf("}%").oneOrMore().endGroup().optional().startGroup().literal("%").startGroup().notAnyOf("}").oneOrMore().lazy().endGroup().endGroup().optional().literal("}").endGroup().optional().startGroup().literal("(").startGroup().notAnyOf(")").oneOrMore().lazy().endGroup().literal(")").endGroup().optional().startGroup().literal("[").startGroup().notAnyOf("\\]").oneOrMore().lazy().endGroup().literal("]").endGroup().optional().endGroup().zeroOrMore().endGroup().toRegExp();
|
|
@@ -293,6 +292,13 @@ var tokensRegex = new RegExp(
|
|
|
293
292
|
].map((r2) => r2.source).join("|"),
|
|
294
293
|
"gu"
|
|
295
294
|
);
|
|
295
|
+
var servingsPrefixPart = (varName) => d().startAnchor().literal(varName).literal(":").anyOf(" ").zeroOrMore().startNamedGroup("servingsPrefix").nonWhitespace().startGroup().anyCharacter().zeroOrMore().lazy().nonWhitespace().endGroup().optional().endGroup().optional().anyOf(" ").zeroOrMore().toRegExp();
|
|
296
|
+
var servingsSuffixPart = d().anyOf(" ").zeroOrMore().startNamedGroup("servingsSuffix").nonWhitespace().startGroup().anyCharacter().zeroOrMore().nonWhitespace().endGroup().optional().endGroup().optional().anyOf(" ").zeroOrMore().endAnchor().toRegExp();
|
|
297
|
+
var scalingSimpleMetaValueRegex = (varName) => d().startAnchor().literal(varName).literal(":").anyOf("\\t ").zeroOrMore().startCaptureGroup().startCaptureGroup().notAnyOf(",\\n").oneOrMore().endGroup().startGroup().literal(",").anyOf("\\t ").zeroOrMore().startCaptureGroup().anyCharacter().oneOrMore().endGroup().optional().endGroup().optional().endGroup().endAnchor().multiline().toRegExp();
|
|
298
|
+
var scalingMetaValueWithUnitRegex = (varName) => new RegExp(
|
|
299
|
+
servingsPrefixPart(varName).source + arbitraryScalableRegex.source + servingsSuffixPart.source,
|
|
300
|
+
"m"
|
|
301
|
+
);
|
|
296
302
|
var commentRegex = d().literal("--").anyCharacter().zeroOrMore().global().toRegExp();
|
|
297
303
|
var blockCommentRegex = d().literal("[-").anyCharacter().zeroOrMore().lazy().literal("-]").whitespace().zeroOrMore().global().toRegExp();
|
|
298
304
|
var shoppingListRegex = d().literal("[").startNamedGroup("name").anyCharacter().oneOrMore().endGroup().literal("]").newline().startNamedGroup("items").anyCharacter().zeroOrMore().lazy().endGroup().startGroup().newline().newline().or().endAnchor().endGroup().global().toRegExp();
|
|
@@ -1276,17 +1282,21 @@ var flattenPlainUnitGroup = (summed) => {
|
|
|
1276
1282
|
}
|
|
1277
1283
|
};
|
|
1278
1284
|
function applyBestUnit(q, system) {
|
|
1279
|
-
|
|
1285
|
+
const extended = { quantity: q.quantity };
|
|
1286
|
+
if (q.unit) {
|
|
1287
|
+
extended.unit = typeof q.unit === "string" ? { name: q.unit } : q.unit;
|
|
1288
|
+
}
|
|
1289
|
+
if (!extended.unit?.name) {
|
|
1280
1290
|
return q;
|
|
1281
1291
|
}
|
|
1282
|
-
const unitDef = resolveUnit(
|
|
1292
|
+
const unitDef = resolveUnit(extended.unit.name);
|
|
1283
1293
|
if (unitDef.type === "other") {
|
|
1284
1294
|
return q;
|
|
1285
1295
|
}
|
|
1286
|
-
if (
|
|
1296
|
+
if (extended.quantity.type === "fixed" && extended.quantity.value.type === "text") {
|
|
1287
1297
|
return q;
|
|
1288
1298
|
}
|
|
1289
|
-
const avgValue = getAverageValue(
|
|
1299
|
+
const avgValue = getAverageValue(extended.quantity);
|
|
1290
1300
|
const effectiveSystem = system ?? (["metric", "JP"].includes(unitDef.system) ? unitDef.system : "US");
|
|
1291
1301
|
const toBase = getToBase(unitDef, effectiveSystem);
|
|
1292
1302
|
const valueInBase = avgValue * toBase;
|
|
@@ -1296,22 +1306,22 @@ function applyBestUnit(q, system) {
|
|
|
1296
1306
|
effectiveSystem,
|
|
1297
1307
|
[unitDef]
|
|
1298
1308
|
);
|
|
1299
|
-
const originalCanonicalName = normalizeUnit(
|
|
1309
|
+
const originalCanonicalName = normalizeUnit(extended.unit.name)?.name;
|
|
1300
1310
|
if (bestUnit.name === originalCanonicalName) {
|
|
1301
1311
|
return q;
|
|
1302
1312
|
}
|
|
1303
1313
|
const formattedValue = formatOutputValue(bestValue, bestUnit);
|
|
1304
|
-
if (
|
|
1314
|
+
if (extended.quantity.type === "range") {
|
|
1305
1315
|
const bestToBase = getToBase(bestUnit, effectiveSystem);
|
|
1306
|
-
const minValue = getNumericValue(
|
|
1307
|
-
const maxValue = getNumericValue(
|
|
1316
|
+
const minValue = getNumericValue(extended.quantity.min) * toBase / bestToBase;
|
|
1317
|
+
const maxValue = getNumericValue(extended.quantity.max) * toBase / bestToBase;
|
|
1308
1318
|
return {
|
|
1309
1319
|
quantity: {
|
|
1310
1320
|
type: "range",
|
|
1311
1321
|
min: formatOutputValue(minValue, bestUnit),
|
|
1312
1322
|
max: formatOutputValue(maxValue, bestUnit)
|
|
1313
1323
|
},
|
|
1314
|
-
unit: { name: bestUnit.name }
|
|
1324
|
+
unit: typeof q.unit === "string" ? bestUnit.name : { name: bestUnit.name }
|
|
1315
1325
|
};
|
|
1316
1326
|
}
|
|
1317
1327
|
return {
|
|
@@ -1319,7 +1329,7 @@ function applyBestUnit(q, system) {
|
|
|
1319
1329
|
type: "fixed",
|
|
1320
1330
|
value: formattedValue
|
|
1321
1331
|
},
|
|
1322
|
-
unit: { name: bestUnit.name }
|
|
1332
|
+
unit: typeof q.unit === "string" ? bestUnit.name : { name: bestUnit.name }
|
|
1323
1333
|
};
|
|
1324
1334
|
}
|
|
1325
1335
|
function subtractQuantities(q1, q2, options = {}) {
|
|
@@ -1671,13 +1681,62 @@ function parseBlockScalarMetaVar(content, varName) {
|
|
|
1671
1681
|
}
|
|
1672
1682
|
return stripped.replace(/\n\n/g, "\0").replace(/\n/g, " ").replace(/\0/g, "\n");
|
|
1673
1683
|
}
|
|
1684
|
+
function parseArbitraryQuantity(raw) {
|
|
1685
|
+
const quantityMatch = raw.trim().match(quantityAlternativeRegex);
|
|
1686
|
+
if (!quantityMatch?.groups) {
|
|
1687
|
+
throw new InvalidQuantityFormat(
|
|
1688
|
+
raw,
|
|
1689
|
+
"Arbitrary quantities must have a numerical value"
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1692
|
+
const value = parseQuantityInput(quantityMatch.groups.quantity);
|
|
1693
|
+
const unit = quantityMatch.groups.unit;
|
|
1694
|
+
if (!value || value.type === "fixed" && value.value.type === "text") {
|
|
1695
|
+
throw new InvalidQuantityFormat(
|
|
1696
|
+
raw,
|
|
1697
|
+
"Arbitrary quantities must have a numerical value"
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
const arbitrary = {
|
|
1701
|
+
quantity: value
|
|
1702
|
+
};
|
|
1703
|
+
if (unit) arbitrary.unit = unit;
|
|
1704
|
+
return arbitrary;
|
|
1705
|
+
}
|
|
1674
1706
|
function parseScalingMetaVar(content, varName) {
|
|
1675
|
-
const
|
|
1707
|
+
const complexMatch = content.match(scalingMetaValueWithUnitRegex(varName));
|
|
1708
|
+
if (complexMatch?.groups?.arbitraryQuantity) {
|
|
1709
|
+
const parsed = parseArbitraryQuantity(
|
|
1710
|
+
complexMatch.groups.arbitraryQuantity
|
|
1711
|
+
);
|
|
1712
|
+
const result2 = {
|
|
1713
|
+
quantity: parsed.quantity
|
|
1714
|
+
};
|
|
1715
|
+
if (parsed.unit) result2.unit = parsed.unit;
|
|
1716
|
+
if (complexMatch.groups.servingsPrefix) {
|
|
1717
|
+
result2.textBefore = complexMatch.groups.servingsPrefix;
|
|
1718
|
+
}
|
|
1719
|
+
if (complexMatch.groups.servingsSuffix) {
|
|
1720
|
+
result2.textAfter = complexMatch.groups.servingsSuffix;
|
|
1721
|
+
}
|
|
1722
|
+
return result2;
|
|
1723
|
+
}
|
|
1724
|
+
const varMatch = content.match(scalingSimpleMetaValueRegex(varName));
|
|
1676
1725
|
if (!varMatch) return void 0;
|
|
1677
1726
|
if (isNaN(Number(varMatch[2]?.trim()))) {
|
|
1678
1727
|
throw new Error("Scaling variables should be numbers");
|
|
1679
1728
|
}
|
|
1680
|
-
|
|
1729
|
+
const numericValue = Number(varMatch[2]?.trim());
|
|
1730
|
+
const result = {
|
|
1731
|
+
quantity: {
|
|
1732
|
+
type: "fixed",
|
|
1733
|
+
value: { type: "decimal", decimal: numericValue }
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
if (varMatch[3]) {
|
|
1737
|
+
result.text = `${varMatch[3].trim()}`;
|
|
1738
|
+
}
|
|
1739
|
+
return result;
|
|
1681
1740
|
}
|
|
1682
1741
|
function parseListMetaVar(content, varName) {
|
|
1683
1742
|
const listMatch = content.match(
|
|
@@ -1795,6 +1854,13 @@ function parseAnyMetaVar(content, varName) {
|
|
|
1795
1854
|
if (simple) return parseMetadataValue(simple);
|
|
1796
1855
|
return void 0;
|
|
1797
1856
|
}
|
|
1857
|
+
function getNumericValueFromMetaVar(v) {
|
|
1858
|
+
if (v.quantity.type === "fixed" && v.quantity.value.type !== "text") {
|
|
1859
|
+
return getNumericValue(v.quantity.value);
|
|
1860
|
+
}
|
|
1861
|
+
if (v.quantity.type === "range") return getNumericValue(v.quantity.min);
|
|
1862
|
+
return 0;
|
|
1863
|
+
}
|
|
1798
1864
|
function extractMetadata(content) {
|
|
1799
1865
|
const metadata = {};
|
|
1800
1866
|
let servings = void 0;
|
|
@@ -1919,9 +1985,9 @@ function extractMetadata(content) {
|
|
|
1919
1985
|
}
|
|
1920
1986
|
for (const metaVar of ["servings", "yield", "serves"]) {
|
|
1921
1987
|
const scalingMetaValue = parseScalingMetaVar(metadataContent, metaVar);
|
|
1922
|
-
if (scalingMetaValue
|
|
1923
|
-
metadata[metaVar] = scalingMetaValue
|
|
1924
|
-
servings = scalingMetaValue
|
|
1988
|
+
if (scalingMetaValue) {
|
|
1989
|
+
metadata[metaVar] = scalingMetaValue;
|
|
1990
|
+
servings = getNumericValueFromMetaVar(scalingMetaValue);
|
|
1925
1991
|
}
|
|
1926
1992
|
}
|
|
1927
1993
|
const tags = parseListMetaVar(metadataContent, "tags");
|
|
@@ -2748,27 +2814,17 @@ var _Recipe = class _Recipe {
|
|
|
2748
2814
|
*/
|
|
2749
2815
|
_parseArbitraryScalable(regexMatchGroups, intoArray) {
|
|
2750
2816
|
if (!regexMatchGroups || !regexMatchGroups.arbitraryQuantity) return;
|
|
2751
|
-
const
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
const arbitrary = {
|
|
2763
|
-
quantity: value
|
|
2764
|
-
};
|
|
2765
|
-
if (name) arbitrary.name = name;
|
|
2766
|
-
if (unit) arbitrary.unit = unit;
|
|
2767
|
-
intoArray.push({
|
|
2768
|
-
type: "arbitrary",
|
|
2769
|
-
index: this.arbitraries.push(arbitrary) - 1
|
|
2770
|
-
});
|
|
2771
|
-
}
|
|
2817
|
+
const parsed = parseArbitraryQuantity(regexMatchGroups.arbitraryQuantity);
|
|
2818
|
+
const name = regexMatchGroups.arbitraryName || void 0;
|
|
2819
|
+
const arbitrary = {
|
|
2820
|
+
quantity: parsed.quantity
|
|
2821
|
+
};
|
|
2822
|
+
if (name) arbitrary.name = name;
|
|
2823
|
+
if (parsed.unit) arbitrary.unit = parsed.unit;
|
|
2824
|
+
intoArray.push({
|
|
2825
|
+
type: "arbitrary",
|
|
2826
|
+
index: this.arbitraries.push(arbitrary) - 1
|
|
2827
|
+
});
|
|
2772
2828
|
}
|
|
2773
2829
|
/**
|
|
2774
2830
|
* Parses text for arbitrary scalables and returns NoteItem array.
|
|
@@ -3097,8 +3153,8 @@ var _Recipe = class _Recipe {
|
|
|
3097
3153
|
const isGrouped = "group" in item && item.group !== void 0;
|
|
3098
3154
|
const groupAlternatives = isGrouped ? this.choices.ingredientGroups.get(item.group) : void 0;
|
|
3099
3155
|
let selectedAltIndex = 0;
|
|
3100
|
-
let isSelected
|
|
3101
|
-
let hasExplicitChoice
|
|
3156
|
+
let isSelected;
|
|
3157
|
+
let hasExplicitChoice;
|
|
3102
3158
|
if (isGrouped) {
|
|
3103
3159
|
const groupChoice = choices?.ingredientGroups?.get(item.group);
|
|
3104
3160
|
hasExplicitChoice = groupChoice !== void 0;
|
|
@@ -3558,37 +3614,34 @@ var _Recipe = class _Recipe {
|
|
|
3558
3614
|
arbitrary.quantity,
|
|
3559
3615
|
factor
|
|
3560
3616
|
);
|
|
3617
|
+
const optimized = applyBestUnit(
|
|
3618
|
+
{ quantity: arbitrary.quantity, unit: arbitrary.unit },
|
|
3619
|
+
unitSystem
|
|
3620
|
+
);
|
|
3621
|
+
arbitrary.quantity = optimized.quantity;
|
|
3622
|
+
arbitrary.unit = optimized.unit;
|
|
3561
3623
|
}
|
|
3562
3624
|
newRecipe._populateIngredientQuantities();
|
|
3563
3625
|
newRecipe.servings = Big4(originalServings).times(factor).toNumber();
|
|
3564
|
-
|
|
3565
|
-
if (
|
|
3566
|
-
const
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
Big4(servingsValue).times(factor).toNumber()
|
|
3571
|
-
);
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
if (newRecipe.metadata.yield && this.metadata.yield) {
|
|
3575
|
-
if (floatRegex.test(String(this.metadata.yield).replace(",", ".").trim())) {
|
|
3576
|
-
const yieldValue = parseFloat(
|
|
3577
|
-
String(this.metadata.yield).replace(",", ".")
|
|
3626
|
+
for (const metaVar of ["servings", "yield", "serves"]) {
|
|
3627
|
+
if (newRecipe.metadata[metaVar] && this.metadata[metaVar]) {
|
|
3628
|
+
const original = this.metadata[metaVar];
|
|
3629
|
+
const scaledQuantity = multiplyQuantityValue(
|
|
3630
|
+
original.quantity,
|
|
3631
|
+
factor
|
|
3578
3632
|
);
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
}
|
|
3583
|
-
}
|
|
3584
|
-
if (newRecipe.metadata.serves && this.metadata.serves) {
|
|
3585
|
-
if (floatRegex.test(String(this.metadata.serves).replace(",", ".").trim())) {
|
|
3586
|
-
const servesValue = parseFloat(
|
|
3587
|
-
String(this.metadata.serves).replace(",", ".")
|
|
3588
|
-
);
|
|
3589
|
-
newRecipe.metadata.serves = String(
|
|
3590
|
-
Big4(servesValue).times(factor).toNumber()
|
|
3633
|
+
const optimized = applyBestUnit(
|
|
3634
|
+
{ quantity: scaledQuantity, unit: original.unit },
|
|
3635
|
+
unitSystem
|
|
3591
3636
|
);
|
|
3637
|
+
const scaled = {
|
|
3638
|
+
quantity: optimized.quantity
|
|
3639
|
+
};
|
|
3640
|
+
if (optimized.unit) scaled.unit = optimized.unit;
|
|
3641
|
+
if (original.textBefore) scaled.textBefore = original.textBefore;
|
|
3642
|
+
if (original.textAfter) scaled.textAfter = original.textAfter;
|
|
3643
|
+
if (original.text) scaled.text = original.text;
|
|
3644
|
+
newRecipe.metadata[metaVar] = scaled;
|
|
3592
3645
|
}
|
|
3593
3646
|
}
|
|
3594
3647
|
return newRecipe;
|
|
@@ -4671,6 +4724,7 @@ export {
|
|
|
4671
4724
|
// v8 ignore else -- @preserve
|
|
4672
4725
|
// v8 ignore if -- @preserve
|
|
4673
4726
|
/* v8 ignore else -- expliciting error type -- @preserve */
|
|
4727
|
+
/* v8 ignore next 4 -- @preserve: defensive guard; regex always matches */
|
|
4674
4728
|
// v8 ignore if -- @preserve: defensive type guard
|
|
4675
4729
|
/* v8 ignore if -- @preserve */
|
|
4676
4730
|
// v8 ignore next -- @preserve
|