FoodAllergens
A comprehensive Elixir library providing detailed information about food allergens, including food examples and standardized SVG icons. Based on the Erudus icons collection, this library helps applications display allergen information consistently and accurately.
- 🥜 Allergen data — 14 EU allergens, each with a display name, description, and food examples
- 🎨 SVG icon set —
:standard,:circle, and:free_fromvariants for every allergen - 🌱 Dietary label icons —
:vegetarianand:vegan, in:standardand:circleshapes - 🪶 Zero runtime dependencies
- 📘 Type safety — full type specifications and documentation
Contents
- Installation
- Supported allergens
- Accuracy and scope
- Usage
- Configuration
- Development
- Contributing
- License
Installation
Add food_allergens to your list of dependencies in mix.exs:
def deps do
[
{:food_allergens, "~> 0.2.0"}
]
end
Then run mix deps.get.
Supported allergens
This is the normative order returned by FoodAllergens.list/0:
- Celery
- Gluten / cereals containing gluten (wheat, rye, barley, oats, spelt, kamut)
- Milk
- Eggs
- Fish
- Peanuts
- Soya
- Crustaceans
- Mustard
- Sesame
- Lupin
- Sulphur Dioxide (SOâ‚‚)
- Molluscs
- Tree Nuts
Accuracy and scope
This is an informational convenience dataset, not legal or medical advice.
The list reflects the 14 allergens that must be declared in the European Union under Regulation (EU) No 1169/2011, Annex II, and it covers that jurisdiction only: other regimes declare different sets (the United States, for example, declares a "Big 9").
The food_examples are illustrative and non-exhaustive, and the data does not model the declaration exemptions in that Annex — for example, fully refined soybean oil, and fish gelatine used as a fining agent in beer and wine, are exempt from declaration.
Verify against the current regulation and your product's actual formulation before relying on this data for labelling. FoodAllergens.Allergens.metadata/0 (or FoodAllergens.metadata/0) reports the source, a link to the regulation, the jurisdiction, and the date the list was last reviewed.
Usage
API at a glance
| Function | Returns |
|---|---|
FoodAllergens.list/0 |
every allergen, in the documented order |
FoodAllergens.get/1 |
one allergen by name, or nil |
FoodAllergens.metadata/0 |
data provenance: source, regulation, jurisdiction, and last review date |
FoodAllergens.get_icon/2,3 |
SVG markup for an allergen (:standard, :circle, :free_from) |
FoodAllergens.get_dietary_icon/2,3 |
SVG markup for a dietary label (:vegetarian, :vegan; :standard, :circle) |
FoodAllergens.Icons.svg_path/2, dietary_svg_path/2, default_path/0 |
filesystem paths to the bundled icons |
See https://hexdocs.pm/food_allergens for full documentation.
Listing and looking up allergens
# Every allergen, in the documented order
allergens = FoodAllergens.list()
Enum.each(allergens, &IO.puts(&1.display_name))
# One allergen, or nil when the name is unknown
peanuts = FoodAllergens.get("peanuts")
# %FoodAllergens.Allergen{
# name: "peanuts",
# display_name: "Peanuts",
# description: "Peanuts and peanut-derived products",
# food_examples: ["peanuts", "peanut butter", "peanut oil", "some candies"]
# }
FoodAllergens.get("nonexistent")
# nil
Getting SVG icons
# Standard is the default variant; :circle and :free_from are the alternatives
FoodAllergens.get_icon("peanuts")
FoodAllergens.get_icon("peanuts", :circle)
FoodAllergens.get_icon("peanuts", :free_from)
# Dietary labels take a shape, not an allergen name
FoodAllergens.get_dietary_icon(:vegetarian)
FoodAllergens.get_dietary_icon(:vegan, :circle)
- Every call returns a complete SVG string.
- Requests for an unknown name, an unknown variant, or a name that is not a bare file name return
nil. After surrounding whitespace is trimmed, a name must match[A-Za-z0-9_-]+. :free_fromexists for every allergen. The dietary labels (:vegetarian,:vegan) describe a label rather than an allergen, so they useget_dietary_icon/2with a:standardor:circleshape and never take an allergen name.- Bundled icons are embedded at compile time, so resolving one performs no file I/O and nothing is cached. See Configuration for how a configured directory changes that.
Configuration
FoodAllergens.get_icon/2 and FoodAllergens.get_dietary_icon/2 resolve each icon from the highest-precedence source that provides it:
| Source | Applies | Read |
|---|---|---|
:icons_path per-call option |
get_icon/3 and get_dietary_icon/3 |
on every call |
:svg_icons_path application env |
when no per-call option is given | on every call |
| Bundled icons | fallback, and always for the path helpers | never; embedded at compile time |
Set the application-wide directory in config/config.exs:
config :food_allergens, :svg_icons_path, "path/to/your/custom/icons"
Or pass :icons_path as the optional last argument to get_icon/3 or get_dietary_icon/3. It takes precedence over :svg_icons_path for that call, which lets one node serve several icon sets and lets tests avoid global state:
FoodAllergens.get_icon("peanuts", :circle, icons_path: "path/to/your/custom/icons")
FoodAllergens.get_dietary_icon(:vegan, icons_path: "path/to/your/custom/icons")
# Serve the bundled icons even when :svg_icons_path is set
FoodAllergens.get_icon("peanuts", icons_path: nil)
Because variant and shape have defaults, the options may also be given in their place: FoodAllergens.get_icon("peanuts", icons_path: dir).
Resolution rules:
- A configured directory overrides icon contents only, one file at a time: any icon it does not contain falls back to the embedded one, so you can overlay just the icons you want to replace.
- When
:svg_icons_pathis not configured (or is blank or invalid), every icon resolves to the bundled set. - Icons supplied by a custom directory or a per-call
:icons_pathare reachable throughFoodAllergens.get_icon/2(andget_dietary_icon/2, plus their/3forms) only. - The path helpers are narrower by design.
FoodAllergens.Icons.svg_path/2,dietary_svg_path/2, anddefault_path/0always describe the bundled icons and never consult:svg_icons_pathor a per-call:icons_path.default_path/0is resolved withApplication.app_dir/2, so it works regardless of the host application's working directory. Servedefault_path/0for static assets: it always contains a file for every icon, so a static server never 404s on an icon thatFoodAllergens.get_icon/2can resolve.
When using a custom path, maintain the expected directory structure:
your_custom_path/
├── standard/
│ ├── peanuts.svg
│ └── milk.svg
├── circle/
│ ├── peanuts.svg
│ └── milk.svg
├── free_from/
│ ├── peanuts.svg
│ └── milk.svg
└── dietary/
├── vegetarian.svg
├── vegetarian_circle.svg
├── vegan.svg
└── vegan_circle.svg
Development
Tests and checks
mix test # Run the test suite
mix check # Everything: format, compile, test, credo, dialyzer
mix credo # Run Credo for code quality checks
mix dialyzer # Run Dialyzer for static analysis
mix format # Format code
Toolchain
Elixir and Erlang/OTP are pinned in .tool-versions to the oldest supported combination — Elixir 1.18.4 on Erlang/OTP 27.3.4 — so the library is exercised at the floor declared by elixir: "~> 1.18" in mix.exs.
Documentation
Documentation can be generated with ExDoc:
mix docs
Once published, the docs can be found at https://hexdocs.pm/food_allergens.
Contributing
Bug reports and pull requests are welcome at https://github.com/eiger-code/ex-food-allergens.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite and quality checks
- Submit a pull request
License
This project is licensed under the MIT License. See the LICENSE file for details.
The SVG files under priv/icons are from the Erudus icons collection and are MIT licensed as well.