Files
Epicure/apps/web/lib/parse-quantity.ts
2026-07-01 11:10:37 +02:00

38 lines
1.2 KiB
TypeScript

const UNICODE_FRACTIONS: Record<string, number> = {
"½": 0.5, "⅓": 1/3, "⅔": 2/3, "¼": 0.25, "¾": 0.75,
"⅕": 0.2, "⅖": 0.4, "⅗": 0.6, "⅘": 0.8,
"⅙": 1/6, "⅚": 5/6, "⅛": 0.125, "⅜": 0.375, "⅝": 0.625, "⅞": 0.875,
};
export function parseQuantity(v: string | number | undefined): string | undefined {
if (v === undefined || v === "") return undefined;
const s = String(v).trim();
if (!s) return undefined;
if (UNICODE_FRACTIONS[s] !== undefined) return String(UNICODE_FRACTIONS[s]);
for (const [frac, val] of Object.entries(UNICODE_FRACTIONS)) {
if (s.endsWith(frac)) {
const whole = s.slice(0, -frac.length).trim();
if (!whole) return String(val);
const w = parseFloat(whole);
if (!isNaN(w)) return String(w + val);
}
}
const mixed = s.match(/^(\d+)\s+(\d+)\s*\/\s*(\d+)$/);
if (mixed) {
const den = parseInt(mixed[3]!);
if (den !== 0) return String(parseInt(mixed[1]!) + parseInt(mixed[2]!) / den);
}
const slash = s.match(/^(\d+)\s*\/\s*(\d+)$/);
if (slash) {
const den = parseInt(slash[2]!);
if (den !== 0) return String(parseInt(slash[1]!) / den);
}
const n = parseFloat(s);
return isNaN(n) ? undefined : String(n);
}