Current section

Files

Jump to
live_view_native lib live_view_native live_reloader.ex
Raw

lib/live_view_native/live_reloader.ex

defmodule LiveViewNative.LiveReloader do
@moduledoc """
Router for live-reload detection of LiveView Native applications in development.
# Usage
Add the `LiveViewNative.LiveReloader` plug within a `code_reloading?` block
in your Endpoint, ie:
if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug LiveViewNative.LiveReloader
end
"""
import Plug.Conn
@behaviour Plug
def init(default), do: default
def call(conn, _default) do
conn
|> get_format()
|> LiveViewNative.fetch_plugin()
|> case do
{:ok, _plugin} -> live_reload(conn)
:error -> conn
end
end
defp get_format(%Plug.Conn{query_string: query_string}) do
URI.decode_query(query_string)["_format"]
end
defp live_reload(conn) do
endpoint = conn.private.phoenix_endpoint
config = endpoint.config(:live_reload)
patterns = config[:patterns]
if patterns && patterns != [] do
before_send_inject_reloader(conn, endpoint, config)
else
conn
end
end
defp before_send_inject_reloader(conn, endpoint, config) do
register_before_send(conn, fn conn ->
if conn.resp_body != nil do
resp_body = IO.iodata_to_binary(conn.resp_body)
if :code.is_loaded(endpoint) do
body = resp_body <> reload_assets_tag(conn, endpoint, config)
put_in(conn.resp_body, body)
else
conn
end
else
conn
end
end)
end
defp reload_assets_tag(conn, endpoint, config) do
path = conn.private.phoenix_endpoint.path("/phoenix/live_reload/frame#{suffix(endpoint)}")
attrs =
Keyword.merge(
[hidden: true, height: 0, width: 0, src: path],
Keyword.get(config, :iframe_attrs, [])
)
attrs =
if Keyword.has_key?(config, :iframe_class) do
IO.warn(
"The :iframe_class for Phoenix LiveReloader is deprecated, " <>
"please remove it or use :iframe_attrs instead"
)
Keyword.put_new(attrs, :class, config[:iframe_class])
else
attrs
end
IO.iodata_to_binary(["<iframe", attrs(attrs), "></iframe>"])
end
defp attrs(attrs) do
Enum.map(attrs, fn
{_key, nil} -> []
{_key, false} -> []
{key, true} -> [?\s, key(key)]
{key, value} -> [?\s, key(key), ?=, ?", value(value), ?"]
end)
end
defp key(key) do
key
|> to_string()
|> String.replace("_", "-")
|> Plug.HTML.html_escape_to_iodata()
end
defp value(value) do
value
|> to_string()
|> Plug.HTML.html_escape_to_iodata()
end
defp suffix(endpoint), do: endpoint.config(:live_reload)[:suffix] || ""
end