Properly emit boolean attributes (#139)
* Update some docs * Properly emit boolean attributes. * Account for quoted literals when compiling attributes * Update changelog
This commit is contained in:
parent
d307fe35de
commit
9d05f74cdf
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
## Main
|
## Main
|
||||||
|
|
||||||
Nothing yet
|
### Enhancements
|
||||||
|
|
||||||
|
- [breaking] Attributes who values are boolean expressions will be emitted as boolean attributes.
|
||||||
|
|
||||||
## 0.6.2
|
## 0.6.2
|
||||||
|
|
||||||
|
|
15
README.md
15
README.md
|
@ -22,15 +22,6 @@ def deps do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
def deps do
|
|
||||||
[{:temple, github: "mhanberg/temple"}]
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
Currently Temple has the following things on which it won't compromise.
|
Currently Temple has the following things on which it won't compromise.
|
||||||
|
@ -140,7 +131,8 @@ config :phoenix, :template_engines,
|
||||||
# you can enable Elixir syntax highlighting in your editor
|
# you can enable Elixir syntax highlighting in your editor
|
||||||
lexs: Temple.LiveViewEngine
|
lexs: Temple.LiveViewEngine
|
||||||
|
|
||||||
# If you're going to be using live_view, make sure to set the `:mode`
|
# If you're going to be using live_view, make sure to set the `:mode` to `:live_view`.
|
||||||
|
# This is necessary for Temple to emit markup that is compatible.
|
||||||
config :temple, :mode, :live_view # defaults to normal
|
config :temple, :mode, :live_view # defaults to normal
|
||||||
|
|
||||||
# config/dev.exs
|
# config/dev.exs
|
||||||
|
@ -156,6 +148,7 @@ config :your_app, YourAppWeb.Endpoint,
|
||||||
```elixir
|
```elixir
|
||||||
# app.html.exs
|
# app.html.exs
|
||||||
|
|
||||||
|
"<!DOCTYPE html>"
|
||||||
html lang: "en" do
|
html lang: "en" do
|
||||||
head do
|
head do
|
||||||
meta charset: "utf-8"
|
meta charset: "utf-8"
|
||||||
|
@ -163,7 +156,7 @@ html lang: "en" do
|
||||||
meta name: "viewport", content: "width=device-width, initial-scale=1.0"
|
meta name: "viewport", content: "width=device-width, initial-scale=1.0"
|
||||||
title do: "YourApp · Phoenix Framework"
|
title do: "YourApp · Phoenix Framework"
|
||||||
|
|
||||||
link rel: "stylesheet", href: Routes.static_path(@conn, "/css/app.css")
|
_link rel: "stylesheet", href: Routes.static_path(@conn, "/css/app.css")
|
||||||
end
|
end
|
||||||
|
|
||||||
body do
|
body do
|
||||||
|
|
|
@ -22,6 +22,8 @@ c Form, changeset: @changeset, action: @action do
|
||||||
text_input f, :author
|
text_input f, :author
|
||||||
error_tag(f, :author)
|
error_tag(f, :author)
|
||||||
|
|
||||||
|
input type: "text", disabled: true, id: "disabled-input"
|
||||||
|
|
||||||
div do
|
div do
|
||||||
submit "Save"
|
submit "Save"
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,6 +37,7 @@ defmodule TempleDemoWeb.TempleFeatureTest do
|
||||||
s |> click(Query.option("21"))
|
s |> click(Query.option("21"))
|
||||||
end)
|
end)
|
||||||
|> fill_in(Query.text_field("Author"), with: "Mitchelob Ultra")
|
|> fill_in(Query.text_field("Author"), with: "Mitchelob Ultra")
|
||||||
|
|> assert_has(Query.css("#disabled-input[disabled]"))
|
||||||
|> click(Query.button("Save"))
|
|> click(Query.button("Save"))
|
||||||
|> assert_text("Post created successfully.")
|
|> assert_text("Post created successfully.")
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,6 +19,14 @@ defmodule Temple do
|
||||||
id
|
id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Attributes that result in boolean values will be emitted as a boolean attribute. Examples of boolean attributes are `disabled` and `checked`.
|
||||||
|
|
||||||
|
input type: "text", disabled: true
|
||||||
|
# <input type="text" disabled>
|
||||||
|
|
||||||
|
input type: "text", disabled: false
|
||||||
|
# <input type="text">
|
||||||
|
|
||||||
# if and unless expressions can be used to conditionally render content
|
# if and unless expressions can be used to conditionally render content
|
||||||
if 5 > 0 do
|
if 5 > 0 do
|
||||||
p do
|
p do
|
||||||
|
@ -61,7 +69,9 @@ defmodule Temple do
|
||||||
|
|
||||||
There are two "modes", `:normal` (the default) and `:live_view`.
|
There are two "modes", `:normal` (the default) and `:live_view`.
|
||||||
|
|
||||||
In `:live_view` mode, Temple emits markup that uses functions provided by Phoenix LiveView in order to be fully "diff trackable".
|
In `:live_view` mode, Temple emits markup that uses functions provided by Phoenix LiveView in order to be fully "diff trackable". These LiveView functions have not been released yet, so if you are going to combine Temple with LiveView, you need to use the latest unreleased default branch from GitHub.
|
||||||
|
|
||||||
|
You should use `:live_view` mode even if you only have a single LiveView.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :temple, :mode, :normal # default
|
config :temple, :mode, :normal # default
|
||||||
|
|
|
@ -18,11 +18,11 @@ defmodule Temple.Parser.Utils do
|
||||||
for {name, value} <- attrs, into: "" do
|
for {name, value} <- attrs, into: "" do
|
||||||
name = snake_to_kebab(name)
|
name = snake_to_kebab(name)
|
||||||
|
|
||||||
case value do
|
cond do
|
||||||
{_, _, _} = macro ->
|
(not is_binary(value) && Macro.quoted_literal?(value)) || match?({_, _, _}, value) ->
|
||||||
" " <> name <> "=\"<%= " <> Macro.to_string(macro) <> " %>\""
|
~s|<%= {:safe, Temple.Parser.Utils.build_attr("#{name}", #{Macro.to_string(value)})} %>|
|
||||||
|
|
||||||
value ->
|
true ->
|
||||||
" " <> name <> "=\"" <> to_string(value) <> "\""
|
" " <> name <> "=\"" <> to_string(value) <> "\""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -37,10 +37,22 @@ defmodule Temple.Parser.Utils do
|
||||||
for {name, value} <- attrs, name not in [:inner_block, :inner_content], into: "" do
|
for {name, value} <- attrs, name not in [:inner_block, :inner_content], into: "" do
|
||||||
name = snake_to_kebab(name)
|
name = snake_to_kebab(name)
|
||||||
|
|
||||||
" " <> name <> "=\"" <> to_string(value) <> "\""
|
build_attr(name, value)
|
||||||
end}
|
end}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_attr(name, true) do
|
||||||
|
" " <> name
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_attr(_name, false) do
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_attr(name, value) do
|
||||||
|
" " <> name <> "=\"" <> to_string(value) <> "\""
|
||||||
|
end
|
||||||
|
|
||||||
def split_args(not_what_i_want) when is_nil(not_what_i_want) or is_atom(not_what_i_want),
|
def split_args(not_what_i_want) when is_nil(not_what_i_want) or is_atom(not_what_i_want),
|
||||||
do: {[], []}
|
do: {[], []}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ defmodule Temple.Parser.NonvoidElementsAliasesTest do
|
||||||
|> Temple.Generator.to_eex()
|
|> Temple.Generator.to_eex()
|
||||||
|
|
||||||
assert result |> :erlang.iolist_to_binary() ==
|
assert result |> :erlang.iolist_to_binary() ==
|
||||||
~s|<div class="foo" id="<%= var %>">\n<select>\n<option>\nfoo\n\n</option>\n</select>\n</div>|
|
~s|<div class="foo"<%= {:safe, Temple.Parser.Utils.build_attr("id", var)} %>>\n<select>\n<option>\nfoo\n\n</option>\n</select>\n</div>|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,7 +67,7 @@ defmodule Temple.Parser.TempleNamespaceNonvoidTest do
|
||||||
|> Temple.Generator.to_eex()
|
|> Temple.Generator.to_eex()
|
||||||
|
|
||||||
assert result |> :erlang.iolist_to_binary() ==
|
assert result |> :erlang.iolist_to_binary() ==
|
||||||
~s|<div class="foo" id="<%= var %>">\nfoo\n\n</div>|
|
~s|<div class="foo"<%= {:safe, Temple.Parser.Utils.build_attr("id", var)} %>>\nfoo\n\n</div>|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,17 +8,19 @@ defmodule Temple.Parser.UtilsTest do
|
||||||
attrs_map = %{
|
attrs_map = %{
|
||||||
class: "text-red",
|
class: "text-red",
|
||||||
id: "form1",
|
id: "form1",
|
||||||
|
disabled: false,
|
||||||
inner_block: %{}
|
inner_block: %{}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs_kw = [
|
attrs_kw = [
|
||||||
class: "text-red",
|
class: "text-red",
|
||||||
id: "form1",
|
id: "form1",
|
||||||
|
disabled: true,
|
||||||
inner_block: %{}
|
inner_block: %{}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert {:safe, ~s| class="text-red" id="form1"|} == Utils.runtime_attrs(attrs_map)
|
assert {:safe, ~s| class="text-red" id="form1"|} == Utils.runtime_attrs(attrs_map)
|
||||||
assert {:safe, ~s| class="text-red" id="form1"|} == Utils.runtime_attrs(attrs_kw)
|
assert {:safe, ~s| class="text-red" id="form1" disabled|} == Utils.runtime_attrs(attrs_kw)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -89,7 +89,8 @@ defmodule TempleTest do
|
||||||
div class: foo <> " bar"
|
div class: foo <> " bar"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert result == ~s{<div class="<%= foo <> " bar" %>"></div>}
|
assert result ==
|
||||||
|
~s|<div<%= {:safe, Temple.Parser.Utils.build_attr("class", foo <> " bar")} %>></div>|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renders an attribute on a div passed as a variable as eex" do
|
test "renders an attribute on a div passed as a variable as eex" do
|
||||||
|
@ -101,7 +102,7 @@ defmodule TempleTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
assert result ==
|
assert result ==
|
||||||
~s{<div class="<%= Enum.map([:one, :two], fn x -> x end) %>"><div class="hi"></div></div>}
|
~s|<div<%= {:safe, Temple.Parser.Utils.build_attr("class", Enum.map([:one, :two], fn x -> x end))} %>><div class="hi"></div></div>|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renders a for comprehension as eex" do
|
test "renders a for comprehension as eex" do
|
||||||
|
@ -335,4 +336,20 @@ defmodule TempleTest do
|
||||||
assert evaluate_template(result, assigns) ==
|
assert evaluate_template(result, assigns) ==
|
||||||
~s{<div>foo</div><hr><div>foo</div><hr class="foofoo"><div>bar</div><hr class="foofoo"><div>bar</div>}
|
~s{<div>foo</div><hr><div>foo</div><hr class="foofoo"><div>bar</div><hr class="foofoo"><div>bar</div>}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "boolean attributes" do
|
||||||
|
assigns = %{is_true: true, is_false: false}
|
||||||
|
|
||||||
|
result =
|
||||||
|
temple do
|
||||||
|
input type: "text", disabled: true
|
||||||
|
input type: "text", disabled: false
|
||||||
|
|
||||||
|
input type: "text", disabled: @is_true
|
||||||
|
input type: "text", disabled: @is_false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert evaluate_template(result, assigns) ==
|
||||||
|
~s{<input type="text" disabled>\n<input type="text">\n<input type="text" disabled>\n<input type="text">}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Reference in a new issue