# `Xenia.Routes.PageModule`
[🔗](https://github.com/uzaydurdu/xenia/blob/v0.1.1/lib/xenia/app/routes/page_module.ex#L1)

Finds the module a `page.ex` defines, without running the file.

The source is parsed with `Code.string_to_quoted!/2` and its top-level
`defmodule` is read from the syntax tree. Nothing is evaluated, so a page
file can't run code at router compile time, and the router doesn't depend
on the page being compiled first.

A page file must contain exactly one top-level `defmodule` with a literal
name. Modules nested inside it are fine.

# `from_source!`

```elixir
@spec from_source!(String.t(), String.t()) :: module()
```

Like `resolve!/1`, for source code already in memory. `file` is only used
in error messages.

    iex> Xenia.Routes.PageModule.from_source!("defmodule MyAppWeb.HomePage do end")
    MyAppWeb.HomePage

# `resolve!`

```elixir
@spec resolve!(Path.t()) :: module()
```

Reads `file` and returns the module it defines.

Raises `ArgumentError` when the file has no top-level module, more than
one, or a name that isn't a literal alias. Syntax errors raise as usual.

# `uses_option?`

```elixir
@spec uses_option?(String.t(), module(), atom(), String.t()) :: boolean()
```

True when `file` contains `use <module>, ...` with `key` among the
options, read from the syntax tree without running the file.

    iex> source = "defmodule L do\n  use Xenia.Layout, on_mount: Auth\nend"
    iex> Xenia.Routes.PageModule.uses_option?(source, Xenia.Layout, :on_mount, "nofile")
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
