feat: added scale buttons

This commit is contained in:
Leyla Becker 2026-02-22 14:03:14 -06:00
parent a96734c394
commit 53c25c9da3
4 changed files with 391 additions and 22 deletions

View file

@ -136,6 +136,70 @@ function toImperialValue(value, unit) {
}
}
// ─── Base Unit Conversion (for scaling) ─────────────────
function toBaseGrams(value, unit) {
switch (unit) {
case 'g': return value;
case 'kg': return value * 1000;
case 'oz': return value * 28.3495;
case 'lb': return value * 453.592;
default: return value;
}
}
function toBaseMl(value, unit) {
switch (unit) {
case 'ml': return value;
case 'L': return value * 1000;
case 'cup': return value * 236.588;
case 'tablespoon': return value * 14.787;
case 'teaspoon': return value * 4.929;
case 'quart': return value * 946.353;
case 'gallon': return value * 3785.41;
case 'pint': return value * 473.176;
case 'fl oz': return value * 29.5735;
default: return value;
}
}
function computeScaleData(measurement) {
const { type, amount, unit, approximate } = measurement;
if (unit === 'parts by volume' || unit === 'parts by weight') return null;
if (type !== 'weight' && type !== 'volume' && type !== 'count') return null;
if (type === 'count') {
if (amount.min !== undefined) {
return {
base: [amount.min.value, amount.max.value],
type: 'count',
approx: approximate || amount.min.approximate || false,
};
}
return {
base: amount.value,
type: 'count',
approx: approximate || false,
};
}
const toBase = type === 'weight' ? toBaseGrams : toBaseMl;
if (amount.min !== undefined) {
return {
base: [toBase(amount.min.value, unit), toBase(amount.max.value, unit)],
type: type,
approx: approximate || amount.min.approximate || false,
};
}
return {
base: toBase(amount.value, unit),
type: type,
approx: approximate || false,
};
}
// ─── Time Formatting ────────────────────────────────────
function toMinutes(value, unit) {
@ -183,6 +247,12 @@ function generateTexts(measurement) {
return { defaultText: text, altText: text };
}
// Bare counts — just display the number, no conversion
if (type === 'count') {
const text = formatCountText(amount, approximate);
return { defaultText: text, altText: text };
}
if (type === 'time') {
return generateTimeTexts(amount, unit, approximate);
}
@ -190,6 +260,14 @@ function generateTexts(measurement) {
return generateUnitTexts(amount, unit, approximate, type);
}
function formatCountText(amount, approximate) {
const prefix = approximate ? '~' : '';
if (amount.min !== undefined) {
return prefix + formatNumber(amount.min.value) + '-' + formatNumber(amount.max.value);
}
return prefix + formatNumber(amount.value);
}
function generateTimeTexts(amount, unit, approximate) {
if (amount.min !== undefined) {
const prefix = amount.min.approximate ? '~' : '';
@ -306,6 +384,13 @@ function replaceMeasurementsInToken(token, Token) {
open.attrSet('data-default', defaultText);
open.attrSet('data-alt', altText);
open.attrSet('title', m.match);
// Add scaling data for weight/volume
const scaleData = computeScaleData(m);
if (scaleData) {
open.attrSet('data-scalable', JSON.stringify(scaleData));
}
newTokens.push(open);
// Display metric-normalized text by default