Got to say, this is pretty great. Far preferable to writing eex. People should definitely give it a look.
Glad you like it!
Hopefully I can get 0.6.0 released soon. I currently am in the market for a new computer, which is one of the reasons why itâs been taking so long.
I very much like the approach Temple takes in parsing.
Out of curiosity and because I think it improves the readability of templates further by removing more boilerplate, I was wondering if if would be possible to support shorthand class-syntax, i.e. div.large.red.button do ... end
being turned into <div class="large red button">... </div>
.
Since you are parsing the quoted AST manually, I think this should be possible.
What do you think?
Just seen this work, great work!
Out of curiosity, did you do any performance benchmarking with barebones phoenix.html and your library?
It would be an interesting test and maybe +1 for your libraries benefits
If you are talking about runtime performance: There will not be any difference, as at compile-time the DSL gets turned into the same IOlist format as .eex
-templates are. So at runtime there is not any difference.
I very much like the approach Temple takes in parsing.
Thanks!
Out of curiosity and because I think it improves the readability of templates further by removing more boilerplate, I was wondering if if would be possible to support shorthand class-syntax, i.e.
div.large.red.button do ... end
being turned into<div class="large red button">... </div>
.
Since you are parsing the quoted AST manually, I think this should be possible.What do you think?
I think that this is technically feasible, but I would have to see some more use cases before considering adding something like that. If youâd like, please open a Discussion on GitHub and we can discuss the feature further!
Out of curiosity, did you do any performance benchmarking with barebones phoenix.html and your library?
As of the 0.6.0 pre-releases, Temple generates EEx at compile time. So if you were to be using it with a Phoenix project, you can use the Temple.Engine or Temple.LiveViewEngine to further compile the generated EEx using the Phoenix.HTML.Engine or Phoenix.LiveView.Engine, which will be compiled the same way a traditional phoenix project would
So, the compiling will be slower as it includes an extra step, but once youâre at runtime it should be identical to a traditional phoenix project.
In the 6.0 RC, I had this component, which acted as a wrapper around live_redirect to make them look like buttons. It mostly just takes any arguments you pass to it, injects some css classes and passes it all down to live_redirect.
In the release I get an error around protocol Phoenix.HTML.Safe not implemented for #Function<27.16960434...
.
Calling live_redirect
without splat
actually works fine, I think itâs to do with the order of expansion inside temples macros (just guessing at how Temple works internally).
Is this kind of component still possible?
defmodule AppWeb.Component.LiveRedirect do
import Temple.Component
# ... snip
# convert any given arguments (as map) to keyword list
# for use in live_redirect
def splat(assigns) do
assigns
|> Map.delete(:inner_content) # needs change/not needed
|> set_defaults()
|> maybe_merge_class()
|> Enum.into([])
end
render do
case assigns[:disabled] do
true ->
span splat(assigns) do
slot :default
end
_ ->
Phoenix.LiveView.Helpers.live_redirect splat(assigns) do
slot :default
end
end
end
end
I think youâll want to rename :inner_content to :inner_block in your splat function.
Oh geez. Yes, that fixed it.
I knew inner_content
had been replaced but the error from elixir tricked me I guess and I had left that change on the âfuture fixâ list.
Love Temple, itâs great.
Internally, slots are represented as a function, so that is why it was saying it the Safe protocol isnât implemented for type Function.
I actually have some protection against this tho with regard to rendering attributes, but it seems it doesnât currently apply when you donât pass any list literal.
I opened an issue for this: [bug] Don't render the inner_block assign when building element attributes · Issue #132 · mhanberg/temple · GitHub
Oh, I think this actually work as expected. What you were experiencing is when the live_redirect
function trying to compile the attrs. youâll have to make sure that donât passthrough the inner block key yourself in that case.
This is because it compiles to
<%= case assigns[:disabled] do %>
<% true -> %>
<span <%= Temple.Parser.Utils.runtime_attrs(splat(assigns)) %>>
<%= Temple.Component.__render_block__(@inner_block, {:default, %{}}) %>
</span>
<% _ -> %>
<%= Phoenix.LiveView.Helpers.live_redirect(splat(assigns)) do %>
<%= Temple.Component.__render_block__(@inner_block, {:default, %{}}) %>
<% end %>
<% end %>
as you can see, the splat passed to the span is run through a temple function that will filter out :inner_block, but that canât happen when you pass the splat to live_redirect. So, you will have to change the Map.delete call in your code snippet to account for :inner_block
That makes sense.
I was considering passing my assigns to Temple.Parser.Util.runtime_attrs()
to avoid any future dropbears, but it returns a string, and smells like a private API.
I wonder if a designated clean_attrs_keys
or something would be good (or map_to_attrs_list(map()) :: keyword()
). I.E:
def splat(assigns) do
assigns
|> munge_etc()
|> Enum.into([])
|> Temple.clean_attributes_keys()
end
Not sure how common the splat pattern is. Itâs very useful for wrapping standard phx stuff but I doubt I would want to take on the maintenance burden if I were writing Temple.
I will probably just extract splat into itâs own module and note where to check for keys I should be dropping if something breaks.
I was considering passing my assigns to
Temple.Parser.Util.runtime_attrs()
to avoid any future dropbears, but it returns a string, and smells like a private API.
Yes, do not use that function .