diff --git a/src/index.test.ts b/src/index.test.ts index 6e63bd4..cc0d8e6 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,6 +1,7 @@ import parseIngredient from '.'; it('works', () => { + // Basic case expect(parseIngredient('1 cup stuff')).toEqual([ { quantity: 1, @@ -10,6 +11,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Fraction expect(parseIngredient('1/2 cup stuff')).toEqual([ { quantity: 0.5, @@ -19,6 +21,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Ranges expect(parseIngredient('1-2 cups stuff')).toEqual([ { quantity: 1, @@ -82,6 +85,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Invalid number for quantity 2 expect(parseIngredient('1-NaN cups stuff')).toEqual([ { quantity: 1, @@ -91,6 +95,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Normalize UOM expect(parseIngredient('1 c stuff', { normalizeUOM: true })).toEqual([ { quantity: 1, @@ -100,6 +105,17 @@ it('works', () => { isGroupHeader: false, }, ]); + // Missing description - parse UOM as description even if it matches + expect(parseIngredient('1 cup')).toEqual([ + { + quantity: 1, + quantity2: null, + unitOfMeasure: null, + description: 'cup', + isGroupHeader: false, + }, + ]); + // Group header ('For ') expect(parseIngredient('For cake')).toEqual([ { quantity: null, @@ -109,6 +125,7 @@ it('works', () => { isGroupHeader: true, }, ]); + // Group header ('xxx:') expect(parseIngredient('Icing:')).toEqual([ { quantity: null, @@ -118,6 +135,7 @@ it('works', () => { isGroupHeader: true, }, ]); + // No numeric part expect(parseIngredient('a bunch of bananas')).toEqual([ { quantity: null, @@ -127,6 +145,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Multi-line expect( parseIngredient(`2/3 cup sugar 1 tsp baking powder`) @@ -146,6 +165,7 @@ it('works', () => { isGroupHeader: false, }, ]); + // Empty lines expect( parseIngredient(`2/3 cup sugar diff --git a/src/index.ts b/src/index.ts index a2e0e0d..7b0c249 100644 --- a/src/index.ts +++ b/src/index.ts @@ -158,26 +158,32 @@ const parseIngredient = ( } // Check for a known unit of measure - const firstSpace = oIng.description.indexOf(' '); - const firstWord = oIng.description.substring(0, firstSpace); - let uom = ''; - let uomBase = ''; - let i = 0; - while (i < UOM_LIST.length && !uom) { - const ndx = UOM_LIST[i].indexOf(firstWord); - if (ndx >= 0) { - uom = UOM_LIST[i][ndx]; - uomBase = UOM_LIST[i][0]; + const firstWordRE = /^([a-zA-Z.]+)\b(.+)/; + const firstWordREMatches = firstWordRE.exec(oIng.description); + if (firstWordREMatches) { + const firstWord = firstWordREMatches[1]; + const remainingDesc = firstWordREMatches[2]; + let uom = ''; + let uomBase = ''; + let i = 0; + + while (i < UOM_LIST.length && !uom) { + const ndx = UOM_LIST[i].indexOf(firstWord); + if (ndx >= 0) { + uom = UOM_LIST[i][ndx]; + uomBase = UOM_LIST[i][0]; + } + i++; } - i++; - } - if (uom) { - if (options?.normalizeUOM) { - oIng.unitOfMeasure = uomBase; - } else { - oIng.unitOfMeasure = uom; + + if (uom) { + if (options?.normalizeUOM) { + oIng.unitOfMeasure = uomBase; + } else { + oIng.unitOfMeasure = uom; + } + oIng.description = remainingDesc.trim(); } - oIng.description = oIng.description.substring(firstSpace + 1); } return oIng;