Extract Form module and rename Html module to Tags

This commit is contained in:
Mitchell Hanberg 2019-05-10 15:55:07 -04:00
parent 80fadb1b15
commit 71e6c91c8f
5 changed files with 107 additions and 78 deletions

View file

@ -5,7 +5,8 @@ defmodule Dsl do
defmacro __using__(_) do
quote do
import Dsl.Html
import Dsl.Tags
import Dsl.Form
end
end
end

60
lib/dsl/form.ex Normal file
View file

@ -0,0 +1,60 @@
defmodule Dsl.Form do
alias Phoenix.HTML
alias Dsl.Utils
@doc """
Generates an empty form tag.
See `Dsl.Form.form_for/4` for more details
"""
defmacro form_for(form_data, action) do
quote do
form_for(unquote_splicing([form_data, action]), [])
end
end
@doc """
Generates a form tag with a form builder and a block.
The form builder will be available inside the block through the `form` variable.
This is a wrapper around the `Phoenix.HTML.Form.form_for/4` function and accepts all of the same options.
## Example
```
htm do
form_for @conn, Routes.some_path(@conn, :create) do
text_input form, :name
end
end
# {:safe,
# "<form accept-charset=\"UTF-8\" action=\"/\" method=\"post\">
# <input name=\"_csrf_token\" type=\"hidden\" value=\"AS5qfX1gcns6eU56BlQgBlwCDgMlNgAAiJ0MR91Kh3v3bbCS5SKjuw==\">
# <input name=\"_utf8\" type=\"hidden\" value=\"✓\">
# <input id=\"name\" name=\"name\" type=\"text\">
# </form>"}
```
"""
defmacro form_for(form_data, action, opts \\ [], block) do
quote do
var!(form) = HTML.Form.form_for(unquote_splicing([form_data, action, opts]))
Utils.put_buffer(var!(buff, Dsl.Tags), var!(form) |> HTML.Safe.to_iodata())
_ = unquote(block)
Utils.put_buffer(var!(buff, Dsl.Tags), "</form>")
end
end
@doc """
Please see `Phoenix.HTML.Form.text_input/3` for details.
"""
defmacro text_input(form, field, opts \\ []) do
quote do
{:safe, input} = HTML.Form.text_input(unquote_splicing([form, field, opts]))
Utils.put_buffer(var!(buff, Dsl.Tags), input)
end
end
end

View file

@ -1,4 +1,4 @@
defmodule Dsl.Html do
defmodule Dsl.Tags do
alias Phoenix.HTML
alias Dsl.Utils
@ -33,7 +33,7 @@ defmodule Dsl.Html do
@doc """
Creates a markup context.
All tags must be called inside of a `Dsl.Html.htm/1` block.
All tags must be called inside of a `Dsl.Tags.htm/1` block.
Returns a safe result of the form `{:safe, result}`
@ -59,13 +59,13 @@ defmodule Dsl.Html do
import HTML.Link, except: [link: 1, link: 2]
import HTML.Form, only: []
{:ok, var!(buff, Dsl.Html)} = Utils.start_buffer([])
{:ok, var!(buff, Dsl.Tags)} = Utils.start_buffer([])
unquote(block)
markup = Utils.get_buffer(var!(buff, Dsl.Html))
markup = Utils.get_buffer(var!(buff, Dsl.Tags))
:ok = Utils.stop_buffer(var!(buff, Dsl.Html))
:ok = Utils.stop_buffer(var!(buff, Dsl.Tags))
markup |> Enum.reverse() |> Enum.join("") |> HTML.raw()
end
@ -79,8 +79,8 @@ defmodule Dsl.Html do
el = unquote(el)
quote do
Utils.put_open_tag(var!(buff, Dsl.Html), unquote(el), [])
Utils.put_close_tag(var!(buff, Dsl.Html), unquote(el))
Utils.put_open_tag(var!(buff, Dsl.Tags), unquote(el), [])
Utils.put_close_tag(var!(buff, Dsl.Tags), unquote(el))
end
end
@ -89,9 +89,9 @@ defmodule Dsl.Html do
el = unquote(el)
quote do
Utils.put_open_tag(var!(buff, Dsl.Html), unquote(el), [])
Utils.put_open_tag(var!(buff, Dsl.Tags), unquote(el), [])
_ = unquote(inner)
Utils.put_close_tag(var!(buff, Dsl.Html), unquote(el))
Utils.put_close_tag(var!(buff, Dsl.Tags), unquote(el))
end
end
@ -99,8 +99,8 @@ defmodule Dsl.Html do
el = unquote(el)
quote do
Utils.put_open_tag(var!(buff, Dsl.Html), unquote(el), unquote(attrs_or_content_or_block))
Utils.put_close_tag(var!(buff, Dsl.Html), unquote(el))
Utils.put_open_tag(var!(buff, Dsl.Tags), unquote(el), unquote(attrs_or_content_or_block))
Utils.put_close_tag(var!(buff, Dsl.Tags), unquote(el))
end
end
@ -110,9 +110,9 @@ defmodule Dsl.Html do
quote do
attrs = unquote(attrs)
Utils.put_open_tag(var!(buff, Dsl.Html), unquote(el), attrs)
Utils.put_open_tag(var!(buff, Dsl.Tags), unquote(el), attrs)
_ = unquote(inner)
Utils.put_close_tag(var!(buff, Dsl.Html), unquote(el))
Utils.put_close_tag(var!(buff, Dsl.Tags), unquote(el))
end
end
@ -121,9 +121,9 @@ defmodule Dsl.Html do
quote do
attrs = unquote(attrs)
Utils.put_open_tag(var!(buff, Dsl.Html), unquote(el), attrs)
Utils.put_open_tag(var!(buff, Dsl.Tags), unquote(el), attrs)
text unquote(content)
Utils.put_close_tag(var!(buff, Dsl.Html), unquote(el))
Utils.put_close_tag(var!(buff, Dsl.Tags), unquote(el))
end
end
end
@ -140,7 +140,7 @@ defmodule Dsl.Html do
attrs = unquote(attrs)
Utils.put_buffer(
var!(buff, Dsl.Html),
var!(buff, Dsl.Tags),
"<#{unquote(el)}#{Utils.compile_attrs(attrs)}>"
)
end
@ -163,7 +163,7 @@ defmodule Dsl.Html do
defmacro text(text) do
quote do
Utils.put_buffer(
var!(buff, Dsl.Html),
var!(buff, Dsl.Tags),
unquote(text) |> to_string |> HTML.html_escape() |> HTML.safe_to_string()
)
end
@ -198,13 +198,38 @@ defmodule Dsl.Html do
defmacro partial(partial) do
quote do
Utils.put_buffer(
var!(buff, Dsl.Html),
var!(buff, Dsl.Tags),
unquote(partial) |> Utils.from_safe()
)
end
end
defmacro defcomponent(name, do: block) do
@doc """
Defines a custom component.
```
defcomponent :flex do
div id: @id, class: "flex" do
@children
end
end
htm do
flex id: "my-flex" do
div "Item 1"
div "Item 2"
div "Item 3"
end
end
# {:safe, "<div id=\"my-flex\" class=\"flex\">
# <div>Item 1</div>
# <div>Item 2</div>
# <div>Item 3</div>
# </div>"}
```
"""
defmacro defcomponent(name, [do: _] = block) do
quote do
defmacro unquote(name)(props \\ []) do
outer = unquote(Macro.escape(block))
@ -232,60 +257,4 @@ defmodule Dsl.Html do
end
end
end
@doc """
Generates an empty form tag.
See `Dsl.Html.form_for/4` for more details
"""
defmacro form_for(form_data, action) do
quote do
form_for(unquote_splicing([form_data, action]), [])
end
end
@doc """
Generates a form tag with a form builder and a block.
The form builder will be available inside the block through the `form` variable.
This is a wrapper around the `Phoenix.HTML.Form.form_for/4` function and accepts all of the same options.
## Example
```
htm do
form_for @conn, Routes.some_path(@conn, :create) do
text_input form, :name
end
end
# {:safe,
# "<form accept-charset=\"UTF-8\" action=\"/\" method=\"post\">
# <input name=\"_csrf_token\" type=\"hidden\" value=\"AS5qfX1gcns6eU56BlQgBlwCDgMlNgAAiJ0MR91Kh3v3bbCS5SKjuw==\">
# <input name=\"_utf8\" type=\"hidden\" value=\"✓\">
# <input id=\"name\" name=\"name\" type=\"text\">
# </form>"}
```
"""
defmacro form_for(form_data, action, opts \\ [], block) do
quote do
var!(form) = HTML.Form.form_for(unquote_splicing([form_data, action, opts]))
Utils.put_buffer(var!(buff, Dsl.Html), var!(form) |> HTML.Safe.to_iodata())
_ = unquote(block)
Utils.put_buffer(var!(buff, Dsl.Html), "</form>")
end
end
@doc """
Please see `Phoenix.HTML.Form.text_input/3` for details.
"""
defmacro text_input(form, field, opts \\ []) do
quote do
{:safe, input} = HTML.Form.text_input(unquote_splicing([form, field, opts]))
Utils.put_buffer(var!(buff, Dsl.Html), input)
end
end
end

View file

@ -6,7 +6,7 @@ defmodule Mix.Tasks.UpdateMdnDocs do
@shortdoc "Update the MDN documentation"
def run(_) do
(Dsl.Html.nonvoid_elements() ++ Dsl.Html.void_elements())
(Dsl.Tags.nonvoid_elements() ++ Dsl.Tags.void_elements())
|> Enum.each(fn el ->
el = to_string(el)

View file

@ -376,7 +376,6 @@ defmodule Dsl.HtmlTest do
import Component
bob = "hi"
class = "joe"
{:safe, result} =
htm do