Skip to content

feat: add @? optional ingredient syntax#22

Merged
hilli merged 1 commit intomainfrom
optional-ingredients
Jan 23, 2026
Merged

feat: add @? optional ingredient syntax#22
hilli merged 1 commit intomainfrom
optional-ingredients

Conversation

@hilli
Copy link
Copy Markdown
Owner

@hilli hilli commented Jan 23, 2026

Summary

  • Implements the @? operator for marking ingredients as optional, following the cooklang-rs extension convention
  • Optional ingredients display with (optional) suffix across all output formats (HTML, Markdown, Print, default display)
  • Includes comprehensive tests and example recipe demonstrating the feature

Changes

Token & Lexer (token/token.go, lexer/lexer.go)

  • Added OPTIONAL_INGREDIENT = "@?" token type
  • Lexer recognizes @? when followed by valid identifier, falls back to ILLEGAL otherwise

Parser (parser/parser.go)

  • Added Optional bool field to Component struct
  • Updated ingredient parsing to handle both @ and @? tokens

Core Types (cooklang.go)

  • Added Optional bool field to Ingredient struct
  • Updated Render() to output @? prefix for optional ingredients
  • Updated RenderDisplay() to append (optional) suffix

Renderers

  • HTML (renderers/html.go): Added optional CSS class and (optional) marker
  • Markdown (renderers/markdown.go): Added *(optional)* suffix in ingredients list and inline
  • Print (renderers/print.go): Added .optional and .optional-marker CSS, displays (optional)

Tests & Examples

  • Added lexer tests for @? tokenization (6 test cases)
  • Added parser tests for optional ingredients (6 test cases)
  • Added spec tests in canonical_extensions.yaml (6 test cases)
  • Created example_recipes/Gin_and_Tonic.cook demonstrating optional garnishes

Example Usage

Add @?thyme{2%sprigs} if desired.
Garnish with @?lime wedge{1} or @?lemon wheel{1}.

Output:

Ingredients:
  - 2 sprigs thyme (optional)
  - 1 lime wedge (optional)
  - 1 lemon wheel (optional)

Implement the @? operator for marking ingredients as optional, following
the cooklang-rs extension convention. Optional ingredients are displayed
with '(optional)' suffix in all output formats.

Changes:
- Add OPTIONAL_INGREDIENT token type and lexer support
- Update parser to handle @? and set Optional field on components
- Add Optional bool field to Ingredient struct
- Update Render() and RenderDisplay() methods for optional ingredients
- Add optional ingredient support to HTML, Markdown, and Print renderers
- Add spec tests and parser/lexer unit tests
- Add example Gin_and_Tonic.cook recipe demonstrating optional garnishes

Example usage:
  Add @?thyme{2%sprigs} if desired.
  Garnish with @?lime wedge{1} or @?lemon wheel{1}.
@hilli hilli self-assigned this Jan 23, 2026
@hilli hilli merged commit 7e41a0f into main Jan 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant