defmodule Mob.MixProject do use Mix.Project def project do [ app: :mob, version: "0.6.21", elixir: "~> 1.19", start_permanent: Mix.env() == :prod, elixirc_paths: elixirc_paths(Mix.env()), compilers: compilers(Mix.env()) ++ Mix.compilers(), deps: deps(), unused: [ ignore: [ # GenServer / behaviour callbacks (mix_unused can't see them). {:_, :init, 1}, {:_, :handle_call, 3}, {:_, :handle_cast, 2}, {:_, :handle_info, 2}, {:_, :handle_continue, 2}, {:_, :terminate, 2}, {:_, :code_change, 3}, # Mob's public render-tree API — every component module exposes # render/1 callable from app code. mix_unused sees no internal # caller because it lives in user apps. {~r/^Mob\..+/, :render, 1}, # Screen lifecycle callbacks dispatched by the Mob.Screen # GenServer wrapper. {~r/^Mob\..+/, :mount, 3}, {~r/^Mob\..+/, :on_start, 0}, {~r/^Mob\..+/, :on_resume, 1}, # Screen state persistence — generated by `use Mob.Screen, vsn: N`. {~r/^Mob\..+/, :__mob_vsn__, 0}, {~r/^Mob\..+/, :__mob_persist__, 0}, {~r/^Mob\..+/, :dump_state, 1}, {~r/^Mob\..+/, :load_state, 2}, {~r/^Mob\..+/, :screen_key, 1}, # NIF stub functions in src/mob_nif.erl (apply'd via load_nif). {:mob_nif, :_, :_}, # Mob.Test diagnostic API surface — IEx-driven, no internal # caller in mob itself. {~r/^Mob\.Test$/, :_, :_}, # Theme accessors — used by user apps via Mob.Theme.. {~r/^Mob\.Theme\..+/, :_, :_} ] ], description: "BEAM-on-device mobile framework for Elixir", source_url: "https://github.com/genericjam/mob", homepage_url: "https://hexdocs.pm/mob", package: package(), docs: docs() ] end def application do [ extra_applications: [:logger] ] end # Render ```mermaid fenced blocks on hexdocs. GitHub renders them natively; # ex_doc does not, so inject mermaid.js and convert the code blocks it emits. defp before_closing_body_tag(:html) do """ """ end defp before_closing_body_tag(_), do: "" defp docs do [ main: "readme", before_closing_body_tag: &before_closing_body_tag/1, logo: "assets/logo/logo_full_color.png", source_url: "https://github.com/genericjam/mob", source_url_pattern: "https://github.com/genericjam/mob/blob/master/%{path}#L%{line}", extras: [ "README.md": [title: "Mob"], "CHANGELOG.md": [title: "Changelog"], "guides/why_beam.md": [title: "Why the BEAM?"], "guides/getting_started.md": [title: "Getting Started"], "guides/architecture.md": [title: "Architecture & Prior Art"], "guides/screen_lifecycle.md": [title: "Screen Lifecycle"], "guides/components.md": [title: "Components"], "guides/styling.md": [title: "Styling & Native Rendering"], "guides/theming.md": [title: "Theming"], "guides/navigation.md": [title: "Navigation"], "guides/device_capabilities.md": [title: "Device Capabilities"], "guides/mobile_surface_matrix.md": [title: "Mobile Surface Matrix"], "guides/permissions.md": [title: "Permissions"], "guides/native_extensions.md": [title: "Native Extensions (NIFs, features)"], "guides/dns_on_ios.md": [title: "DNS on iOS"], "guides/push_notifications.md": [title: "Push Notifications"], "guides/data.md": [title: "Data & Persistence"], "guides/testing.md": [title: "Testing"], "guides/tooling.md": [title: "Tooling & Formatting"], "guides/publishing.md": [title: "Publishing to App Store / TestFlight"], "guides/troubleshooting.md": [title: "Troubleshooting"], "guides/agentic_coding.md": [title: "Agentic Coding"] ], groups_for_extras: [ Guides: ~r/guides\/.*/ ], groups_for_modules: [ Core: [Mob, Mob.App, Mob.Screen, Mob.ScreenState, Mob.Socket, Mob.State], UI: [ Mob.UI, Mob.Style, Mob.Renderer, Mob.Theme, Mob.Theme.Obsidian, Mob.Theme.Citrus, Mob.Theme.Birch ], Navigation: [Mob.Nav.Registry], "Device APIs": [ Mob.Haptic, Mob.Clipboard, Mob.Share, Mob.Permissions, Mob.Biometric, Mob.Location, Mob.Camera, Mob.Photos, Mob.Files, Mob.Audio, Mob.Motion, Mob.Scanner, Mob.Notify ], "Testing & Debugging": [Mob.Test], Tooling: [Mob.Formatter], Internals: [Mob.Dist, Mob.NativeLogger, Mob.List, Mob.Sigil] ], before_closing_body_tag: &before_closing_body_tag/1 ] end defp before_closing_body_tag(:html) do """ """ end defp before_closing_body_tag(_), do: "" defp elixirc_paths(:test), do: ["lib", "test/onboarding", "test/onboarding/support"] defp elixirc_paths(_), do: ["lib"] defp package do [ licenses: ["MIT"], links: %{"GitHub" => "https://github.com/genericjam/mob"}, files: ~w( lib src priv android ios assets mix.exs mix.lock README.md CHANGELOG.md LICENSE ) ] end defp deps do [ # HTML/HEEx template engine — same one Phoenix uses # {:phoenix_live_view, "~> 1.0", optional: true}, # add when HEEx rendering lands {:nimble_parsec, "~> 1.0"}, {:ex_doc, "~> 0.34", only: :dev, runtime: false}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:jump_credo_checks, "~> 0.1.0", only: [:dev, :test], runtime: false}, # ex_slop — Credo check that catches AI-generated Elixir patterns # (blanket rescue, narrator-style docs, redundant Enum chains, etc). # Wired in via .credo.exs as `{ExSlop, []}` in the enabled list. {:ex_slop, "~> 0.4", only: [:dev, :test], runtime: false}, {:erlfmt, "~> 1.8", only: :dev, runtime: false}, # mix_audit — CVE scan over mix.lock against the Erlef advisory feed. # Invocation note: `mix deps.audit` alone fails with # `YamlElixir.read_from_file/1 is undefined` because mix_audit doesn't # ensure_all_started its yaml_elixir transitive dep before parsing # the advisory files. CI works around this with `mix do app.start + # deps.audit` (the app.start prefix starts the host app, which # transitively starts yaml_elixir via the runtime tree). {:mix_audit, "~> 2.1", only: [:dev, :test], runtime: false}, # Known Elixir 1.20-rc.4 dep warning (cosmetic, dev-only): # lib/mix_unused/filter.ex:61 — `_.._ inside match is deprecated`. # No upstream fix shipped yet (0.4.1 is latest, from 2024). Bump # this version + drop this comment once mix_unused ships a 1.20-clean # release. {:mix_unused, "~> 0.4", only: :dev, runtime: false}, {:ecto_sqlite3, "~> 0.18", only: :test} ] end # `:unused` only runs in dev. Keeps test/CI logs clean. defp compilers(:dev), do: [:unused] defp compilers(_), do: [] end