Skip to content

Commit

Permalink
Only collect slots in the root of a component
Browse files Browse the repository at this point in the history
slot definitions in a component instance can only exist in the root of
that component, with root being defined as the lexical scoping of the
slot still being the component it's defined in.

Fixes #126
  • Loading branch information
mhanberg committed May 23, 2021
1 parent 978df64 commit 15a999d
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,7 +2,9 @@

## Main

Nothing Yet
### Bug fixes

- Only collect slots in the root of a component instance #127

## 0.6.0 The LiveView compatibility release!

Expand Down
22 changes: 13 additions & 9 deletions lib/temple/parser/components.ex
Expand Up @@ -19,27 +19,31 @@ defmodule Temple.Parser.Components do

{do_and_else, assigns} = Temple.Parser.Utils.consolidate_blocks(do_and_else, args)

{default_slot, named_slots} =
{default_slot, {_, named_slots}} =
if children = do_and_else[:do] do
Macro.postwalk(
Macro.prewalk(
children,
%{},
{component_module, %{}},
fn
{:slot, _, [name | args]} = node, named_slots ->
{:c, _, [name | _]} = node, {_, named_slots} ->
{node, {name, named_slots}}

{:slot, _, [name | args]} = node, {^component_module, named_slots} ->
{assigns, slot} = split_assigns_and_children(args, Macro.escape(%{}))

if is_nil(slot) do
{node, named_slots}
{node, {component_module, named_slots}}
else
{nil, Map.put(named_slots, name, %{assigns: assigns, slot: slot})}
{nil,
{component_module, Map.put(named_slots, name, %{assigns: assigns, slot: slot})}}
end

node, named_slots ->
{node, named_slots}
node, acc ->
{node, acc}
end
)
else
{nil, %{}}
{nil, {nil, %{}}}
end

children =
Expand Down
39 changes: 39 additions & 0 deletions test/parser/components_test.exs
Expand Up @@ -131,6 +131,45 @@ defmodule Temple.Parser.ComponentsTest do
children: []
} = ast
end

test "slots should only be assigned to the component root" do
raw_ast =
quote do
c Card do
c Card.Footer do
c LinkList, socials: @user.socials do
"hello"

slot :default, %{text: text, url: url} do
a class: "text-blue-500 hover:underline", href: url do
text
end
end
end
end
end
end

ast = Components.run(raw_ast)

assert Kernel.==(ast.slots, [])

assert %Components{
children: [
%Components{
children: [
%Components{
slots: [
%Slottable{
name: :default
}
]
}
]
}
]
} = ast
end
end

describe "Temple.Generator.to_eex/1" do
Expand Down

0 comments on commit 15a999d

Please sign in to comment.