Natural ingredient quantity rendering

- showQuantity now produces natural text (4 cups, 125 g, 1/2 tsp)
  instead of Cooklang internal format (4%cup, 125%g, 1/2%tsp)
- Add pluralize helper: cups, tbsp, lbs, pinches, etc.
  Handles common units; unknown units stay unchanged
- Add formatFraction: displays 3/2 as '1 1/2', 1/2 as '1/2'
- No % signs in displayed quantities
This commit is contained in:
2026-05-19 13:34:23 -04:00
parent 1314c38e85
commit f902ec65b9
+52 -2
View File
@@ -52,16 +52,66 @@ pairWith _ Nothing = Nothing
pairWith a (Just b) = Just (a, b)
-- | Format a quantity for display.
-- | Format a quantity for natural display (e.g. @4 cups@, @1/2 tsp@).
showQuantity :: Quantity -> Text
showQuantity q =
let amt = quantityAmount q
amount = case denominator amt of
1 -> T.pack (show (numerator amt))
_ -> T.pack (show (toDouble amt))
_ -> formatFraction amt
prefix = if quantityFixed q then "=" else ""
unit = maybe "" ("%" <>) (quantityUnit q)
unit = maybe "" (\u -> " " <> pluralize amt u) (quantityUnit q)
in prefix <> amount <> unit
-- | Format a rational as a nice fraction string (e.g. @1/2@, @1 1/2@).
formatFraction :: Rational -> Text
formatFraction r =
let w = numerator r `Prelude.div` denominator r
rem = r - toRational w
in case w of
0 -> simpleFrac rem
_ -> T.pack (show w) <> " " <> simpleFrac rem
where
simpleFrac f =
let n = numerator f
d = denominator f
in T.pack (show n <> "/" <> show d)
-- | Pluralize a unit name based on the amount.
pluralize :: Rational -> Text -> Text
pluralize amt unit
| amt == 1 = unit
| otherwise = case T.toLower unit of
-- Units that stay the same (abbreviations, mass, volume)
"g" -> "g"
"kg" -> "kg"
"ml" -> "ml"
"l" -> "l"
"oz" -> "oz"
"lb" -> "lbs"
"tbsp" -> "tbsp"
"tsp" -> "tsp"
"cup" -> "cups"
"tablespoon" -> "tablespoons"
"teaspoon" -> "teaspoons"
"ounce" -> "ounces"
"pound" -> "pounds"
"pinch" -> "pinches"
"clove" -> "cloves"
"item" -> "items"
"piece" -> "pieces"
"can" -> "cans"
"package" -> "packages"
"bag" -> "bags"
"bunch" -> "bunches"
"sprig" -> "sprigs"
"leaf" -> "leaves"
"slice" -> "slices"
"minute" -> "minutes"
"hour" -> "hours"
"second" -> "seconds"
_ -> unit
-- ---------------------------------------------------------------------------
-- Page shell
-- ---------------------------------------------------------------------------