Hi.
I’m relatively new to Elixir and meta programming in particular.
For a small project of mine I thought hat a HTML DSL would be a good exercise.
But I’m stuck.
My DSL should use the Eml HTML library to generate the actual HTML.
I have the following simple macro:
defmacro tag(name, attrs, do: inner) do
IO.puts "tag(name): #{inspect(name)}"
IO.puts "tag(attrs): #{inspect(attrs)}"
IO.puts "tag(inner): #{inspect(inner)}"
ast = quote do
%Eml.Element{tag: unquote(name), attrs: Enum.into(unquote(attrs), %{}), content: unquote(inner)}
end
IO.puts "ast: #{Macro.to_string(ast)}"
ast
end
On top of this I have generated macros for the html tags like:
defmacro unquote(tag)(attrs, do: inner) do
tag = unquote(tag)
quote do: tag(unquote(tag), unquote(attrs), do: unquote(inner))
end
This is pretty much taken from Chris McCord’s book “Metaprogramming Elixir”.
So far so good.
The problem here is generating the Eml.Element type from a nested block when it contains 2 or more macros.
For a simple code like this:
html do
span id: "1", do: "MySpan1"
span id: "2", do: "MySpan2"
end
the dump of ‘inner’ from within the macro gives me this:
tag(name): :html
tag(attrs): [foo: "bar"]
tag(inner): {:__block__, [line: 60], [{:span, [line: 58], [[id: "1", do: "MySpan"]]}, {:span, [line: 59], [[id: "2", do: "MySpan2"]]}]}
ast: %Eml.Element{tag: :html, attrs: Enum.into([foo: "bar"], %{}), content: (
span(id: "1", do: "MySpan")
span(id: "2", do: "MySpan2")
)}
tag(name): :span
tag(attrs): [id: "1"]
tag(inner): "MySpan"
ast: %E{tag: :span, attrs: Enum.into([id: "1"], %{}), content: "MySpan"}
tag(name): :span
tag(attrs): [id: "2"]
tag(inner): "MySpan2"
ast: %E{tag: :span, attrs: Enum.into([id: "2"], %{}), content: "MySpan2"}
"#html<%{foo: \"bar\"} #span<%{id: \"2\"} \"MySpan2\">>"
The problem here is the:
%Eml.Element{tag: :html, attrs: Enum.into([foo: "bar"], %{}), content: (
span(id: "1", do: "MySpan")
span(id: "2", do: "MySpan2")
)}
It seems that only the last of the nested spans is taken for the content, the first one is discarded.
Is there a way this can be fixed?
Regards,
Manfred