defmodule Mob.MixProject do use Mix.Project def project do [ app: :mob, version: "0.7.2", elixir: "~> 1.19", start_permanent: Mix.env() == :prod, elixirc_paths: elixirc_paths(Mix.env()), compilers: compilers(Mix.env()) ++ Mix.compilers(), deps: deps(), aliases: aliases(), 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 [ # :public_key is needed by Mob.Certs at runtime; Elixir 1.19+ strips # unused OTP applications from the code path, so it must be declared # here even though mob doesn't *start* it directly. extra_applications: [:logger, :public_key] ] end # Two hexdocs-only injections: (1) classify unstyled
 blocks as
  # Elixir so they get syntax-highlighted, and (2) render ```mermaid fenced
  # blocks as SVG (ex_doc has no built-in mermaid support; GitHub renders
  # them natively, so READMEs work there without this).
  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"],
        "MOB_PLUGINS.md": [title: "Plugins — Manifest Reference"],
        "MOB_PLUGIN_SECURITY.md": [title: "Plugins — Security & Trust"],
        "MOB_STYLES.md": [title: "Styles — Manifest Reference"],
        "guides/why_beam.md": [title: "Why the BEAM?"],
        "guides/getting_started.md": [title: "Getting Started"],
        "guides/packages.md": [title: "First-Party Packages"],
        "guides/architecture.md": [title: "Architecture & Prior Art"],
        "guides/screen_lifecycle.md": [title: "Screen Lifecycle"],
        "guides/events.md": [title: "Events"],
        "guides/event_model.md": [title: "Event Model"],
        "guides/background_execution.md": [title: "Background Execution"],
        "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/plugins.md": [title: "Writing a Plugin"],
        "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/support_matrix.md": [title: "Device Support Matrix"],
        "guides/liveview.md": [title: "LiveView Mode"],
        "guides/ios_physical_device.md": [title: "iOS Physical Devices"],
        "guides/agentic_coding.md": [title: "Agentic Coding"]
      ],
      groups_for_extras: [
        Guides: ~r/guides\/.*/,
        Plugins: ["MOB_PLUGINS.md", "MOB_PLUGIN_SECURITY.md", "MOB_STYLES.md"]
      ],
      groups_for_modules: [
        Core: [Mob, Mob.App, Mob.Screen, Mob.ScreenState, Mob.Socket, Mob.State],
        UI: [
          Mob.UI,
          Mob.Style,
          Mob.Renderer,
          Mob.Composite,
          Mob.Theme,
          Mob.Theme.Light,
          Mob.Theme.Dark,
          Mob.Theme.Adaptive
        ],
        Navigation: [Mob.Nav.Registry],
        Plugins: [Mob.Plugins, Mob.Plugins.Supervisor, Mob.Plugins.Lifecycle],
        "Device APIs": [
          Mob.Haptic,
          Mob.Clipboard,
          Mob.Share,
          Mob.Permissions,
          Mob.Files,
          Mob.Audio,
          Mob.Motion
        ],
        "Testing & Debugging": [Mob.Test],
        Tooling: [Mob.Formatter],
        Internals: [Mob.Dist, Mob.NativeLogger, Mob.List, Mob.Sigil]
      ]
    ]
  end

  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 aliases do
    # `mix setup` after cloning installs deps and activates the shared git
    # hooks (.githooks): format / Credo --strict / compile run on every push
    # and the full suite when mix.exs changes — the same gate CI enforces.
    [setup: ["deps.get", "cmd git config core.hooksPath .githooks"]]
  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