Don't recursively call generated component macros (#12)
Recursively calling the macros works fine if you `import` the whole module wherever you are using your components, but not if you `require` the module. This is because importing brings in the all the macros into the callers namespace, which allows them to be called just by the macro name. When you `require` the module, it will look for the generated 2-arity macro in the callers namespace, which probably doesn't exist. We get around this by not recursively calling them and avoiding the problem all togther. A few utility functions solves the original issue of wanting to DRY the file.
This commit is contained in:
parent
030e0f9d3c
commit
eb0fde6e83
4 changed files with 45 additions and 17 deletions
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
## Master
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Allow components to be used correctly when their module was `require`d instead of `import`ed
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Bugfixes
|
||||
|
|
|
@ -148,39 +148,33 @@ defmodule Temple do
|
|||
defmacro unquote(name)() do
|
||||
outer = unquote(Macro.escape(block))
|
||||
|
||||
quote do
|
||||
_ = unquote(outer)
|
||||
end
|
||||
Temple.Utils.__quote__(outer)
|
||||
end
|
||||
|
||||
defmacro unquote(name)(props_or_block)
|
||||
|
||||
defmacro unquote(name)([{:do, inner}]) do
|
||||
name = unquote(name)
|
||||
outer =
|
||||
unquote(Macro.escape(block))
|
||||
|> Temple.Utils.__insert_props__([], inner)
|
||||
|
||||
quote do
|
||||
unquote(name)([], unquote(inner))
|
||||
end
|
||||
Temple.Utils.__quote__(outer)
|
||||
end
|
||||
|
||||
defmacro unquote(name)(props) do
|
||||
name = unquote(name)
|
||||
outer =
|
||||
unquote(Macro.escape(block))
|
||||
|> Temple.Utils.__insert_props__(props, nil)
|
||||
|
||||
quote do
|
||||
unquote(name)(unquote(props), nil)
|
||||
end
|
||||
Temple.Utils.__quote__(outer)
|
||||
end
|
||||
|
||||
defmacro unquote(name)(props, inner) do
|
||||
outer =
|
||||
unquote(Macro.escape(block))
|
||||
|> Macro.prewalk(&Temple.Utils.insert_props(&1, props, inner))
|
||||
|> Temple.Utils.__insert_props__(props, inner)
|
||||
|
||||
name = unquote(name)
|
||||
|
||||
quote do
|
||||
_ = unquote(outer)
|
||||
end
|
||||
Temple.Utils.__quote__(outer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -60,4 +60,13 @@ defmodule Temple.Utils do
|
|||
|> Phoenix.HTML.html_escape()
|
||||
|> Phoenix.HTML.safe_to_string()
|
||||
end
|
||||
|
||||
def __quote__(outer) do
|
||||
quote do: unquote(outer)
|
||||
end
|
||||
|
||||
def __insert_props__(block, props, inner) do
|
||||
block
|
||||
|> Macro.prewalk(&Temple.Utils.insert_props(&1, props, inner))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,25 @@ defmodule TempleTest do
|
|||
use Temple
|
||||
|
||||
describe "custom component" do
|
||||
test "defcomponent works when requiring the module" do
|
||||
require Component, as: C
|
||||
|
||||
{:safe, result} =
|
||||
temple do
|
||||
C.flex()
|
||||
|
||||
C.flex([])
|
||||
C.flex([], [])
|
||||
|
||||
C.flex do
|
||||
text "hi"
|
||||
end
|
||||
end
|
||||
|
||||
assert result ==
|
||||
~s{<div class="flex"></div><div class="flex"></div><div class="flex"></div><div class="flex"></div>}
|
||||
end
|
||||
|
||||
test "defines a basic component" do
|
||||
import Component
|
||||
|
||||
|
|
Reference in a new issue