Packages
phoenix_html
2.3.0
4.3.0
4.2.1
4.2.0
4.1.1
4.1.0
4.0.0
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.0
3.1.0
3.0.4
3.0.3
retired
3.0.2
retired
3.0.1
retired
3.0.0
retired
2.14.3
2.14.2
2.14.1
2.14.0
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.12.0
2.11.2
2.11.1
2.11.0
2.10.5
2.10.4
2.10.3
2.10.2
2.10.1
2.10.0
2.9.3
2.9.2
2.9.1
2.9.0
2.8.0
2.7.0
2.7.0-dev
2.6.2
2.6.1
2.6.0
2.5.1
2.5.0
2.4.0
2.4.0-dev
2.3.1
2.3.0
2.2.0
2.1.2
2.1.1
2.1.0
2.0.1
2.0.0
2.0.0-dev
1.4.0
1.3.0
1.2.1
1.2.0
1.1.0
1.0.1
1.0.0
Phoenix view functions for working with HTML templates
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/phoenix_html/engine.ex
defmodule Phoenix.HTML.Engine do
@moduledoc """
This is an implementation of EEx.Engine that guarantees
templates are HTML Safe.
"""
use EEx.Engine
@doc false
def handle_body(body), do: body
@doc false
def handle_text(buffer, text) do
quote do
{:safe, [unquote(unwrap(buffer))|unquote(text)]}
end
end
@doc false
def handle_expr(buffer, "=", expr) do
line = line_from_expr(expr)
expr = expr(expr)
buffer = unwrap(buffer)
{:safe, quote do
tmp1 = unquote(buffer)
[tmp1|unquote(to_safe(expr, line))]
end}
end
@doc false
def handle_expr(buffer, "", expr) do
expr = expr(expr)
buffer = unwrap(buffer)
quote do
tmp2 = unquote(buffer)
unquote(expr)
tmp2
end
end
defp line_from_expr({_, meta, _}) when is_list(meta), do: Keyword.get(meta, :line)
defp line_from_expr(_), do: nil
# We can do the work at compile time
defp to_safe(literal, _line) when is_binary(literal) or is_atom(literal) or is_number(literal) do
Phoenix.HTML.Safe.to_iodata(literal)
end
# We can do the work at runtime
defp to_safe(literal, line) when is_list(literal) do
quote line: line, do: Phoenix.HTML.Safe.to_iodata(unquote(literal))
end
# We need to check at runtime and we do so by
# optimizing common cases.
defp to_safe(expr, line) do
# Keep stacktraces for protocol dispatch...
fallback = quote line: line, do: Phoenix.HTML.Safe.to_iodata(other)
# However ignore them for the generated clauses to avoid warnings
quote line: -1 do
case unquote(expr) do
{:safe, data} -> data
bin when is_binary(bin) -> Plug.HTML.html_escape(bin)
other -> unquote(fallback)
end
end
end
defp expr(expr) do
Macro.prewalk(expr, &handle_assign/1)
end
defp handle_assign({:@, meta, [{name, _, atom}]}) when is_atom(name) and is_atom(atom) do
quote line: meta[:line] || 0 do
Phoenix.HTML.Engine.fetch_assign(var!(assigns), unquote(name))
end
end
defp handle_assign(arg), do: arg
@doc false
def fetch_assign(assigns, key) do
case {key, Dict.fetch(assigns, key)} do
{:inner, :error} ->
raise ArgumentError, message: """
@inner has been removed in favor of explicit rendering with
@view_module and @view_template assigns. Update your
`<%= @inner %>` code to use `render/3`:
<%= render @view_module, @view_template, assigns %>
"""
{_, :error} ->
raise ArgumentError, message: """
assign @#{key} not available in eex template.
Please make sure all proper assigns have been set. If this
is a child template, ensure assigns are given explicitly by
the parent template as they are not automatically forwarded.
Available assigns: #{inspect Dict.keys(assigns)}
"""
{_, {:ok, val}} -> val
end
end
defp unwrap({:safe, value}), do: value
defp unwrap(value), do: value
end