UNPKG

parse-ingredient

Version:

Recipe ingredient parser with support for mixed numbers and vulgar fractions

1 lines 20.3 kB
{"version":3,"sources":["../src/parseIngredient.ts","../src/constants.ts"],"sourcesContent":["import { numericQuantity } from 'numeric-quantity';\nimport {\n defaultOptions,\n firstWordRegEx,\n forsRegEx,\n fromRegEx,\n ofRegEx,\n rangeSeparatorRegEx,\n trailingQuantityRegEx,\n unitsOfMeasure,\n} from './constants';\nimport type { Ingredient, ParseIngredientOptions, UnitOfMeasure } from './types';\n\nconst newLineRegExp = /\\r?\\n/;\n\nconst addIdToUomDefinition = ([uom, def]: [string, UnitOfMeasure]) => ({ id: uom, ...def });\n\n/**\n * Parses a string into an array of recipe ingredient objects\n */\nexport const parseIngredient = (\n /**\n * The ingredient list, as plain text.\n */\n ingredientText: string,\n /**\n * Configuration options. Defaults to {@link defaultOptions}.\n */\n options: ParseIngredientOptions = defaultOptions\n): Ingredient[] => {\n const opts = { ...defaultOptions, ...options };\n const mergedUOMs = { ...unitsOfMeasure, ...opts.additionalUOMs };\n const uomArray = Object.entries(mergedUOMs).map(addIdToUomDefinition);\n const uomArrayLength = uomArray.length;\n\n const ingredientArray = ingredientText\n .split(newLineRegExp)\n .map(line => line.trim())\n .filter(Boolean);\n\n return ingredientArray.map(line => {\n const oIng: Ingredient = {\n quantity: null,\n quantity2: null,\n unitOfMeasureID: null,\n unitOfMeasure: null,\n description: '',\n isGroupHeader: false,\n };\n\n // Check if the first character is numeric.\n if (isNaN(numericQuantity(line[0]))) {\n // The first character is not numeric. First check for trailing quantity/uom.\n const trailingQtyResult = trailingQuantityRegEx.exec(line);\n\n if (trailingQtyResult && opts.ignoreUOMs.includes(trailingQtyResult.at(-1) ?? '')) {\n // Trailing quantity detected, but bailing out since the UOM should be ignored.\n oIng.description = line;\n } else if (trailingQtyResult) {\n // Trailing quantity detected with missing or non-ignored UOM.\n // Remove the quantity and unit of measure from the description.\n oIng.description = line.replace(trailingQuantityRegEx, '').trim();\n\n // Trailing quantity/range.\n const firstQty = trailingQtyResult[3];\n const secondQty = trailingQtyResult[12];\n if (!firstQty) {\n oIng.quantity = numericQuantity(secondQty);\n } else {\n oIng.quantity = numericQuantity(firstQty);\n oIng.quantity2 = numericQuantity(secondQty);\n }\n\n // Trailing unit of measure.\n const uomRaw = trailingQtyResult.at(-1);\n if (uomRaw) {\n let uom = '';\n let uomID = '';\n let i = -1;\n\n while (++i < uomArrayLength && !uom) {\n const { alternates, id, short, plural } = uomArray[i];\n const versions = [...alternates, id, short, plural];\n if (versions.includes(uomRaw)) {\n uom = uomRaw;\n uomID = id;\n }\n }\n\n if (uom) {\n oIng.unitOfMeasureID = uomID;\n oIng.unitOfMeasure = opts.normalizeUOM ? uomID : uom;\n } else if (oIng.description.match(fromRegEx)) {\n oIng.description += ` ${uomRaw}`;\n }\n }\n } else {\n // The first character is not numeric, and no trailing quantity was detected,\n // so the entire line is the description.\n oIng.description = line;\n\n // If the line ends with \":\" or starts with \"For \", then it is assumed to be a group header.\n if (oIng.description.endsWith(':') || forsRegEx.test(oIng.description)) {\n oIng.isGroupHeader = true;\n }\n }\n } else {\n // The first character is numeric. See how many of the first seven\n // constitute a single value. This will be `quantity`.\n let lenNum = 6;\n let nqResult = NaN;\n\n while (lenNum > 0 && isNaN(nqResult)) {\n nqResult = numericQuantity(line.substring(0, lenNum).trim());\n\n if (nqResult > -1) {\n oIng.quantity = nqResult;\n oIng.description = line.substring(lenNum).trim();\n }\n\n lenNum--;\n }\n }\n\n // Now check the description for a `quantity2` at the beginning.\n // First we look for a dash, emdash, endash, \"to \", or \"or \" to\n // indicate a range, then process the next seven characters just\n // like we did for `quantity`.\n const q2reMatch = rangeSeparatorRegEx.exec(oIng.description);\n if (q2reMatch) {\n const q2reMatchLen = q2reMatch[1].length;\n const nqResultFirstChar = numericQuantity(oIng.description.substring(q2reMatchLen).trim()[0]);\n\n if (!isNaN(nqResultFirstChar)) {\n let lenNum = 7;\n let nqResult = NaN;\n\n while (--lenNum > 0 && isNaN(nqResult)) {\n nqResult = numericQuantity(oIng.description.substring(q2reMatchLen, lenNum));\n\n if (!isNaN(nqResult)) {\n oIng.quantity2 = nqResult;\n oIng.description = oIng.description.substring(lenNum).trim();\n }\n }\n }\n }\n\n // Check for a known unit of measure\n const firstWordREMatches = firstWordRegEx.exec(oIng.description);\n\n if (firstWordREMatches) {\n const firstWord = firstWordREMatches[1].replace(/\\s+/g, ' ');\n const remainingDesc = (firstWordREMatches[2] ?? '').trim();\n if (remainingDesc) {\n let uom = '';\n let uomID = '';\n let i = -1;\n\n while (++i < uomArrayLength && !uom) {\n const { alternates, id, short, plural } = uomArray[i];\n const versions = [...alternates, id, short, plural].filter(\n unit => !opts.ignoreUOMs.includes(unit)\n );\n if (versions.includes(firstWord)) {\n uom = firstWord;\n uomID = id;\n }\n }\n\n if (uom) {\n oIng.unitOfMeasureID = uomID;\n oIng.unitOfMeasure = opts.normalizeUOM ? uomID : uom;\n oIng.description = remainingDesc;\n }\n }\n }\n\n if (!opts.allowLeadingOf && oIng.description.match(ofRegEx)) {\n oIng.description = oIng.description.replace(ofRegEx, '');\n }\n\n return oIng;\n });\n};\n","import { numericRegex } from 'numeric-quantity';\nimport { ParseIngredientOptions, UnitOfMeasureDefinitions } from './types';\n\n/**\n * Default options for {@link parseIngredient}.\n */\nexport const defaultOptions: Required<ParseIngredientOptions> = {\n additionalUOMs: {},\n allowLeadingOf: false,\n normalizeUOM: false,\n ignoreUOMs: [],\n} as const;\n\n/**\n * List of \"for\" equivalents (for upcoming i18n support).\n */\nexport const fors = ['For'] as const;\n/**\n * Regex to capture \"for\" equivalents (for upcoming i18n support).\n */\nexport const forsRegEx: RegExp = new RegExp(`^(?:${fors.join('|')})\\\\s`, 'i');\n\n/**\n * List of range separators (for upcoming i18n support).\n */\nexport const rangeSeparatorWords = ['or', 'to'] as const;\nconst rangeSeparatorRegExSource = `(-|–|—|(?:${rangeSeparatorWords.join('|')})\\\\s)`;\n/**\n * Regex to capture range separators (for upcoming i18n support).\n */\nexport const rangeSeparatorRegEx: RegExp = new RegExp(`^${rangeSeparatorRegExSource}`, 'i');\n\n/**\n * Regex to capture the first word of a description, to see if it's a unit of measure.\n */\nexport const firstWordRegEx: RegExp = /^(fl(?:uid)?(?:\\s+|-)(?:oz|ounces?)|\\w+[-.]?)(.+)?/;\n\nconst numericRegexAnywhere = numericRegex.source.replace(/^\\^/, '').replace(/\\$$/, '');\n\n/**\n * Regex to capture trailing quantity and unit of measure.\n */\nexport const trailingQuantityRegEx: RegExp = new RegExp(\n `(,|:|-|–|—|x|⨯)?\\\\s*((${numericRegexAnywhere})\\\\s*(${rangeSeparatorRegExSource}))?\\\\s*(${numericRegexAnywhere})\\\\s*(fl(?:uid)?(?:\\\\s+|-)(?:oz|ounces?)|\\\\w+)?$`,\n 'i'\n);\n\n/**\n * List of \"of\" equivalents (for upcoming i18n support).\n */\nexport const ofs = ['of'] as const;\n/**\n * Regex to capture \"of\" equivalents at the beginning of a string (for upcoming i18n support).\n */\nexport const ofRegEx: RegExp = new RegExp(`^(?:${ofs.join('|')})\\\\s+`, 'i');\n\n/**\n * List of \"from\" equivalents (for upcoming i18n support).\n */\nexport const froms = ['from', 'of'] as const;\n/**\n * Regex to capture \"from\" equivalents at the end of a string (for upcoming i18n support).\n */\nexport const fromRegEx: RegExp = new RegExp(`\\\\s+(?:${froms.join('|')})$`, 'i');\n\n/**\n * Default unit of measure specifications.\n */\nexport const unitsOfMeasure: UnitOfMeasureDefinitions = {\n bag: {\n short: 'bag',\n plural: 'bags',\n alternates: [] satisfies string[],\n },\n box: {\n short: 'box',\n plural: 'boxes',\n alternates: [] satisfies string[],\n },\n bunch: {\n short: 'bunch',\n plural: 'bunches',\n alternates: [] satisfies string[],\n },\n can: {\n short: 'can',\n plural: 'cans',\n alternates: [] satisfies string[],\n },\n carton: {\n short: 'carton',\n plural: 'cartons',\n alternates: [] satisfies string[],\n },\n centimeter: {\n short: 'cm',\n plural: 'centimeters',\n alternates: ['cm.'] satisfies string[],\n },\n clove: {\n short: 'clove',\n plural: 'cloves',\n alternates: [] satisfies string[],\n },\n container: {\n short: 'container',\n plural: 'containers',\n alternates: [] satisfies string[],\n },\n cup: {\n short: 'c',\n plural: 'cups',\n alternates: ['c.', 'C'] satisfies string[],\n },\n dash: {\n short: 'dash',\n plural: 'dashes',\n alternates: [] satisfies string[],\n },\n drop: {\n short: 'drop',\n plural: 'drops',\n alternates: [] satisfies string[],\n },\n ear: {\n short: 'ear',\n plural: 'ears',\n alternates: [] satisfies string[],\n },\n 'fluid ounce': {\n short: 'fl oz',\n plural: 'fluid ounces',\n alternates: [\n 'fluidounce',\n 'floz',\n 'fl-oz',\n 'fluid-ounce',\n 'fluid-ounces',\n 'fluidounces',\n 'fl ounce',\n 'fl ounces',\n 'fl-ounce',\n 'fl-ounces',\n 'fluid oz',\n 'fluid-oz',\n ] satisfies string[],\n },\n foot: {\n short: 'ft',\n plural: 'feet',\n alternates: ['ft.'] satisfies string[],\n },\n gallon: {\n short: 'gal',\n plural: 'gallons',\n alternates: ['gal.'] satisfies string[],\n },\n gram: {\n short: 'g',\n plural: 'grams',\n alternates: ['g.'] satisfies string[],\n },\n head: {\n short: 'head',\n plural: 'heads',\n alternates: [] satisfies string[],\n },\n inch: {\n short: 'in',\n plural: 'inches',\n alternates: ['in.'] satisfies string[],\n },\n kilogram: {\n short: 'kg',\n plural: 'kilograms',\n alternates: ['kg.'] satisfies string[],\n },\n large: {\n short: 'lg',\n plural: 'large',\n alternates: ['lg', 'lg.'] satisfies string[],\n },\n liter: {\n short: 'l',\n plural: 'liters',\n alternates: ['l.'] satisfies string[],\n },\n medium: {\n short: 'md',\n plural: 'medium',\n alternates: ['med', 'med.', 'md.'] satisfies string[],\n },\n meter: {\n short: 'm',\n plural: 'meters',\n alternates: ['m.'] satisfies string[],\n },\n milligram: {\n short: 'mg',\n plural: 'milligrams',\n alternates: ['mg.'] satisfies string[],\n },\n milliliter: {\n short: 'ml',\n plural: 'milliliters',\n alternates: ['mL', 'ml.', 'mL.'] satisfies string[],\n },\n millimeter: {\n short: 'mm',\n plural: 'millimeters',\n alternates: ['mm.'] satisfies string[],\n },\n ounce: {\n short: 'oz',\n plural: 'ounces',\n alternates: ['oz.'] satisfies string[],\n },\n pack: {\n short: 'pack',\n plural: 'packs',\n alternates: [] satisfies string[],\n },\n package: {\n short: 'pkg',\n plural: 'packages',\n alternates: ['pkg.', 'pkgs', 'pkgs.'] satisfies string[],\n },\n piece: {\n short: 'piece',\n plural: 'pieces',\n alternates: ['pc', 'pc.', 'pcs', 'pcs.'] satisfies string[],\n },\n pinch: {\n short: 'pinch',\n plural: 'pinches',\n alternates: [] satisfies string[],\n },\n pint: {\n short: 'pt',\n plural: 'pints',\n alternates: ['pt.'] satisfies string[],\n },\n pound: {\n short: 'lb',\n plural: 'pounds',\n alternates: ['lb.', 'lbs', 'lbs.'] satisfies string[],\n },\n quart: {\n short: 'qt',\n plural: 'quarts',\n alternates: ['qt.', 'qts', 'qts.'] satisfies string[],\n },\n small: {\n short: 'sm',\n plural: 'small',\n alternates: ['sm.'] satisfies string[],\n },\n sprig: {\n short: 'sprig',\n plural: 'sprigs',\n alternates: [] satisfies string[],\n },\n stick: {\n short: 'stick',\n plural: 'sticks',\n alternates: [] satisfies string[],\n },\n tablespoon: {\n short: 'tbsp',\n plural: 'tablespoons',\n alternates: ['tbsp.', 'T', 'Tbsp.', 'Tbsp'] satisfies string[],\n },\n teaspoon: {\n short: 'tsp',\n plural: 'teaspoons',\n alternates: ['tsp.', 't'] satisfies string[],\n },\n yard: {\n short: 'yd',\n plural: 'yards',\n alternates: ['yd.', 'yds.'] satisfies string[],\n },\n} as const;\n"],"mappings":"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","names":[]}