- Strip .cook from map keys to match lookupRecipe behavior
- Use makeRelative for event paths to match relative map keys
- Filter watcher to only .cook files
- Log watcher thread exceptions
- Use imported isSuffixOf from Data.List
- scripts/scrape-recipe: Python script using recipe-scrapers to extract
schema.org JSON-LD from a recipe URL (or local HTML file for testing)
- Dockerfile: add Python3 + recipe-scrapers in virtualenv, install the
scrape-recipe script at /usr/local/bin/scrape-recipe
- Dockerfile: production image for roux-server (Debian slim, tini, binary)
- docker-compose.yml: production compose with recipe/data volume mounts
- .gitea/workflows/deploy.yaml: Gitea Actions pipeline that builds, tests,
pushes Docker image, and deploys via SSH
Follows the same pattern used by the Atlas project.
Haskell\'s \' within double-quoted string literals is interpreted as
just \' (no-op escape). Switched to \\' to produce \' in the JS
output, which correctly escapes the single quotes inside the
single-quoted JS string literal for the CSS class name.
Installs a pre-commit hook that checks all staged .hs files are
formatted by fourmolu before allowing a commit. Configured via
core.hooksPath = .githooks.
Run: ./hs fourmolu -i <files> to format
- Rewrites indexPage to render a shell page with embedded JSON + JS
- Adds searchJs with vanilla JS for client-side list rendering, filtering, sorting
- Hash-based sort modes (#alpha, #tags, #course)
- Search filters by title and filename (case-insensitive)
- Fix: recipe links use /recipes/ prefix and encodeURIComponent for # encoding
- Fix: avoid double-render on initial page load
- Add nytToCooklang function to Roux.NYTimes
- buildMetadata: maps title, URL, description, time, servings
- buildSections: creates sections for ingredient groups then step groups
- ingredientGroupToSection: converts NYT ingredient items to
Cooklang step items with @ingredient references
- stepGroupToSection: converts method steps into Cooklang steps
- Add parseDuration, parseServings, parseNYTQuantity helpers
- Add extractIngredientName heuristic for core ingredient extraction
- Add 2 conversion tests verifying both example recipes
- All 32 tests passing, hlint clean
- 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
- 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
- When recipe has a source: field in YAML metadata, shows a link
to the right of the recipe title
- Link opens in new tab with ↗ icon and 'Original recipe' text
- Hidden when no source is present
- Title row uses flexbox: title on left, source link on right
- 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
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