Fix parser for personal recipes: newlines, ranges, &, markdown-style headings

Three categories of fixes:

1. Multi-line steps: removed \n from pText exclusion list so newlines
   within a step are consumed as regular text
2. Range timers (e.g. ~{14-18%minutes}): handle hyphen-separated
   ranges in parseSimpleRational by taking the lower value
3. & in ingredient names: added & to pSingleNameChar and
   pMultiNameChar char sets
4. Markdown-style # headings: added pAnyChar fallback so # followed
   by invalid cookware name falls through to text consumption
5. Note detection: tightened > check to require >  (with space)
   or > followed by non->, preventing >> metadata from being
   treated as notes
This commit is contained in:
2026-05-19 12:58:43 -04:00
parent 1e150e703e
commit c55a54796a
7 changed files with 133 additions and 25 deletions
+8 -14
View File
@@ -335,7 +335,6 @@ spec = do
let body = NE.toList (sectionBody (NE.head (recipeSections recipe)))
case body of
(_ : SecStep (Step items) : _) -> do
-- "Crack the @eggs{3} into a blender, then add the @flour{125%g}, @milk{250%ml} and @sea salt{1%pinch}, and blitz until smooth."
let expected =
[ StepText "Crack the "
, StepIngredient (Ingredient "eggs" (Just (Quantity 3 Nothing False)) Nothing)
@@ -348,9 +347,7 @@ spec = do
, StepText ", and blitz until smooth."
]
items `shouldBe` expected
_ ->
expectationFailure
("expected SecStep as second body item, got body=" <> show body)
_ -> expectationFailure ("expected SecStep as second body item, got body=" <> show body)
it "second step parses cookware and timer" $ do
case parseCookFile pancakeInput of
@@ -359,7 +356,6 @@ spec = do
let body = NE.toList (sectionBody (NE.head (recipeSections recipe)))
case body of
(_ : _ : SecStep (Step items) : _) -> do
-- "Pour into a #bowl and leave to stand for ~{15%minutes}."
let expected =
[ StepText "Pour into a "
, StepCookware (Cookware "bowl")
@@ -368,9 +364,7 @@ spec = do
, StepText "."
]
items `shouldBe` expected
_ ->
expectationFailure
("expected SecStep as third body item, got body=" <> show body)
_ -> expectationFailure ("expected SecStep as third body item, got body=" <> show body)
describe "Quantities" $ do
it "parses compound quantity (1,1/2) with unit attached" $ do
@@ -379,9 +373,9 @@ spec = do
Left err -> expectationFailure ("parse failed: " <> err)
Right recipe -> do
let items = stepItems recipe
items
`shouldBe` [ StepIngredient (Ingredient "water" (Just (Quantity (3 % 2) (Just "cups") False)) Nothing)
]
items `shouldBe`
[ StepIngredient (Ingredient "water" (Just (Quantity (3 % 2) (Just "cups") False)) Nothing)
]
it "parses quantity with trailing unit (no %)" $ do
let input = "@gelatine{3tsp}"
@@ -389,9 +383,9 @@ spec = do
Left err -> expectationFailure ("parse failed: " <> err)
Right recipe -> do
let items = stepItems recipe
items
`shouldBe` [ StepIngredient (Ingredient "gelatine" (Just (Quantity 3 (Just "tsp") False)) Nothing)
]
items `shouldBe`
[ StepIngredient (Ingredient "gelatine" (Just (Quantity 3 (Just "tsp") False)) Nothing)
]
describe "Recipe references" $ do
it "parses a recipe reference" $ do