Skip to content

Commit

Permalink
Add ignoreUOMs option
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeboone02 committed Jan 18, 2024
1 parent 01b89ad commit eead400
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 30 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

- N/A
### Added

- New option `ignoreUOMs`, an array of strings that will _not_ be considered units of measure.

## [v1.1.1] - 2024-01-15

Expand Down
61 changes: 35 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ In the browser, all exports including the `parseIngredient` function are availab
```html
<script src="https://unpkg.com/parse-ingredient"></script>
<script>
console.log(ParseIngredient.parseIngredient('1 1/2 cups sugar'));
ParseIngredient.parseIngredient('1 1/2 cups sugar');
// [
// {
// quantity: 1.5,
Expand All @@ -83,7 +83,7 @@ In the browser, all exports including the `parseIngredient` function are availab
```js
import { parseIngredient } from 'parse-ingredient';

console.log(parseIngredient('1-2 pears'));
parseIngredient('1-2 pears');
// [
// {
// quantity: 1,
Expand All @@ -94,11 +94,10 @@ console.log(parseIngredient('1-2 pears'));
// isGroupHeader: false,
// }
// ]
console.log(
parseIngredient(
`2/3 cup flour

parseIngredient(
`2/3 cup flour
1 tsp baking powder`
)
);
// [
// {
Expand All @@ -118,7 +117,7 @@ console.log(
// isGroupHeader: false,
// },
// ]
console.log(parseIngredient('For cake:'));
parseIngredient('For cake:');
// [
// {
// quantity: null,
Expand All @@ -129,7 +128,7 @@ console.log(parseIngredient('For cake:'));
// isGroupHeader: true,
// }
// ]
console.log(parseIngredient('Ripe tomato x2'));
parseIngredient('Ripe tomato x2');
// [
// {
// quantity: 2,
Expand All @@ -148,10 +147,8 @@ console.log(parseIngredient('Ripe tomato x2'));

Pass `true` to convert units of measure to their long, singular form, e.g. "ml" becomes "milliliter" and "cups" becomes "cup". This can help normalize the units of measure for processing. In most cases, this option will make `unitOfMeasure` equivalent to `unitOfMeasureID`.

Example:

```js
console.log(parseIngredient('1 c sugar', { normalizeUOM: true }));
parseIngredient('1 c sugar', { normalizeUOM: true });
// [
// {
// quantity: 1,
Expand All @@ -168,20 +165,16 @@ console.log(parseIngredient('1 c sugar', { normalizeUOM: true }));

Pass an object that matches the format of the exported `unitsOfMeasure` object. Keys that match any in the exported object will be used instead of the default, and any others will be added to the list of known units of measure when parsing ingredients.

Example:

```js
console.log(
parseIngredient('2 buckets of widgets', {
additionalUOMs: {
bucket: {
short: 'bkt',
plural: 'buckets',
versions: ['bk'],
},
parseIngredient('2 buckets of widgets', {
additionalUOMs: {
bucket: {
short: 'bkt',
plural: 'buckets',
versions: ['bk'],
},
})
);
},
});
// [
// {
// quantity: 2,
Expand All @@ -198,10 +191,8 @@ console.log(

When `true`, ingredient descriptions that start with "of " will not be modified. (By default, a leading "of " will be removed from all descriptions.)

Example:

```js
console.log(parseIngredient('1 cup of sugar', { allowLeadingOf: true }));
parseIngredient('1 cup of sugar', { allowLeadingOf: true });
// [
// {
// quantity: 1,
Expand All @@ -214,6 +205,24 @@ console.log(parseIngredient('1 cup of sugar', { allowLeadingOf: true }));
// ]
```

### `ignoreUOMs`

An array of strings to ignore as units of measure when parsing ingredients.

```js
parseIngredient('2 large eggs', { ignoreUOMs: ['large'] });
// [
// {
// quantity: 2,
// quantity2: null,
// unitOfMeasure: null,
// unitOfMeasureID: null,
// description: 'large eggs',
// isGroupHeader: false,
// }
// ]
```

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultOptions = {
additionalUOMs: {},
allowLeadingOf: false,
normalizeUOM: false,
ignoreUOMs: [],
} as const satisfies Required<ParseIngredientOptions>;

/**
Expand Down
11 changes: 8 additions & 3 deletions src/parseIngredient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ export const parseIngredient = (
// The first character is not numeric. First check for trailing quantity/uom.
const trailingQtyResult = trailingQuantityRegEx.exec(line);

if (trailingQtyResult) {
// Trailing quantity detected.
if (trailingQtyResult && opts.ignoreUOMs.includes(trailingQtyResult.at(-1) ?? '')) {
// Trailing quantity detected, but bailing out since the UOM should be ignored.
oIng.description = line;
} else if (trailingQtyResult) {
// Trailing quantity detected with missing or non-ignored UOM.
// Remove the quantity and unit of measure from the description.
oIng.description = line.replace(trailingQuantityRegEx, '').trim();

Expand Down Expand Up @@ -153,7 +156,9 @@ export const parseIngredient = (

while (++i < uomArrayLength && !uom) {
const { alternates, id, short, plural } = uomArray[i];
const versions = [...alternates, id, short, plural];
const versions = [...alternates, id, short, plural].filter(
unit => !opts.ignoreUOMs.includes(unit)
);
if (versions.includes(firstWord)) {
uom = firstWord;
uomID = id;
Expand Down
22 changes: 22 additions & 0 deletions src/parseIngredientTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,4 +526,26 @@ export const parseIngredientTests: Record<
},
],
],
'ignores units of measure': [
'1 cup stuff\nstuff x 2 cups',
[
{
quantity: 1,
quantity2: null,
unitOfMeasureID: null,
unitOfMeasure: null,
description: 'cup stuff',
isGroupHeader: false,
},
{
quantity: null,
quantity2: null,
unitOfMeasureID: null,
unitOfMeasure: null,
description: 'stuff x 2 cups',
isGroupHeader: false,
},
],
{ ignoreUOMs: ['cup', 'cups'] },
],
};
24 changes: 24 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,30 @@ export interface ParseIngredientOptions {
* @default {}
*/
additionalUOMs?: UnitOfMeasureDefinitions;
/**
* An array of strings to ignore as units of measure when parsing ingredients.
*
* @example
*
* ```ts
* parseIngredient('2 small eggs', {
* ignoreUOMs: ['small', 'medium', 'large']
* })
* // [
* // {
* // quantity: 2,
* // quantity2: null,
* // unitOfMeasure: null,
* // unitOfMeasureID: null,
* // description: 'small eggs',
* // isGroupHeader: false,
* // }
* // ]
* ```
*
* @default []
*/
ignoreUOMs?: string[];
/**
* If `true`, ingredient descriptions that start with "of " will not be
* modified. (By default, a leading "of " will be removed from all descriptions.)
Expand Down

0 comments on commit eead400

Please sign in to comment.