Packages

WebAssembly is a web DSL for Elixir. You create html structure straight using do blocks. Means, you can intermix html-building blocks with full Elixir syntax. DSL output is an iolist, which you can flatten to string, but better use is to just feed it to the socket (via Plug & Cowboy). WebAssem...

Current section

Files

Jump to
webassembly lib dsl.ex
Raw

lib/dsl.ex

defmodule WebAssembly.DSL do
@moduledoc """
DSL for assembling tag blocks into iolist.
Tag blocks can be intermixed with regular Elixir syntax.
"""
alias WebAssembly.Core.St
require St
defmodule TagChunks do
@moduledoc """
Macros producing iolist with tag starts & ends plus tag attributes.
"""
import WebAssembly.Tools.Input, only: [htmlize_attrs: 1]
defmacro tag_start(tag, []) do
quote do: "\n<#{unquote(tag)}>"
end
defmacro tag_start(tag, attrs) do
quote do: ["\n<#{unquote(tag)} ", htmlize_attrs(unquote(attrs)), ">"]
end
defmacro tag_end(tag) do
quote do: "</#{unquote(tag)}>"
end
defmacro tag_only(tag, []), do:
quote do: "<#{unquote(tag)} />"
defmacro tag_only(tag, attrs) do
quote do: ["\n<#{unquote(tag)} ", htmlize_attrs(unquote(attrs)), " />"]
end
end
# basic api
defmacro builder(do: body) do
quote do
alias WebAssembly.Core.St
var!(st) = St.new
unquote(body)
St.release(var!(st))
end
end
defmacro add_val!(v) do
quote do
var!(st) = var!(st) |> St.push(unquote(v))
end
end
defmacro add_tag!(tagname, attrs, content) do
quote do
import TagChunks
add_val! tag_start(unquote(tagname), unquote(attrs))
add_val! unquote(content)
add_val! tag_end(unquote(tagname))
end
end
defmacro add_tag_void!(tagname, attrs) do
quote do
import TagChunks
add_val! tag_only(unquote(tagname), unquote(attrs))
end
end
defmacro tag(tagname, attrs\\[], rest)
defmacro tag(tagname, attrs, do: body) do
quote do
add_tag!(unquote(tagname), unquote(attrs), fn ->
builder do: unquote(body)
end.())
end
end
defmacro tag(tagname, attrs, content) do
quote do: add_tag!(unquote(tagname), unquote(attrs), unquote(content))
end
defmacro tag_void(tagname, attrs\\[]) do
quote do: add_tag_void!(unquote(tagname), unquote(attrs))
end
# pick / gather for loops & closures
defmacro pick(expr) do
quote do
unquote(expr)
var!(st)
end
end
defmacro gather(new_scope_expr) do
quote do
inner_content = case unquote(new_scope_expr) do
states when is_list(states) ->
states |> Enum.map fn st=%St{} -> St.release(st) end
st=%St{} ->
St.release(st)
end
add_val! inner_content
end
end
# todo: somehow prevent from span(span("a"))
end