recipe-ingredient-parser-v3
Version:
Natural language parser for recipes and ingredient lists, incl. combining ingredients
133 lines • 5.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.findQuantityAndConvertIfUnicode = exports.feach = exports.text2num = exports.getFirstMatch = exports.convertFromFraction = void 0;
var numbers_1 = require("./numbers");
function convertFromFraction(value) {
// number comes in, for example: 1 1/3
if (value && value.split(' ').length > 1) {
var _a = value.split(' '), whole = _a[0], fraction = _a[1];
var _b = fraction.split('/'), a = _b[0], b = _b[1];
var remainder = parseFloat(a) / parseFloat(b);
var wholeAndFraction = parseInt(whole) ? parseInt(whole) + remainder : remainder;
return keepTwoDecimals(wholeAndFraction);
}
else if (!value || value.split('-').length > 1) {
return value;
}
else {
var _c = value.split('/'), a = _c[0], b = _c[1];
return b ? keepTwoDecimals(parseFloat(a) / parseFloat(b)) : a;
}
}
exports.convertFromFraction = convertFromFraction;
function getFirstMatch(line, regex) {
var match = line.match(regex);
return (match && match[0]) || '';
}
exports.getFirstMatch = getFirstMatch;
var unicodeObj = {
'½': '1/2',
'⅓': '1/3',
'⅔': '2/3',
'¼': '1/4',
'¾': '3/4',
'⅕': '1/5',
'⅖': '2/5',
'⅗': '3/5',
'⅘': '4/5',
'⅙': '1/6',
'⅚': '5/6',
'⅐': '1/7',
'⅛': '1/8',
'⅜': '3/8',
'⅝': '5/8',
'⅞': '7/8',
'⅑': '1/9',
'⅒': '1/10'
};
function text2num(s, language) {
var a = s.toString().split(/[\s-]+/);
var values = [0, 0];
a.forEach(function (x) {
values = feach(x, values[0], values[1], language);
});
if (values[0] + values[1] < 0)
return null;
else
return values[0] + values[1];
}
exports.text2num = text2num;
function feach(w, g, n, language) {
var number = numbers_1.numbersMap.get(language);
var small = number[0];
var magnitude = number[1];
var x = small[w];
if (x != null) {
g = g + x;
}
else if (100 == magnitude[w]) {
if (g > 0)
g = g * 100;
else
g = 100;
}
else {
x = magnitude[w];
if (x != null) {
n = n + g * x;
g = 0;
}
else
return [-1, -1];
}
return [g, n];
}
exports.feach = feach;
function findQuantityAndConvertIfUnicode(ingredientLine, language) {
var numericAndFractionRegex = /\b(\d+\/\d+|\d+\s\d+\/\d+|\d+\.\d+|\d+)\b/g; // consider only the numbers that have space and not those attached to words, such as "petra9"
//const numericRangeWithSpaceRegex = /^(\d+\-\d+)|^(\d+\s\-\s\d+)|^(\d+\sto\s\d+)/g; // for ex: "1 to 2" or "1 - 2"
var unicodeFractionRegex = /\d*[^\u0000-\u007F]+/g;
var onlyUnicodeFraction = /[^\u0000-\u007F]+/g;
var wordUntilSpace = /[^\s]+/g;
// found a unicode quantity inside our regex, for ex: '⅝'
if (ingredientLine.match(unicodeFractionRegex)) {
var numericPart = getFirstMatch(ingredientLine, numericAndFractionRegex);
var unicodePart = getFirstMatch(ingredientLine, numericPart ? onlyUnicodeFraction : unicodeFractionRegex);
// If there's a match for the unicodePart in our dictionary above
if (unicodeObj[unicodePart]) {
return [numericPart + " " + unicodeObj[unicodePart], ingredientLine.replace(getFirstMatch(ingredientLine, unicodeFractionRegex), '').trim()];
}
}
// found a quantity range, for ex: "2 to 3"
// if (ingredientLine.match(numericRangeWithSpaceRegex)) {
// const quantity = getFirstMatch(ingredientLine, numericRangeWithSpaceRegex).replace('to', '-').split(' ').join('');
// const restOfIngredient = ingredientLine.replace(getFirstMatch(ingredientLine, numericRangeWithSpaceRegex), '').trim();
// return [ingredientLine.match(numericRangeWithSpaceRegex) && quantity, restOfIngredient];
// }
// found a numeric/fraction quantity, for example: "1 1/3"
if (ingredientLine.match(numericAndFractionRegex)) {
var quantity = getFirstMatch(ingredientLine, numericAndFractionRegex);
var restOfIngredient = ingredientLine.replace(getFirstMatch(ingredientLine, numericAndFractionRegex), '').trim();
return [ingredientLine.match(numericAndFractionRegex) && quantity, restOfIngredient];
}
else if (ingredientLine.match(wordUntilSpace)) {
var quantity = getFirstMatch(ingredientLine, wordUntilSpace);
var quantityNumber = text2num(quantity.toLowerCase(), language);
if (quantityNumber) {
var restOfIngredient = ingredientLine.replace(getFirstMatch(ingredientLine, wordUntilSpace), '').trim();
return [ingredientLine.match(wordUntilSpace) && quantityNumber + '', restOfIngredient];
}
else
return [null, ingredientLine];
}
// no parse-able quantity found
else {
return [null, ingredientLine];
}
}
exports.findQuantityAndConvertIfUnicode = findQuantityAndConvertIfUnicode;
function keepTwoDecimals(val) {
var strVal = val.toString();
return strVal.split('.')[0] + '.' + strVal.split('.')[1].substring(0, 2);
}
//# sourceMappingURL=convert.js.map