Commit Graph

10 Commits

Author SHA1 Message Date
jbrechtel 8f8dbecea5 refactor: replace aeson ToJSON/FromJSON with json-fleece schemas
- RecipeSearchEntry: replace genericToJSON ToJSON with Fleece schema
  using object combinators (required, optionalNullable, list text)
- SchemaOrgRecipe: replace manual FromJSON instance with Fleece decoder
  that reuses existing helper functions for quirky fields
- Html.hs: use Fleece.Aeson.Encoder.encode instead of Data.Aeson.encode
- stack.yaml: add shrubbery + json-fleece extra-deps
- package.yaml: add json-fleece-aeson + json-fleece-core deps
- Remove unused LANGUAGE pragmas and redundant brackets
2026-05-19 23:24:24 -04:00
jbrechtel 340b95cf79 chore: format with fourmolu and add SchemaOrg to cabal 2026-05-19 22:52:12 -04:00
jbrechtel 4055bf62c1 Extract Cooklang types into Data.CookLang module
- Create src/Data/CookLang.hs with all recipe types (Recipe, Section,
  StepItem, Ingredient, Cookware, Timer, RecipeRef, Quantity, Duration,
  Metadata, emptyMetadata)
- Data.CookLang has zero Roux imports — can be extracted to its own
  package
- Roux.Types now just re-exports from Data.CookLang
- Update all Roux.* modules and tests to import Data.CookLang directly
- All 30 tests passing, hlint clean
2026-05-19 15:59:59 -04:00
jbrechtel 21a4cea083 Add NYTimes recipe extraction from __NEXT_DATA__ JSON tag
- Add Roux.NYTimes module with:
  - extractNextData: finds <script id="__NEXT_DATA__"> tag in HTML
    and parses its JSON content via aeson
  - parseNYTRecipe: maps NYTimes recipe JSON structure into a
    typed intermediate representation (NYTRecipe, NYTIngredientGroup,
    NYTIngredientItem, NYTStepGroup, NYTStepItem)
- Supports all NYTimes Cooking data: title, URL, total time, yield,
  topnote, ingredient groups (with section names), step groups
- Add aeson to dependencies
- Add 4 tests: extraction + parsing for both fried-rice and
  carrot-risotto example HTML files
- Wire NYTimesSpec into test runner
2026-05-19 15:51:37 -04:00
jbrechtel c55a54796a 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
2026-05-19 12:58:43 -04:00
jbrechtel d1582e9034 Recipe page restyled to match mockup design
- Add Pompiere font from Google Fonts
- Color theme: #F5EFE0 (bg), #3D2C1E (text), #B85C38 (accent)
- Two-column layout (ingredients | method) matching mockup
- Horizontal metadata bar: Serves, Prep, Cook, Total
- Course badge and description paragraph
- Ingredients: checkbox rows with quantity prefix, grouped by section
- Method: numbered steps with checkboxes
- Notes: ¶ ornament + paragraph style
- Index page: styled navbar with sort mode buttons
- Index page: styled recipe list with separators
- Custom CSS via internal stylesheet (no Pico CSS override except
  link for reset/utility classes)
- Add LambdaCase and TupleSections to default extensions
- All 26 tests passing, hlint clean
2026-05-19 09:54:08 -04:00
jbrechtel 4943d4d42e Web server with recipe index page
- 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
2026-05-19 07:04:22 -04:00
jbrechtel 235adce596 Add minimal Cooklang parser with first tests
- 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
2026-05-18 22:21:32 -04:00
jbrechtel e907a03b09 Define Cooklang data model and add DerivingStrategies + containers deps
- Add full Cooklang (.cook) recipe data model to Roux.Types:
  Recipe, Section, Step, StepItem (with StepText/StepIngredient/
  StepCookware/StepTimer/StepRecipeRef/StepNote/StepComment/StepBreak),
  Ingredient, Cookware, Timer, RecipeRef, Quantity, Duration, Metadata
- Enable DerivingStrategies extension project-wide
- Add containers to build dependencies
2026-05-18 22:15:21 -04:00
jbrechtel 130dc5326d Haskell project 2026-05-18 22:00:30 -04:00