Current section

Files

Jump to
hologram lib hologram router helpers.ex
Raw

lib/hologram/router/helpers.ex

defmodule Hologram.Router.Helpers do
alias Hologram.Assets.PathRegistry, as: AssetPathRegistry
alias Hologram.Reflection
@doc """
Retrieves the asset path, including the digest, for the specified static file within the static directory.
If there's no corresponding entry for the provided static file, the static file path itself will be returned.
"""
@spec asset_path(String.t()) :: String.t()
def asset_path(static_path) do
case AssetPathRegistry.lookup(static_path) do
{:ok, asset_path} ->
asset_path
:error ->
raise Hologram.AssetNotFoundError, "there is no such asset: \"#{static_path}\""
end
end
@doc """
Returns the relative URL of a page's JavaScript bundle using the page's digest.
"""
@spec page_bundle_path(String.t()) :: String.t()
def page_bundle_path(page_digest) do
"/hologram/page-#{page_digest}.js"
end
@doc """
Builds relative URL for the given page module or a tuple of a page module and params.
"""
@spec page_path(module | tuple) :: String.t()
def page_path({module, params}) do
page_path(module, params)
end
def page_path(module) do
page_path(module, [])
end
@doc """
Builds relative URL for the given page module and params.
"""
@spec page_path(module, keyword | map) :: String.t()
def page_path(page_module, params) when is_map(params) do
page_path(page_module, Map.to_list(params))
end
def page_path(page_module, params) do
required_params = page_module.__params__()
initial_acc = {params, page_module.__route__()}
{remaining_params, path} =
Enum.reduce(required_params, initial_acc, &process_param(&1, &2, page_module, params))
ensure_no_extra_params!(remaining_params, page_module)
path
end
defp encode_param_value(value) do
value
|> to_string()
|> URI.encode(&URI.char_unreserved?/1)
end
defp ensure_no_extra_params!([], _page_module), do: :ok
defp ensure_no_extra_params!(remaining_params, page_module) do
{key, _value} = hd(remaining_params)
raise ArgumentError,
~s/page "#{Reflection.module_name(page_module)}" doesn't expect "#{key}" param/
end
defp ensure_param_exists!(params, key, page_module) do
if not Keyword.has_key?(params, key) do
raise ArgumentError,
~s'page "#{Reflection.module_name(page_module)}" expects "#{key}" param'
end
end
defp process_param({key, _type, _opts}, {params_acc, path_acc}, page_module, original_params) do
ensure_param_exists!(params_acc, key, page_module)
encoded_value = encode_param_value(original_params[key])
new_path = String.replace(path_acc, ":#{key}", encoded_value)
new_params = Keyword.drop(params_acc, [key])
{new_params, new_path}
end
end