UNPKG

parse-ingredient

Version:

Recipe ingredient parser with support for mixed numbers and vulgar fractions

2 lines 10.1 kB
import{numericQuantity as e,numericRegex as t}from"numeric-quantity";const n=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),r=e=>{if(e.length===0)return null;let t=e.map(e=>e instanceof RegExp?`(?:${e.source})`:`(?:${n(e)})\\s`);return RegExp(`^(?:${t.join(`|`)})`,`iu`)},i=e=>`(-|–|—|(?:${e.map(e=>e instanceof RegExp?`(?:${e.source})`:`(?:${n(e)})`).join(`|`)})\\s)`,a=e=>RegExp(`^${i(e)}`,`iu`),o=e=>{if(e.length===0)return null;let t=e.map(e=>e instanceof RegExp?`(?:${e.source})`:`(?:${n(e)})\\s+`);return RegExp(`^(?:${t.join(`|`)})`,`iu`)},s=e=>{if(e.length===0)return null;let t=e.map(e=>e instanceof RegExp?`(?:${e.source})\\s*`:`(?:${n(e)})\\s*`);return RegExp(`^(?:${t.join(`|`)})`,`iu`)},c=e=>RegExp(`\\s+(?:${e.map(n).join(`|`)})$`,`iu`),l=[`For`],u=[`or`,`to`],d=[`of`],f=[`from`,`of`],p=[],m={additionalUOMs:{},allowLeadingOf:!1,normalizeUOM:!1,ignoreUOMs:[],decimalSeparator:`.`,groupHeaderPatterns:l,rangeSeparators:u,descriptionStripPrefixes:d,trailingQuantityContext:f,leadingQuantityPrefixes:p,includeMeta:!1,partialUnitMatching:!1},h=l,g=r(l),_=u,v=a(u),y=/^(fl(?:uid)?(?:\s+|-)(?:oz|ounces?)|[\p{L}\p{N}_]+(?:[./-][\p{L}\p{N}_]+|\([\p{L}\p{N}_]+\))*[-.]?)(.+)?/iu,b=t.source.replace(`^`,``).replace(/\$$/,``),x=e=>{let t=i(e);return RegExp(`(,|:|-|–|—|x|⨯)?\\s*((${b})\\s*(${t}))?\\s*(${b})\\s*(fl(?:uid)?(?:\\s+|-)(?:oz|ounces?)|[\\p{L}\\p{N}_]+(?:[./-][\\p{L}\\p{N}_]+|\\([\\p{L}\\p{N}_]+\\))*[-.]?)?$`,`iu`)},S=x(u),C=d,w=o(d),T=f,E=c(f),D={bag:{short:`bag`,plural:`bags`,alternates:[],type:`count`},box:{short:`box`,plural:`boxes`,alternates:[],type:`count`},bunch:{short:`bunch`,plural:`bunches`,alternates:[],type:`count`},can:{short:`can`,plural:`cans`,alternates:[],type:`count`},carton:{short:`carton`,plural:`cartons`,alternates:[],type:`count`},clove:{short:`clove`,plural:`cloves`,alternates:[],type:`count`},container:{short:`container`,plural:`containers`,alternates:[],type:`count`},dozen:{short:`dz`,plural:`dozen`,alternates:[`dz.`],type:`count`},ear:{short:`ear`,plural:`ears`,alternates:[],type:`count`},head:{short:`head`,plural:`heads`,alternates:[],type:`count`},pack:{short:`pack`,plural:`packs`,alternates:[],type:`count`},package:{short:`pkg`,plural:`packages`,alternates:[`pkg.`,`pkgs`,`pkgs.`],type:`count`},piece:{short:`piece`,plural:`pieces`,alternates:[`pc`,`pc.`,`pcs`,`pcs.`],type:`count`},sprig:{short:`sprig`,plural:`sprigs`,alternates:[],type:`count`},stick:{short:`stick`,plural:`sticks`,alternates:[],type:`count`},large:{short:`lg`,plural:`large`,alternates:[`lg`,`lg.`],type:`other`},medium:{short:`md`,plural:`medium`,alternates:[`med`,`med.`,`md.`],type:`other`},small:{short:`sm`,plural:`small`,alternates:[`sm.`],type:`other`},centimeter:{short:`cm`,plural:`centimeters`,alternates:[`cm.`],type:`length`,conversionFactor:10},foot:{short:`ft`,plural:`feet`,alternates:[`ft.`],type:`length`,conversionFactor:304.8},inch:{short:`in`,plural:`inches`,alternates:[`in.`],type:`length`,conversionFactor:25.4},meter:{short:`m`,plural:`meters`,alternates:[`m.`],type:`length`,conversionFactor:1e3},millimeter:{short:`mm`,plural:`millimeters`,alternates:[`mm.`],type:`length`,conversionFactor:1},yard:{short:`yd`,plural:`yards`,alternates:[`yd.`,`yds.`],type:`length`,conversionFactor:914.4},gram:{short:`g`,plural:`grams`,alternates:[`g.`],type:`mass`,conversionFactor:1},kilogram:{short:`kg`,plural:`kilograms`,alternates:[`kg.`],type:`mass`,conversionFactor:1e3},milligram:{short:`mg`,plural:`milligrams`,alternates:[`mg.`],type:`mass`,conversionFactor:.001},ounce:{short:`oz`,plural:`ounces`,alternates:[`oz.`],type:`mass`,conversionFactor:28.349523},pound:{short:`lb`,plural:`pounds`,alternates:[`lb.`,`lbs`,`lbs.`],type:`mass`,conversionFactor:453.59237},cup:{short:`c`,plural:`cups`,alternates:[`c.`,`C`],type:`volume`,conversionFactor:{us:236.58824,imperial:284.13063,metric:250}},deciliter:{short:`dl`,plural:`deciliters`,alternates:[`dl.`],type:`volume`,conversionFactor:100},"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`],type:`volume`,conversionFactor:{us:29.57353,imperial:28.413063}},gallon:{short:`gal`,plural:`gallons`,alternates:[`gal.`],type:`volume`,conversionFactor:{us:3785.4118,imperial:4546.09}},liter:{short:`l`,plural:`liters`,alternates:[`l.`],type:`volume`,conversionFactor:1e3},milliliter:{short:`ml`,plural:`milliliters`,alternates:[`mL`,`ml.`,`mL.`],type:`volume`,conversionFactor:1},pint:{short:`pt`,plural:`pints`,alternates:[`pt.`],type:`volume`,conversionFactor:{us:473.17647,imperial:568.26125}},quart:{short:`qt`,plural:`quarts`,alternates:[`qt.`,`qts`,`qts.`],type:`volume`,conversionFactor:{us:946.35295,imperial:1136.5225}},tablespoon:{short:`tbsp`,plural:`tablespoons`,alternates:[`tbsp.`,`T`,`Tbsp.`,`Tbsp`,`tablespoonful`],type:`volume`,conversionFactor:{us:14.786765,imperial:15,metric:15}},teaspoon:{short:`tsp`,plural:`teaspoons`,alternates:[`tsp.`,`t`,`teaspoonful`],type:`volume`,conversionFactor:{us:4.9289216,imperial:5,metric:5}},dash:{short:`dash`,plural:`dashes`,alternates:[],type:`volume`},drop:{short:`drop`,plural:`drops`,alternates:[],type:`volume`},pinch:{short:`pinch`,plural:`pinches`,alternates:[],type:`volume`}},O=(e={})=>{let t=new Map,n=new Map,r=(e,r)=>{let i=[e,r.short,r.plural,...r.alternates];for(let r of i)t.set(r,e),n.set(r.toLowerCase(),e)};for(let[e,t]of Object.entries(D))r(e,t);for(let[t,n]of Object.entries(e))r(t,n);return{caseSensitive:t,caseInsensitive:n}},k=(e,t)=>{var n,r;return(n=(r=t.caseSensitive.get(e))==null?t.caseInsensitive.get(e.toLowerCase()):r)==null?null:n};let A=null;const j=()=>{var e;return(e=A)==null?A=O():e},M=e=>{let t=[...e.caseSensitive.keys()];return t.sort((e,t)=>t.length-e.length),t},N=(e,t={})=>{let{additionalUOMs:n={},ignoreUOMs:r=[]}=t;if(r.length>0){let t=e.toLowerCase();if(r.some(e=>e.toLowerCase()===t))return null}return k(e,Object.keys(n).length>0?O(n):j())},P=(e,t)=>{var n;return e===void 0?null:typeof e==`number`?e:(n=e[t])==null?null:n},F=(e,t,n,r={})=>{let{fromSystem:i=`us`,toSystem:a=`us`,additionalUOMs:o={}}=r,s=i.toLowerCase(),c=a.toLowerCase(),l={...D,...o},u=N(t,{additionalUOMs:o}),d=N(n,{additionalUOMs:o});if(!u||!d)return null;if(u===d&&s===c)return e;let f=l[u],p=l[d];if(!f.type||!p.type||f.type!==p.type)return null;let m=P(f.conversionFactor,s),h=P(p.conversionFactor,c);if(m===null||h===null)return null;let g=e*m/h;return Math.round(g*1e6)/1e6},I=/\r?\n/,L=/^([\p{L}\p{N}_]+(?:[.-]?[\p{L}\p{N}_]+)*[-.]?)(?:\s+|$)/iu,R=(e,t)=>{if(!e||!t)return e;let n=e.trimStart();for(;n;){let e=t.exec(n);if(!e||!e[0])break;n=n.slice(e[0].length).trimStart()}return n},z=(t,n=m)=>{let i={...m,...n},l=i.decimalSeparator===`,`?{decimalSeparator:`,`}:void 0,u=i.ignoreUOMs.map(e=>e.toLowerCase()),d=r(i.groupHeaderPatterns),f=a(i.rangeSeparators),p=o(i.descriptionStripPrefixes),h=c(i.trailingQuantityContext),g=x(i.rangeSeparators),_=s(i.leadingQuantityPrefixes),v=i.partialUnitMatching?M(Object.keys(i.additionalUOMs).length>0?O(i.additionalUOMs):j()):[];return(Array.isArray(t)?t:t.split(I)).map((e,t)=>({line:e.trim(),sourceIndex:t})).filter(({line:e})=>!!e).map(({line:t,sourceIndex:r})=>{let a=R(t,_),o={quantity:null,quantity2:null,unitOfMeasureID:null,unitOfMeasure:null,description:``,isGroupHeader:!1};if(i.includeMeta&&(o.meta={sourceText:t,sourceIndex:r}),a&&(!isNaN(e(a[0],l))||a[0]===i.decimalSeparator&&!isNaN(e(a.slice(0,2),l)))){let t=6,n=NaN;for(;t>0&&isNaN(n);)n=e(a.substring(0,t).trim(),l),n>-1&&(o.quantity=n,o.description=a.substring(t).trim()),t--}else{var s;let t=g.exec(a),r=t==null||(s=t.at(-1))==null?void 0:s.toLowerCase();if(r&&u.includes(r))o.description=a;else if(t){o.description=a.replace(g,``).trim();let r=t[3],s=t[12];r?(o.quantity=e(r,l),o.quantity2=e(s,l)):o.quantity=e(s,l);let c=t.at(-1);if(c){let e=null,t=c;if(o.description){let r=o.description.trim().split(/\s+/);if(r.length>=1){let i=r[r.length-1]+` `+c,a=N(i,n);a&&(e=a,t=i,o.description=r.slice(0,-1).join(` `))}}e||(e=N(c,n),t=c),e?(o.unitOfMeasureID=e,o.unitOfMeasure=i.normalizeUOM?e:t):o.description.match(h)&&(o.description+=` ${c}`)}}else o.description=a,(o.description.endsWith(`:`)||d!=null&&d.test(o.description))&&(o.isGroupHeader=!0)}let c=f.exec(o.description);if(c){let t=c[1].length,n=R(o.description.substring(t).trim(),_);if(n){let t=e(n[0],l);if(!isNaN(t)){let t=7,r=NaN;for(;--t>0&&isNaN(r);)r=e(n.substring(0,t),l),isNaN(r)||(o.quantity2=r,o.description=n.substring(t).trim())}}}let m=y.exec(o.description);if(m){var b;let e=m[1].replace(/\s+/g,` `),t=((b=m[2])==null?``:b).trim();if(t){let r=N(e,n),a=e,s=t,c=t.match(L);if(c){let i=e+` `+c[1],l=N(i,n),u=t.substring(c[0].length).trim();l&&(o.quantity!==null||u)&&(r=l,a=i,s=u)}r&&(o.unitOfMeasureID=r,o.unitOfMeasure=i.normalizeUOM?r:a,o.description=s)}}if(!o.unitOfMeasureID&&i.partialUnitMatching&&o.description){let e=o.description.toLowerCase();for(let t of v){let r=e.indexOf(t.toLowerCase());if(r===-1)continue;let a=o.description.substring(r,r+t.length),s=N(a,n);if(!s)continue;let c=[o.description.substring(0,r).trim(),o.description.substring(r+t.length).trim()].filter(Boolean).join(` `);if(c){o.unitOfMeasureID=s,o.unitOfMeasure=i.normalizeUOM?s:a,o.description=c;break}}}return!i.allowLeadingOf&&p&&o.description.match(p)&&(o.description=o.description.replace(p,``)),o})};export{s as buildLeadingQuantityPrefixRegex,r as buildPrefixPatternRegex,a as buildRangeSeparatorRegex,i as buildRangeSeparatorSource,o as buildStripPrefixRegex,c as buildTrailingContextRegex,x as buildTrailingQuantityRegex,F as convertUnit,d as defaultDescriptionStripPrefixes,l as defaultGroupHeaderPatterns,p as defaultLeadingQuantityPrefixes,m as defaultOptions,u as defaultRangeSeparators,f as defaultTrailingQuantityContext,n as escapeRegex,y as firstWordRegEx,h as fors,g as forsRegEx,E as fromRegEx,T as froms,N as identifyUnit,w as ofRegEx,C as ofs,z as parseIngredient,v as rangeSeparatorRegEx,_ as rangeSeparatorWords,S as trailingQuantityRegEx,D as unitsOfMeasure}; //# sourceMappingURL=parse-ingredient.production.mjs.map