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
|
||||
|
||||
Nothing yet
|
||||
### Enhancements
|
||||
|
||||
- [breaking] Attributes who values are boolean expressions will be emitted as boolean attributes.
|
||||
|
||||
## 0.6.2
|
||||
|
||||
|
|
15
README.md
15
README.md
|
@ -22,15 +22,6 @@ def deps do
|
|||
]
|
||||
end
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[{:temple, github: "mhanberg/temple"}]
|
||||
end
|
||||
```
|
||||
|
||||
## Goals
|
||||
|
||||
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
|
||||
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/dev.exs
|
||||
|
@ -156,6 +148,7 @@ config :your_app, YourAppWeb.Endpoint,
|
|||
```elixir
|
||||
# app.html.exs
|
||||
|
||||
"<!DOCTYPE html>"
|
||||
html lang: "en" do
|
||||
head do
|
||||
meta charset: "utf-8"
|
||||
|
@ -163,7 +156,7 @@ html lang: "en" do
|
|||
meta name: "viewport", content: "width=device-width, initial-scale=1.0"
|
||||
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
|
||||
|
||||
body do
|
||||
|
|
|
@ -22,6 +22,8 @@ c Form, changeset: @changeset, action: @action do
|
|||
text_input f, :author
|
||||
error_tag(f, :author)
|
||||
|
||||
input type: "text", disabled: true, id: "disabled-input"
|
||||
|
||||
div do
|
||||
submit "Save"
|
||||
end
|
||||
|
|
|
@ -37,6 +37,7 @@ defmodule TempleDemoWeb.TempleFeatureTest do
|
|||
s |> click(Query.option("21"))
|
||||
end)
|
||||
|> fill_in(Query.text_field("Author"), with: "Mitchelob Ultra")
|
||||
|> assert_has(Query.css("#disabled-input[disabled]"))
|
||||
|> click(Query.button("Save"))
|
||||
|> assert_text("Post created successfully.")
|
||||
end
|
||||
|
|
|
@ -19,6 +19,14 @@ defmodule Temple do
|
|||
id
|
||||
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 5 > 0 do
|
||||
p do
|
||||
|
@ -61,7 +69,9 @@ defmodule Temple do
|
|||
|
||||
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
|
||||
config :temple, :mode, :normal # default
|
||||
|
|
|
@ -18,11 +18,11 @@ defmodule Temple.Parser.Utils do
|
|||
for {name, value} <- attrs, into: "" do
|
||||
name = snake_to_kebab(name)
|
||||
|
||||
case value do
|
||||
{_, _, _} = macro ->
|
||||
" " <> name <> "=\"<%= " <> Macro.to_string(macro) <> " %>\""
|
||||
cond do
|
||||
(not is_binary(value) && Macro.quoted_literal?(value)) || match?({_, _, _}, value) ->
|
||||
~s|<%= {:safe, Temple.Parser.Utils.build_attr("#{name}", #{Macro.to_string(value)})} %>|
|
||||
|
||||
value ->
|
||||
true ->
|
||||
" " <> name <> "=\"" <> to_string(value) <> "\""
|
||||
end
|
||||
end
|
||||
|
@ -37,10 +37,22 @@ defmodule Temple.Parser.Utils do
|
|||
for {name, value} <- attrs, name not in [:inner_block, :inner_content], into: "" do
|
||||
name = snake_to_kebab(name)
|
||||
|
||||
" " <> name <> "=\"" <> to_string(value) <> "\""
|
||||
build_attr(name, value)
|
||||
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),
|
||||
do: {[], []}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ defmodule Temple.Parser.NonvoidElementsAliasesTest do
|
|||
|> Temple.Generator.to_eex()
|
||||
|
||||
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
|
||||
|
|
|
@ -67,7 +67,7 @@ defmodule Temple.Parser.TempleNamespaceNonvoidTest do
|
|||
|> Temple.Generator.to_eex()
|
||||
|
||||
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
|
||||
|
|
|
@ -8,17 +8,19 @@ defmodule Temple.Parser.UtilsTest do
|
|||
attrs_map = %{
|
||||
class: "text-red",
|
||||
id: "form1",
|
||||
disabled: false,
|
||||
inner_block: %{}
|
||||
}
|
||||
|
||||
attrs_kw = [
|
||||
class: "text-red",
|
||||
id: "form1",
|
||||
disabled: true,
|
||||
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_kw)
|
||||
assert {:safe, ~s| class="text-red" id="form1" disabled|} == Utils.runtime_attrs(attrs_kw)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -89,7 +89,8 @@ defmodule TempleTest do
|
|||
div class: foo <> " bar"
|
||||
end
|
||||
|
||||
assert result == ~s{<div class="<%= foo <> " bar" %>"></div>}
|
||||
assert result ==
|
||||
~s|<div<%= {:safe, Temple.Parser.Utils.build_attr("class", foo <> " bar")} %>></div>|
|
||||
end
|
||||
|
||||
test "renders an attribute on a div passed as a variable as eex" do
|
||||
|
@ -101,7 +102,7 @@ defmodule TempleTest do
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
test "renders a for comprehension as eex" do
|
||||
|
@ -335,4 +336,20 @@ defmodule TempleTest do
|
|||
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>}
|
||||
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
|
||||
|
|
Reference in New Issue