defmodule Vite.View do @moduledoc """ Help with View integration into Phoenix views """ alias Vite.{Config, Entry, ManifestReader} @doc """ The snippet for `@vite/client` during development. Does nothing in :prod env. """ @spec vite_client :: binary() | {:safe, binary()} def vite_client() do case Config.current_env() do :prod -> "" _ -> ~s() |> as_safe() end end @doc """ The complete snippet for a single entry-point during prod. Delegates to vite dev-server otherwise. See `:for_entry` for details. """ @spec vite_snippet(binary()) :: binary() | {:safe, binary()} def vite_snippet(entry_name) do case Config.current_env() do :prod -> Vite.Manifest.entry(entry_name) |> for_entry() |> as_safe() _ -> ~s() |> as_safe() end end @doc """ Generate all links for an entry struct in following order: 1. styles to prevent FOUC 2. main entry script 3. imports ` ` """ @spec for_entry(Entry.t(), binary()) :: binary() def for_entry(entry = %Entry{}, prefix \\ "/") do script = entry.file |> module_script(prefix) imports = entry.imports |> Enum.map(&module_preload(&1, prefix)) |> Enum.join("\n") css_files = entry.cssfiles |> Enum.map(&css_link(&1, prefix)) |> Enum.join("\n") [css_files, script, imports] |> Enum.join("\n") end @doc """ Helper to get HTML for all entry points at once """ @spec for_entries(list(Entry.t())) :: binary() def for_entries(entries, prefix \\ "/") do entries |> Enum.map(&for_entry(&1, prefix)) |> Enum.join("\n") end @doc """ Helper to generate HTML for module preloading, eg: ` ` """ @spec module_preload(binary(), binary()) :: binary() def module_preload(href, prefix) do ~s() end @doc """ Helper to generate HTML for a CSS link with static tracking: ` ` """ @spec css_link(binary(), binary()) :: binary() def css_link(href, prefix) do ~s{} end @doc """ Helper to generate HTML for JS modules Has automatic inclusion of `defer`, `crossorigin` and `phx-track-static` attributes. ` ` """ @spec module_script(binary(), binary()) :: binary() def module_script(src, prefix) do ~s{} end @doc """ Helper to generate inlined Phoenix cache manifest to simplify integration with Javascript code. The manifest generated by `mix phx.digest` is stored in a global variable `window.PhxManifest`. Only works in :prod environment. """ @spec inlined_phx_manifest() :: {atom(), binary()} | binary() def inlined_phx_manifest do case Config.current_env() do :prod -> manifest = ManifestReader.read_phx() |> Map.get("latest") |> Config.json_library().encode!(pretty: true) as_safe([""]]]) _ -> "" end end defp as_safe(s), do: {:safe, s} end