Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

parse-ingredient

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

parse-ingredient - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

dist/constants.d.ts

62

dist/index.d.ts

@@ -1,59 +0,3 @@

export interface Ingredient {
/**
* The primary quantity (the lower quantity in a range, if applicable)
*/
quantity: number | null;
/**
* The secondary quantity (the upper quantity in a range, or `null` if not applicable)
*/
quantity2: number | null;
/**
* The unit of measure identifier
*/
unitOfMeasureID: string | null;
/**
* The unit of measure
*/
unitOfMeasure: string | null;
/**
* The description
*/
description: string;
/**
* Whether the "ingredient" is actually a group header, e.g. "For icing:"
*/
isGroupHeader: boolean;
}
export interface UnitOfMeasure {
short: string;
plural: string;
alternates: string[];
}
export declare type UnitOfMeasureDefinitions = Record<string, UnitOfMeasure>;
export interface ParseIngredientOptions {
/**
* Converts the unit of measure (`unitOfMeasure` property) of each
* ingredient to its long, singular form. For example, "ml" becomes
* "milliliter" and "cups" becomes "cup".
*/
normalizeUOM?: boolean;
/**
* An object that matches the format of `unitsOfMeasure`. Keys that
* match any in `unitsOfMeasure` will be used instead of the default,
* and any others will be added to the list of known units of measure
* when parsing ingredients.
*/
additionalUOMs?: UnitOfMeasureDefinitions;
/**
* If `true`, ingredient descriptions that start with "of " will not be
* modified. (By default, a leading "of " will be removed all descriptions.)
*/
allowLeadingOf?: boolean;
}
export declare const unitsOfMeasure: UnitOfMeasureDefinitions;
/**
* Parses a string into an array of recipe ingredient objects
* @param ingText The ingredient text
* @param options Configuration options
*/
export declare const parseIngredient: (ingText: string, options?: ParseIngredientOptions | undefined) => Ingredient[];
export * from './parseIngredient';
export * from './constants';
export * from './types';

@@ -1,4 +0,169 @@

"use strict";var N=Object.defineProperty;var b=Object.getOwnPropertySymbols;var M=Object.prototype.hasOwnProperty,O=Object.prototype.propertyIsEnumerable;var q=(r,t,s)=>t in r?N(r,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):r[t]=s,p=(r,t)=>{for(var s in t||(t={}))M.call(t,s)&&q(r,s,t[s]);if(b)for(var s of b(t))O.call(t,s)&&q(r,s,t[s]);return r};Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var v=require("numeric-quantity");function z(r){return r&&typeof r=="object"&&"default"in r?r:{default:r}}var d=z(v);const y={bag:{short:"bag",plural:"bags",alternates:[]},box:{short:"box",plural:"boxes",alternates:[]},bunch:{short:"bunch",plural:"bunches",alternates:[]},can:{short:"can",plural:"cans",alternates:[]},carton:{short:"carton",plural:"cartons",alternates:[]},centimeter:{short:"cm",plural:"centimeters",alternates:["cm."]},clove:{short:"clove",plural:"cloves",alternates:[]},container:{short:"container",plural:"containers",alternates:[]},cup:{short:"c",plural:"cups",alternates:["c.","C"]},dash:{short:"dash",plural:"dashes",alternates:[]},drop:{short:"drop",plural:"drops",alternates:[]},ear:{short:"ear",plural:"ears",alternates:[]},"fluid ounce":{short:"fl oz",plural:"fluid ounces",alternates:["fluidounce","floz","fl-oz","fluid-ounce","fluid-ounces","fluidounces","fl ounce","fl ounces","fl-ounce","fl-ounces","fluid oz","fluid-oz"]},foot:{short:"ft",plural:"feet",alternates:["ft."]},gallon:{short:"gal",plural:"gallons",alternates:["gal."]},gram:{short:"g",plural:"grams",alternates:["g."]},head:{short:"head",plural:"heads",alternates:[]},inch:{short:"in",plural:"inches",alternates:["in."]},kilogram:{short:"kg",plural:"kilograms",alternates:["kg."]},liter:{short:"l",plural:"liters",alternates:[]},meter:{short:"m",plural:"meters",alternates:["m."]},milligram:{short:"mg",plural:"milligrams",alternates:["mg."]},milliliter:{short:"ml",plural:"milliliters",alternates:["mL","ml.","mL."]},millimeter:{short:"mm",plural:"millimeters",alternates:["mm."]},ounce:{short:"oz",plural:"ounces",alternates:["oz."]},pack:{short:"pack",plural:"packs",alternates:[]},package:{short:"pkg",plural:"packages",alternates:["pkg.","pkgs"]},piece:{short:"piece",plural:"pieces",alternates:["pcs","pcs."]},pinch:{short:"pinch",plural:"pinches",alternates:[]},pint:{short:"pt",plural:"pints",alternates:["pt."]},pound:{short:"lb",plural:"pounds",alternates:["lb.","lbs","lbs."]},quart:{short:"qt",plural:"quarts",alternates:["qt.","qts","qts."]},sprig:{short:"sprig",plural:"sprigs",alternates:[]},stick:{short:"stick",plural:"sticks",alternates:[]},tablespoon:{short:"tbsp",plural:"tablespoons",alternates:["tbsp.","T"]},teaspoon:{short:"tsp",plural:"teaspoons",alternates:["tsp.","t"]},yard:{short:"yd",plural:"yards",alternates:["yd.","yds."]}},I=r=>{let t=-1;const s=r.length;let i=0;const h=[];for(;++t<s;){const f=r[t];f&&(h[i++]=f)}return h},R=(r,t)=>{const s=p(p({},y),t==null?void 0:t.additionalUOMs),i=Object.keys(s).map(l=>p({id:l},s[l]));return I(r.replace(/\n{2,}/g,`
`).split(`
`).map(l=>l.trim())).map(l=>{const e={quantity:null,quantity2:null,unitOfMeasureID:null,unitOfMeasure:null,description:"",isGroupHeader:!1},k=d.default(l.substring(0,1));if(isNaN(k))e.description=l,(/:$/.test(e.description)||/^For /i.test(e.description))&&(e.isGroupHeader=!0);else{let a=6,u=NaN;for(;a>0&&isNaN(u);)u=d.default(l.substring(0,a).trim()),u>-1&&(e.quantity=u,e.description=l.substring(a).trim()),a--}const g=/^(-|–|—|to )/i.exec(e.description);if(g){const a=g[1].length,u=d.default(e.description.substring(a).trim().substring(0,1));if(!isNaN(u)){let n=6,o=NaN;for(;n>0&&isNaN(o);)o=d.default(e.description.substring(a,n)),isNaN(o)||(e.quantity2=o,e.description=e.description.substring(n).trim()),n--}}const m=/^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|[a-zA-Z.]+)\b(.+)/.exec(e.description);if(m){const a=m[1].replace(/\s+/g," "),u=m[2];let n="",o="",c=0;for(;c<i.length&&!n;)[...i[c].alternates,i[c].id,i[c].short,i[c].plural].includes(a)&&(n=a,o=i[c].id),c++;n&&(e.unitOfMeasureID=o,t!=null&&t.normalizeUOM?e.unitOfMeasure=o:e.unitOfMeasure=n,e.description=u.trim())}return!(t!=null&&t.allowLeadingOf)&&e.description.match(/^of\s+/i)&&(e.description=e.description.replace(/^of\s+/i,"")),e})};exports.parseIngredient=R;exports.unitsOfMeasure=y;
"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const numericQuantity = require("numeric-quantity");
const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
const numericQuantity__default = /* @__PURE__ */ _interopDefaultLegacy(numericQuantity);
const fors = ["For"];
const forsRegEx = new RegExp(`^(?:${fors.join("|")})\\s`, "i");
const rangeSeparatorWords = ["or", "to"];
const rangeSeparatorRegEx = new RegExp(
`^(-|\u2013|\u2014|(?:${rangeSeparatorWords.join("|")})\\s)`,
"i"
);
const firstWordRegEx = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|\w+[-.]?)(.+)/;
const ofs = ["of"];
const ofRegEx = new RegExp(`^(?:${ofs.join("|")})\\s+`, "i");
const unitsOfMeasure = {
bag: { short: "bag", plural: "bags", alternates: [] },
box: { short: "box", plural: "boxes", alternates: [] },
bunch: { short: "bunch", plural: "bunches", alternates: [] },
can: { short: "can", plural: "cans", alternates: [] },
carton: { short: "carton", plural: "cartons", alternates: [] },
centimeter: { short: "cm", plural: "centimeters", alternates: ["cm."] },
clove: { short: "clove", plural: "cloves", alternates: [] },
container: { short: "container", plural: "containers", alternates: [] },
cup: { short: "c", plural: "cups", alternates: ["c.", "C"] },
dash: { short: "dash", plural: "dashes", alternates: [] },
drop: { short: "drop", plural: "drops", alternates: [] },
ear: { short: "ear", plural: "ears", alternates: [] },
"fluid ounce": { short: "fl oz", plural: "fluid ounces", alternates: ["fluidounce", "floz", "fl-oz", "fluid-ounce", "fluid-ounces", "fluidounces", "fl ounce", "fl ounces", "fl-ounce", "fl-ounces", "fluid oz", "fluid-oz"] },
foot: { short: "ft", plural: "feet", alternates: ["ft."] },
gallon: { short: "gal", plural: "gallons", alternates: ["gal."] },
gram: { short: "g", plural: "grams", alternates: ["g."] },
head: { short: "head", plural: "heads", alternates: [] },
inch: { short: "in", plural: "inches", alternates: ["in."] },
kilogram: { short: "kg", plural: "kilograms", alternates: ["kg."] },
large: { short: "lg", plural: "large", alternates: ["lg", "lg."] },
liter: { short: "l", plural: "liters", alternates: [] },
medium: { short: "md", plural: "medium", alternates: ["med", "med.", "md."] },
meter: { short: "m", plural: "meters", alternates: ["m."] },
milligram: { short: "mg", plural: "milligrams", alternates: ["mg."] },
milliliter: { short: "ml", plural: "milliliters", alternates: ["mL", "ml.", "mL."] },
millimeter: { short: "mm", plural: "millimeters", alternates: ["mm."] },
ounce: { short: "oz", plural: "ounces", alternates: ["oz."] },
pack: { short: "pack", plural: "packs", alternates: [] },
package: { short: "pkg", plural: "packages", alternates: ["pkg.", "pkgs"] },
piece: { short: "piece", plural: "pieces", alternates: ["pcs", "pcs."] },
pinch: { short: "pinch", plural: "pinches", alternates: [] },
pint: { short: "pt", plural: "pints", alternates: ["pt."] },
pound: { short: "lb", plural: "pounds", alternates: ["lb.", "lbs", "lbs."] },
quart: { short: "qt", plural: "quarts", alternates: ["qt.", "qts", "qts."] },
small: { short: "sm", plural: "small", alternates: ["sm."] },
sprig: { short: "sprig", plural: "sprigs", alternates: [] },
stick: { short: "stick", plural: "sticks", alternates: [] },
tablespoon: { short: "tbsp", plural: "tablespoons", alternates: ["tbsp.", "T", "Tbsp."] },
teaspoon: { short: "tsp", plural: "teaspoons", alternates: ["tsp.", "t"] },
yard: { short: "yd", plural: "yards", alternates: ["yd.", "yds."] }
};
const compactArray = (array) => {
let index = -1;
const length = array.length;
let resIndex = 0;
const result = [];
while (++index < length) {
const value = array[index];
if (value) {
result[resIndex++] = value;
}
}
return result;
};
const parseIngredient = (ingText, options) => {
const mergedUOMs = { ...unitsOfMeasure, ...options == null ? void 0 : options.additionalUOMs };
const uomArray = Object.keys(mergedUOMs).map((uom) => ({ id: uom, ...mergedUOMs[uom] }));
const arrRaw = compactArray(
ingText.replace(/\n{2,}/g, "\n").split("\n").map((ing) => ing.trim())
);
const arrIngs = arrRaw.map((line) => {
const oIng = {
quantity: null,
quantity2: null,
unitOfMeasureID: null,
unitOfMeasure: null,
description: "",
isGroupHeader: false
};
const nqResultFirstChar = numericQuantity__default.default(line.substring(0, 1));
if (isNaN(nqResultFirstChar)) {
oIng.description = line;
if (/:$/.test(oIng.description) || forsRegEx.test(oIng.description)) {
oIng.isGroupHeader = true;
}
} else {
let lenNum = 6;
let nqResult = NaN;
while (lenNum > 0 && isNaN(nqResult)) {
nqResult = numericQuantity__default.default(line.substring(0, lenNum).trim());
if (nqResult > -1) {
oIng.quantity = nqResult;
oIng.description = line.substring(lenNum).trim();
}
lenNum--;
}
}
const q2reMatch = rangeSeparatorRegEx.exec(oIng.description);
if (q2reMatch) {
const q2reMatchLen = q2reMatch[1].length;
const nqResultFirstChar2 = numericQuantity__default.default(
oIng.description.substring(q2reMatchLen).trim().substring(0, 1)
);
if (!isNaN(nqResultFirstChar2)) {
let lenNum = 6;
let nqResult = NaN;
while (lenNum > 0 && isNaN(nqResult)) {
nqResult = numericQuantity__default.default(oIng.description.substring(q2reMatchLen, lenNum));
if (!isNaN(nqResult)) {
oIng.quantity2 = nqResult;
oIng.description = oIng.description.substring(lenNum).trim();
}
lenNum--;
}
}
}
const firstWordREMatches = firstWordRegEx.exec(oIng.description);
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;
}
i++;
}
if (uom) {
oIng.unitOfMeasureID = uomID;
if (options == null ? void 0 : options.normalizeUOM) {
oIng.unitOfMeasure = uomID;
} else {
oIng.unitOfMeasure = uom;
}
oIng.description = remainingDesc.trim();
}
}
if (!(options == null ? void 0 : options.allowLeadingOf) && oIng.description.match(ofRegEx)) {
oIng.description = oIng.description.replace(ofRegEx, "");
}
return oIng;
});
return arrIngs;
};
exports.firstWordRegEx = firstWordRegEx;
exports.fors = fors;
exports.forsRegEx = forsRegEx;
exports.ofRegEx = ofRegEx;
exports.ofs = ofs;
exports.parseIngredient = parseIngredient;
exports.rangeSeparatorRegEx = rangeSeparatorRegEx;
exports.rangeSeparatorWords = rangeSeparatorWords;
exports.unitsOfMeasure = unitsOfMeasure;
//# sourceMappingURL=parse-ingredient.cjs.js.map

@@ -1,18 +0,12 @@

var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
import numericQuantity from "numeric-quantity";
const fors = ["For"];
const forsRegEx = new RegExp(`^(?:${fors.join("|")})\\s`, "i");
const rangeSeparatorWords = ["or", "to"];
const rangeSeparatorRegEx = new RegExp(
`^(-|\u2013|\u2014|(?:${rangeSeparatorWords.join("|")})\\s)`,
"i"
);
const firstWordRegEx = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|\w+[-.]?)(.+)/;
const ofs = ["of"];
const ofRegEx = new RegExp(`^(?:${ofs.join("|")})\\s+`, "i");
const unitsOfMeasure = {

@@ -38,3 +32,5 @@ bag: { short: "bag", plural: "bags", alternates: [] },

kilogram: { short: "kg", plural: "kilograms", alternates: ["kg."] },
large: { short: "lg", plural: "large", alternates: ["lg", "lg."] },
liter: { short: "l", plural: "liters", alternates: [] },
medium: { short: "md", plural: "medium", alternates: ["med", "med.", "md."] },
meter: { short: "m", plural: "meters", alternates: ["m."] },

@@ -52,5 +48,6 @@ milligram: { short: "mg", plural: "milligrams", alternates: ["mg."] },

quart: { short: "qt", plural: "quarts", alternates: ["qt.", "qts", "qts."] },
small: { short: "sm", plural: "small", alternates: ["sm."] },
sprig: { short: "sprig", plural: "sprigs", alternates: [] },
stick: { short: "stick", plural: "sticks", alternates: [] },
tablespoon: { short: "tbsp", plural: "tablespoons", alternates: ["tbsp.", "T"] },
tablespoon: { short: "tbsp", plural: "tablespoons", alternates: ["tbsp.", "T", "Tbsp."] },
teaspoon: { short: "tsp", plural: "teaspoons", alternates: ["tsp.", "t"] },

@@ -73,7 +70,7 @@ yard: { short: "yd", plural: "yards", alternates: ["yd.", "yds."] }

const parseIngredient = (ingText, options) => {
const mergedUOMs = __spreadValues(__spreadValues({}, unitsOfMeasure), options == null ? void 0 : options.additionalUOMs);
const uomArray = Object.keys(mergedUOMs).map((uom) => __spreadValues({
id: uom
}, mergedUOMs[uom]));
const arrRaw = compactArray(ingText.replace(/\n{2,}/g, "\n").split("\n").map((ing) => ing.trim()));
const mergedUOMs = { ...unitsOfMeasure, ...options == null ? void 0 : options.additionalUOMs };
const uomArray = Object.keys(mergedUOMs).map((uom) => ({ id: uom, ...mergedUOMs[uom] }));
const arrRaw = compactArray(
ingText.replace(/\n{2,}/g, "\n").split("\n").map((ing) => ing.trim())
);
const arrIngs = arrRaw.map((line) => {

@@ -91,3 +88,3 @@ const oIng = {

oIng.description = line;
if (/:$/.test(oIng.description) || /^For /i.test(oIng.description)) {
if (/:$/.test(oIng.description) || forsRegEx.test(oIng.description)) {
oIng.isGroupHeader = true;

@@ -107,7 +104,8 @@ }

}
const q2re = /^(-|–|—|to )/i;
const q2reMatch = q2re.exec(oIng.description);
const q2reMatch = rangeSeparatorRegEx.exec(oIng.description);
if (q2reMatch) {
const q2reMatchLen = q2reMatch[1].length;
const nqResultFirstChar2 = numericQuantity(oIng.description.substring(q2reMatchLen).trim().substring(0, 1));
const nqResultFirstChar2 = numericQuantity(
oIng.description.substring(q2reMatchLen).trim().substring(0, 1)
);
if (!isNaN(nqResultFirstChar2)) {

@@ -126,4 +124,3 @@ let lenNum = 6;

}
const firstWordRE = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|[a-zA-Z.]+)\b(.+)/;
const firstWordREMatches = firstWordRE.exec(oIng.description);
const firstWordREMatches = firstWordRegEx.exec(oIng.description);
if (firstWordREMatches) {

@@ -158,4 +155,4 @@ const firstWord = firstWordREMatches[1].replace(/\s+/g, " ");

}
if (!(options == null ? void 0 : options.allowLeadingOf) && oIng.description.match(/^of\s+/i)) {
oIng.description = oIng.description.replace(/^of\s+/i, "");
if (!(options == null ? void 0 : options.allowLeadingOf) && oIng.description.match(ofRegEx)) {
oIng.description = oIng.description.replace(ofRegEx, "");
}

@@ -166,3 +163,13 @@ return oIng;

};
export { parseIngredient, unitsOfMeasure };
export {
firstWordRegEx,
fors,
forsRegEx,
ofRegEx,
ofs,
parseIngredient,
rangeSeparatorRegEx,
rangeSeparatorWords,
unitsOfMeasure
};
//# sourceMappingURL=parse-ingredient.es.js.map

@@ -1,4 +0,172 @@

var v=Object.defineProperty;var N=Object.getOwnPropertySymbols;var R=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var M=(t,r,s)=>r in t?v(t,r,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[r]=s,m=(t,r)=>{for(var s in r||(r={}))R.call(r,s)&&M(t,s,r[s]);if(N)for(var s of N(r))x.call(r,s)&&M(t,s,r[s]);return t};(function(t,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("numeric-quantity")):typeof define=="function"&&define.amd?define(["exports","numeric-quantity"],r):(t=typeof globalThis!="undefined"?globalThis:t||self,r(t.ParseIngredient={},t.numericQuantity))})(this,function(t,r){"use strict";function s(l){return l&&typeof l=="object"&&"default"in l?l:{default:l}}var f=s(r);const y={bag:{short:"bag",plural:"bags",alternates:[]},box:{short:"box",plural:"boxes",alternates:[]},bunch:{short:"bunch",plural:"bunches",alternates:[]},can:{short:"can",plural:"cans",alternates:[]},carton:{short:"carton",plural:"cartons",alternates:[]},centimeter:{short:"cm",plural:"centimeters",alternates:["cm."]},clove:{short:"clove",plural:"cloves",alternates:[]},container:{short:"container",plural:"containers",alternates:[]},cup:{short:"c",plural:"cups",alternates:["c.","C"]},dash:{short:"dash",plural:"dashes",alternates:[]},drop:{short:"drop",plural:"drops",alternates:[]},ear:{short:"ear",plural:"ears",alternates:[]},"fluid ounce":{short:"fl oz",plural:"fluid ounces",alternates:["fluidounce","floz","fl-oz","fluid-ounce","fluid-ounces","fluidounces","fl ounce","fl ounces","fl-ounce","fl-ounces","fluid oz","fluid-oz"]},foot:{short:"ft",plural:"feet",alternates:["ft."]},gallon:{short:"gal",plural:"gallons",alternates:["gal."]},gram:{short:"g",plural:"grams",alternates:["g."]},head:{short:"head",plural:"heads",alternates:[]},inch:{short:"in",plural:"inches",alternates:["in."]},kilogram:{short:"kg",plural:"kilograms",alternates:["kg."]},liter:{short:"l",plural:"liters",alternates:[]},meter:{short:"m",plural:"meters",alternates:["m."]},milligram:{short:"mg",plural:"milligrams",alternates:["mg."]},milliliter:{short:"ml",plural:"milliliters",alternates:["mL","ml.","mL."]},millimeter:{short:"mm",plural:"millimeters",alternates:["mm."]},ounce:{short:"oz",plural:"ounces",alternates:["oz."]},pack:{short:"pack",plural:"packs",alternates:[]},package:{short:"pkg",plural:"packages",alternates:["pkg.","pkgs"]},piece:{short:"piece",plural:"pieces",alternates:["pcs","pcs."]},pinch:{short:"pinch",plural:"pinches",alternates:[]},pint:{short:"pt",plural:"pints",alternates:["pt."]},pound:{short:"lb",plural:"pounds",alternates:["lb.","lbs","lbs."]},quart:{short:"qt",plural:"quarts",alternates:["qt.","qts","qts."]},sprig:{short:"sprig",plural:"sprigs",alternates:[]},stick:{short:"stick",plural:"sticks",alternates:[]},tablespoon:{short:"tbsp",plural:"tablespoons",alternates:["tbsp.","T"]},teaspoon:{short:"tsp",plural:"teaspoons",alternates:["tsp.","t"]},yard:{short:"yd",plural:"yards",alternates:["yd.","yds."]}},O=l=>{let a=-1;const h=l.length;let o=0;const g=[];for(;++a<h;){const b=l[a];b&&(g[o++]=b)}return g},z=(l,a)=>{const h=m(m({},y),a==null?void 0:a.additionalUOMs),o=Object.keys(h).map(i=>m({id:i},h[i]));return O(l.replace(/\n{2,}/g,`
`).split(`
`).map(i=>i.trim())).map(i=>{const e={quantity:null,quantity2:null,unitOfMeasureID:null,unitOfMeasure:null,description:"",isGroupHeader:!1},I=f.default(i.substring(0,1));if(isNaN(I))e.description=i,(/:$/.test(e.description)||/^For /i.test(e.description))&&(e.isGroupHeader=!0);else{let n=6,c=NaN;for(;n>0&&isNaN(c);)c=f.default(i.substring(0,n).trim()),c>-1&&(e.quantity=c,e.description=i.substring(n).trim()),n--}const k=/^(-|–|—|to )/i.exec(e.description);if(k){const n=k[1].length,c=f.default(e.description.substring(n).trim().substring(0,1));if(!isNaN(c)){let u=6,p=NaN;for(;u>0&&isNaN(p);)p=f.default(e.description.substring(n,u)),isNaN(p)||(e.quantity2=p,e.description=e.description.substring(u).trim()),u--}}const q=/^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|[a-zA-Z.]+)\b(.+)/.exec(e.description);if(q){const n=q[1].replace(/\s+/g," "),c=q[2];let u="",p="",d=0;for(;d<o.length&&!u;)[...o[d].alternates,o[d].id,o[d].short,o[d].plural].includes(n)&&(u=n,p=o[d].id),d++;u&&(e.unitOfMeasureID=p,a!=null&&a.normalizeUOM?e.unitOfMeasure=p:e.unitOfMeasure=u,e.description=c.trim())}return!(a!=null&&a.allowLeadingOf)&&e.description.match(/^of\s+/i)&&(e.description=e.description.replace(/^of\s+/i,"")),e})};t.parseIngredient=z,t.unitsOfMeasure=y,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("numeric-quantity")) : typeof define === "function" && define.amd ? define(["exports", "numeric-quantity"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.ParseIngredient = {}, global.numericQuantity));
})(this, function(exports2, numericQuantity) {
"use strict";
const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
const numericQuantity__default = /* @__PURE__ */ _interopDefaultLegacy(numericQuantity);
const fors = ["For"];
const forsRegEx = new RegExp(`^(?:${fors.join("|")})\\s`, "i");
const rangeSeparatorWords = ["or", "to"];
const rangeSeparatorRegEx = new RegExp(
`^(-|\u2013|\u2014|(?:${rangeSeparatorWords.join("|")})\\s)`,
"i"
);
const firstWordRegEx = /^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|\w+[-.]?)(.+)/;
const ofs = ["of"];
const ofRegEx = new RegExp(`^(?:${ofs.join("|")})\\s+`, "i");
const unitsOfMeasure = {
bag: { short: "bag", plural: "bags", alternates: [] },
box: { short: "box", plural: "boxes", alternates: [] },
bunch: { short: "bunch", plural: "bunches", alternates: [] },
can: { short: "can", plural: "cans", alternates: [] },
carton: { short: "carton", plural: "cartons", alternates: [] },
centimeter: { short: "cm", plural: "centimeters", alternates: ["cm."] },
clove: { short: "clove", plural: "cloves", alternates: [] },
container: { short: "container", plural: "containers", alternates: [] },
cup: { short: "c", plural: "cups", alternates: ["c.", "C"] },
dash: { short: "dash", plural: "dashes", alternates: [] },
drop: { short: "drop", plural: "drops", alternates: [] },
ear: { short: "ear", plural: "ears", alternates: [] },
"fluid ounce": { short: "fl oz", plural: "fluid ounces", alternates: ["fluidounce", "floz", "fl-oz", "fluid-ounce", "fluid-ounces", "fluidounces", "fl ounce", "fl ounces", "fl-ounce", "fl-ounces", "fluid oz", "fluid-oz"] },
foot: { short: "ft", plural: "feet", alternates: ["ft."] },
gallon: { short: "gal", plural: "gallons", alternates: ["gal."] },
gram: { short: "g", plural: "grams", alternates: ["g."] },
head: { short: "head", plural: "heads", alternates: [] },
inch: { short: "in", plural: "inches", alternates: ["in."] },
kilogram: { short: "kg", plural: "kilograms", alternates: ["kg."] },
large: { short: "lg", plural: "large", alternates: ["lg", "lg."] },
liter: { short: "l", plural: "liters", alternates: [] },
medium: { short: "md", plural: "medium", alternates: ["med", "med.", "md."] },
meter: { short: "m", plural: "meters", alternates: ["m."] },
milligram: { short: "mg", plural: "milligrams", alternates: ["mg."] },
milliliter: { short: "ml", plural: "milliliters", alternates: ["mL", "ml.", "mL."] },
millimeter: { short: "mm", plural: "millimeters", alternates: ["mm."] },
ounce: { short: "oz", plural: "ounces", alternates: ["oz."] },
pack: { short: "pack", plural: "packs", alternates: [] },
package: { short: "pkg", plural: "packages", alternates: ["pkg.", "pkgs"] },
piece: { short: "piece", plural: "pieces", alternates: ["pcs", "pcs."] },
pinch: { short: "pinch", plural: "pinches", alternates: [] },
pint: { short: "pt", plural: "pints", alternates: ["pt."] },
pound: { short: "lb", plural: "pounds", alternates: ["lb.", "lbs", "lbs."] },
quart: { short: "qt", plural: "quarts", alternates: ["qt.", "qts", "qts."] },
small: { short: "sm", plural: "small", alternates: ["sm."] },
sprig: { short: "sprig", plural: "sprigs", alternates: [] },
stick: { short: "stick", plural: "sticks", alternates: [] },
tablespoon: { short: "tbsp", plural: "tablespoons", alternates: ["tbsp.", "T", "Tbsp."] },
teaspoon: { short: "tsp", plural: "teaspoons", alternates: ["tsp.", "t"] },
yard: { short: "yd", plural: "yards", alternates: ["yd.", "yds."] }
};
const compactArray = (array) => {
let index = -1;
const length = array.length;
let resIndex = 0;
const result = [];
while (++index < length) {
const value = array[index];
if (value) {
result[resIndex++] = value;
}
}
return result;
};
const parseIngredient = (ingText, options) => {
const mergedUOMs = { ...unitsOfMeasure, ...options == null ? void 0 : options.additionalUOMs };
const uomArray = Object.keys(mergedUOMs).map((uom) => ({ id: uom, ...mergedUOMs[uom] }));
const arrRaw = compactArray(
ingText.replace(/\n{2,}/g, "\n").split("\n").map((ing) => ing.trim())
);
const arrIngs = arrRaw.map((line) => {
const oIng = {
quantity: null,
quantity2: null,
unitOfMeasureID: null,
unitOfMeasure: null,
description: "",
isGroupHeader: false
};
const nqResultFirstChar = numericQuantity__default.default(line.substring(0, 1));
if (isNaN(nqResultFirstChar)) {
oIng.description = line;
if (/:$/.test(oIng.description) || forsRegEx.test(oIng.description)) {
oIng.isGroupHeader = true;
}
} else {
let lenNum = 6;
let nqResult = NaN;
while (lenNum > 0 && isNaN(nqResult)) {
nqResult = numericQuantity__default.default(line.substring(0, lenNum).trim());
if (nqResult > -1) {
oIng.quantity = nqResult;
oIng.description = line.substring(lenNum).trim();
}
lenNum--;
}
}
const q2reMatch = rangeSeparatorRegEx.exec(oIng.description);
if (q2reMatch) {
const q2reMatchLen = q2reMatch[1].length;
const nqResultFirstChar2 = numericQuantity__default.default(
oIng.description.substring(q2reMatchLen).trim().substring(0, 1)
);
if (!isNaN(nqResultFirstChar2)) {
let lenNum = 6;
let nqResult = NaN;
while (lenNum > 0 && isNaN(nqResult)) {
nqResult = numericQuantity__default.default(oIng.description.substring(q2reMatchLen, lenNum));
if (!isNaN(nqResult)) {
oIng.quantity2 = nqResult;
oIng.description = oIng.description.substring(lenNum).trim();
}
lenNum--;
}
}
}
const firstWordREMatches = firstWordRegEx.exec(oIng.description);
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;
}
i++;
}
if (uom) {
oIng.unitOfMeasureID = uomID;
if (options == null ? void 0 : options.normalizeUOM) {
oIng.unitOfMeasure = uomID;
} else {
oIng.unitOfMeasure = uom;
}
oIng.description = remainingDesc.trim();
}
}
if (!(options == null ? void 0 : options.allowLeadingOf) && oIng.description.match(ofRegEx)) {
oIng.description = oIng.description.replace(ofRegEx, "");
}
return oIng;
});
return arrIngs;
};
exports2.firstWordRegEx = firstWordRegEx;
exports2.fors = fors;
exports2.forsRegEx = forsRegEx;
exports2.ofRegEx = ofRegEx;
exports2.ofs = ofs;
exports2.parseIngredient = parseIngredient;
exports2.rangeSeparatorRegEx = rangeSeparatorRegEx;
exports2.rangeSeparatorWords = rangeSeparatorWords;
exports2.unitsOfMeasure = unitsOfMeasure;
Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
});
//# sourceMappingURL=parse-ingredient.umd.js.map
{
"name": "parse-ingredient",
"author": "Jake Boone",
"version": "0.5.0",
"version": "0.6.0",
"license": "MIT",

@@ -36,2 +36,3 @@ "description": "Recipe ingredient parser with support for mixed numbers and vulgar fractions",

"test": "jest --coverage",
"pretty-print": "prettier --write src",
"publish:npm": "np",

@@ -42,16 +43,17 @@ "publish:demo": "node gh-pages.publish.js",

"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@types/jest": "^27.4.1",
"gh-pages": "^3.1.0",
"jest": "^27.5.1",
"np": "^7.3.0",
"prettier": "^2.6.0",
"typescript": "^4.1.5",
"vite": "^2.8.6"
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.4",
"@babel/preset-typescript": "^7.18.6",
"@types/jest": "^29.1.2",
"gh-pages": "^4.0.0",
"jest": "^29.2.0",
"np": "^7.6.2",
"prettier": "^2.7.1",
"typescript": "^4.8.4",
"vite": "^3.1.8"
},
"dependencies": {
"numeric-quantity": "^1.0.2"
}
"numeric-quantity": "^1.0.4"
},
"packageManager": "yarn@3.2.3"
}

@@ -42,3 +42,3 @@ # parse-ingredient

This library pairs nicely with [format-quantity](https://www.npmjs.com/package/format-quantity) which can display numeric values as imperial measurements (e.g. `'1 1/2'` instead of `1.5`).
For a complimentary library that handles the inverse operation, displaying numeric values as imperial measurements (e.g. `'1 1/2'` instead of `1.5`), see [format-quantity](https://www.npmjs.com/package/format-quantity).

@@ -65,3 +65,3 @@ If present (i.e. not `null`), the `unitOfMeasureID` property corresponds to a key from the exported `unitsOfMeasure` object which defines short, plural, and other alternate versions of known units of measure. To extend the list of units, use the [`additionalUOMs` option](#additionaluoms) and/or or submit a [pull request](https://github.com/jakeboone02/parse-ingredient/pulls) to add new units to this library's default list.

In the browser, available as a global function `parseIngredient`. Remember to first include `numeric-quantity`.
In the browser, all exports including the `parseIngredient` function are available on the global object `ParseIngredient`. (Remember to first include `numeric-quantity`.)

@@ -210,1 +210,11 @@ ```html

```
## Other exports
| Name | Type | Description |
| -------------------------- | ----------- | ------------------------------------------------------------------------------------- |
| `unitsOfMeasure` | `object` | Information about natively-supported units of measure (see `UnitOfMeasure` interface) |
| `ParseIngredientOptions` | `interface` | Shape of the second parameter to the `parseIngredient` function |
| `Ingredient` | `interface` | Interface describing the shape of each element in the returned ingredient array |
| `UnitOfMeasure` | `interface` | Interface including short, plural, and alternate forms of a unit of measure |
| `UnitOfMeasureDefinitions` | `type` | Object with keys representing a `unitOfMeasureID` and values of type `UnitOfMeasure` |

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc