- Html.hs: replace lambdas with section/composition where possible
- Html.hs: replace case/fromMaybe with fromMaybe
- Html.hs: add fromMaybe to imports, use unqualified
- Parser.hs: replace span with break (2 locations)
- Parser.hs: replace if/then/else with list comprehension
- Parser.hs: remove redundant catch-all patterns (break is exhaustive)
- Server.hs: eta reduce htmlResponse
- Add .hlint.yaml to suppress 'Avoid lambda' (suggested fix has
precedence issues with blaze-html's infix (!) operator)
- All 26 tests passing, hlint: No hints, exit code 0
- Add Roux.Html.recipePage: full recipe detail page with:
- Back navigation link
- Title and metadata (servings, times, difficulty, etc.)
- Ingredients summary list with quantities
- Sections with named headings
- Steps with inline element rendering:
- Ingredients highlighted in pumpkin (with quantity badge)
- Cookware in violet italic
- Timers in azure with ⏱ icon
- Comments in sand italic
- Recipe refs as links
- Line breaks
- Update Roux.Server: route /recipes/FILENAME to recipe page
- Case-insensitive filename lookup, .cook extension optional
- URL decoding for filenames
- Fix ingredient name parsing: restrict name characters to
alphaNum + spaces/hyphens/apostrophes, preventing greedy
consumption across special chars like ) and #
- Split name chars into pMultiNameChar (with spaces, before braces)
and pSingleNameChar (without spaces, fallback)
- Suppress -Wname-shadowing in Html.hs (blaze-html exports clash
with common variable names)
- All 26 tests passing, server smoke-tested with examples
- Add Roux.Server: WAI application using wai+warp directly
- Scans .cook files from recipe directory on startup
- GET / → HTML index page listing all recipes
- Other routes → 404
- Add Roux.RecipeIndex: directory scanning and recipe parsing
- scanRecipes: lists .cook files, parses each, extracts titles
- Falls back to filename when metadata title is absent
- Add Roux.Html: blaze-html rendering with Pico CSS
- indexPage: renders recipe list with links
- urlEncode: percent-encodes filenames for URLs
- Update Roux.hs: re-exports Server.app and Types
- Add filepath to dependencies
- Add splitAmountUnit to parse quantities with unit attached without
% separator (e.g., @water{1,1/2cups}, @gelatine{3tsp})
- Add isNumericChar helper for detecting numeric quantity characters
- Add compound quantity test (1,1/2 cups = 3/2)
- Add no-separator unit test (3tsp)
- All 26 tests passing, all 4 example files parse correctly
- Fix pRecipeRef to include ./ prefix in stored path
- Add recipe reference test
- Add parse-validation tests for all 4 example .cook files
(EasyPancakes, FriedRice, CoffeeSouffle, OlivierSalad)
- All 24 tests passing, all examples parse without error
- Add pEndComment parser for -- end-of-line comments
- Add pInlineComment parser for [- ... -] block comments
- Update pText to stop before -- and [- sequences using notFollowedBy
- Add tests for both comment types (2 new tests, 19 total)
- Update Roux.Types: add SectionBodyItem (SecStep/SecComment/SecNote),
StepEndComment, remove StepNote (notes are now section-level)
- Rewrite Roux.Parser using Parsec for inline elements, text-splitting
for file-level structure
- Handle full-line -- comments, > notes, = Name = section headers
- Handle = Name (w/ and w/o closing =), == Name == variations
- Handle end-of-line backslash line breaks within steps
- Update tests to match new model + 3 EasyPancakes integration tests
- Add expectTextStep helper at module level
- Create Roux.Parser with parseCookFile (splits paragraphs, treats
each as a plain-text step, no metadata parsing yet)
- Add emptyMetadata to Roux.Types for convenience
- Add test dependencies: hspec, tasty-golden, tasty-hspec
- Add ParserSpec with 4 tests covering single step, multiple steps,
empty input, and whitespace trimming
- Wire ParserSpec into test runner via tasty-hspec