Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jakeboone02/parse-ingredient
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0
Choose a base ref
...
head repository: jakeboone02/parse-ingredient
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.1
Choose a head ref
  • 7 commits
  • 9 files changed
  • 1 contributor

Commits on Jun 19, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2657929 View commit details
  2. Update bun.lockb

    jakeboone02 committed Jun 19, 2023
    Copy the full SHA
    f7865dd View commit details

Commits on Jun 21, 2023

  1. Copy the full SHA
    f52524f View commit details
  2. Publish demo with Bun

    jakeboone02 committed Jun 21, 2023
    Copy the full SHA
    cd78f81 View commit details
  3. Copy the full SHA
    60ecd79 View commit details

Commits on Jul 26, 2023

  1. Update dependencies

    jakeboone02 committed Jul 26, 2023
    Copy the full SHA
    dae15f9 View commit details
  2. 1.0.1

    jakeboone02 committed Jul 26, 2023
    Copy the full SHA
    1da1874 View commit details
Showing with 58 additions and 67 deletions.
  1. +8 −1 CHANGELOG.md
  2. BIN bun.lockb
  3. +1 −1 ci/package.json
  4. +6 −7 demo/index.html
  5. +9 −9 package.json
  6. +1 −1 src/constants.ts
  7. +29 −44 src/parseIngredient.ts
  8. +1 −1 src/parseIngredientTests.ts
  9. +3 −3 src/utils.ts
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,7 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

- N/A
### Changed

- `compactArray` is now `compactStringArray` and only works for arrays of actual strings.

### Fixed

- Properly handles CRLF line endings.
- Minor performance improvements.

## [v1.0.0] - 2023-06-18

Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion ci/package.json
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
"build": "parcel build index.html"
},
"dependencies": {
"parse-ingredient": "0.6.0",
"parse-ingredient": "^1.0.0",
"parcel-bundler": "^1.12.5"
},
"devDependencies": {
13 changes: 6 additions & 7 deletions demo/index.html
Original file line number Diff line number Diff line change
@@ -156,19 +156,18 @@ <h4>Results</h4>
<script src="https://unpkg.com/parse-ingredient"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
<script>
const gBId = document.getElementById;
gBId('parse').addEventListener('click', () => {
const normalizeUOM = gBId('normalize-uom').checked;
const allowLeadingOf = gBId('allow-leading-of').checked;
gBId('results').innerHTML = JSON.stringify(
ParseIngredient.parseIngredient(gBId('ingredient-list').value, {
document.getElementById('parse').addEventListener('click', () => {
const normalizeUOM = document.getElementById('normalize-uom').checked;
const allowLeadingOf = document.getElementById('allow-leading-of').checked;
document.getElementById('results').innerHTML = JSON.stringify(
ParseIngredient.parseIngredient(document.getElementById('ingredient-list').value, {
normalizeUOM,
allowLeadingOf,
}),
null,
2
);
hljs.highlightBlock(gBId('results'));
hljs.highlightBlock(document.getElementById('results'));
});
</script>
</body>
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "parse-ingredient",
"author": "Jake Boone",
"version": "1.0.0",
"version": "1.0.1",
"license": "MIT",
"description": "Recipe ingredient parser with support for mixed numbers and vulgar fractions",
"files": [
@@ -44,19 +44,19 @@
"watch": "jest --watch",
"pretty-print": "prettier --write src *.{mjs,json,html,ts}",
"publish:npm": "np",
"publish:demo": "node gh-pages.publish.js"
"publish:demo": "bun ./gh-pages.publish.js"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"bun-types": "^0.6.9",
"@types/jest": "^29.5.3",
"bun-types": "^0.7.0",
"gh-pages": "^5.0.0",
"jest": "^29.5.0",
"jest": "^29.6.1",
"np": "^8.0.4",
"open": "^9.1.0",
"prettier": "^2.8.8",
"ts-jest": "^29.1.0",
"tsup": "^7.0.0",
"typescript": "^5.1.3"
"prettier": "^3.0.0",
"ts-jest": "^29.1.1",
"tsup": "^7.1.0",
"typescript": "^5.1.6"
},
"dependencies": {
"numeric-quantity": "2.0.0"
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ export const rangeSeparatorRegEx = new RegExp(
'i'
);

export const firstWordRegEx = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|\w+[-.]?)(.+)/;
export const firstWordRegEx = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|\w+[-.]?)(.+)?/;

export const ofs = ['of'] as const;
export const ofRegEx = new RegExp(`^(?:${ofs.join('|')})\\s+`, 'i');
73 changes: 29 additions & 44 deletions src/parseIngredient.ts
Original file line number Diff line number Diff line change
@@ -7,8 +7,12 @@ import {
rangeSeparatorRegEx,
unitsOfMeasure,
} from './constants';
import type { Ingredient, ParseIngredientOptions, UnitOfMeasureDefinitions } from './types';
import { compactArray } from './utils';
import type { Ingredient, ParseIngredientOptions, UnitOfMeasure } from './types';
import { compactStringArray } from './utils';

const newLineRegExp = /\r?\n/;

const addIdToUomDefinition = ([uom, def]: [string, UnitOfMeasure]) => ({ id: uom, ...def });

/**
* Parses a string into an array of recipe ingredient objects
@@ -21,16 +25,10 @@ export const parseIngredient = (
): Ingredient[] => {
const opts = { ...defaultOptions, ...options };
const mergedUOMs = { ...unitsOfMeasure, ...opts.additionalUOMs };
const uomArray = Object.entries(mergedUOMs).map(([uom, def]) => ({ id: uom, ...def }));
const uomArray = Object.entries(mergedUOMs).map(addIdToUomDefinition);
const uomArrayLength = uomArray.length;

const arrRaw = compactArray(
ingText
.replace(/\n{2,}/g, '\n')
.split('\n')
.map(ing => ing.trim())
);

const arrIngs = arrRaw.map(line => {
return compactStringArray(ingText.split(newLineRegExp)).map(line => {
const oIng: Ingredient = {
quantity: null,
quantity2: null,
@@ -76,23 +74,19 @@ export const parseIngredient = (
const q2reMatch = rangeSeparatorRegEx.exec(oIng.description);
if (q2reMatch) {
const q2reMatchLen = q2reMatch[1].length;
const nqResultFirstChar = numericQuantity(
oIng.description.substring(q2reMatchLen).trim().substring(0, 1)
);
const nqResultFirstChar = numericQuantity(oIng.description.substring(q2reMatchLen).trim()[0]);

if (!isNaN(nqResultFirstChar)) {
let lenNum = 6;
let lenNum = 7;
let nqResult = NaN;

while (lenNum > 0 && isNaN(nqResult)) {
while (--lenNum > 0 && isNaN(nqResult)) {
nqResult = numericQuantity(oIng.description.substring(q2reMatchLen, lenNum));

if (!isNaN(nqResult)) {
oIng.quantity2 = nqResult;
oIng.description = oIng.description.substring(lenNum).trim();
}

lenNum--;
}
}
}
@@ -102,33 +96,26 @@ export const parseIngredient = (

if (firstWordREMatches) {
const firstWord = firstWordREMatches[1].replace(/\s+/g, ' ');
const remainingDesc = firstWordREMatches[2];
let uom = '';
let uomID = '';
let i = 0;

while (i < uomArray.length && !uom) {
const versions = [
...uomArray[i].alternates,
uomArray[i].id,
uomArray[i].short,
uomArray[i].plural,
];
if (versions.includes(firstWord)) {
uom = firstWord;
uomID = uomArray[i].id;
const remainingDesc = (firstWordREMatches[2] ?? '').trim();
if (remainingDesc) {
let uom = '';
let uomID = '';
let i = -1;

while (++i < uomArrayLength && !uom) {
const { alternates, id, short, plural } = uomArray[i];
const versions = [...alternates, id, short, plural];
if (versions.includes(firstWord)) {
uom = firstWord;
uomID = id;
}
}
i++;
}

if (uom) {
oIng.unitOfMeasureID = uomID;
if (opts.normalizeUOM) {
oIng.unitOfMeasure = uomID;
} else {
oIng.unitOfMeasure = uom;
if (uom) {
oIng.unitOfMeasureID = uomID;
oIng.unitOfMeasure = opts.normalizeUOM ? uomID : uom;
oIng.description = remainingDesc;
}
oIng.description = remainingDesc.trim();
}
}

@@ -138,6 +125,4 @@ export const parseIngredient = (

return oIng;
});

return arrIngs;
};
2 changes: 1 addition & 1 deletion src/parseIngredientTests.ts
Original file line number Diff line number Diff line change
@@ -323,7 +323,7 @@ export const parseIngredientTests: Record<
],
],
'empty lines': [
'2/3 cup sugar\n\n 1 tsp baking powder',
'2/3 cup sugar\r\n \n 1 tsp baking powder',
[
{
quantity: 0.667,
6 changes: 3 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -3,14 +3,14 @@
*
* Originally from lodash: https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L6874
*/
export const compactArray = <T>(array: T[]) => {
export const compactStringArray = (array: string[]) => {
let index = -1;
const length = array.length;
let resIndex = 0;
const result: T[] = [];
const result: string[] = [];

while (++index < length) {
const value = array[index];
const value = array[index].trim();
// istanbul ignore else
if (value) {
result[resIndex++] = value;