This repository has been archived on 2023-08-07. You can view files and clone it, but cannot push or open issues or pull requests.
temple/lib/temple.ex

183 lines
3.9 KiB
Elixir
Raw Normal View History

2019-07-02 02:48:51 +00:00
defmodule Temple do
2019-04-15 02:35:42 +00:00
defmacro __using__(_) do
quote location: :keep do
import Temple
2019-04-15 01:44:39 +00:00
end
end
2019-05-11 16:49:34 +00:00
@doc """
Creates a markup context.
2019-07-09 02:29:41 +00:00
All tags must be called inside of a `Temple.temple/1` block.
2019-05-11 16:49:34 +00:00
Returns a safe result of the form `{:safe, result}`
## Example
```
team = ["Alice", "Bob", "Carol"]
2019-07-09 02:29:41 +00:00
temple do
2019-05-11 16:49:34 +00:00
for name <- team do
div class: "text-bold" do
text name
end
end
end
# {:safe, "<div class=\"text-bold\">Alice</div><div class=\"text-bold\">Bob</div><div class=\"text-bold\">Carol</div>"}
```
"""
2019-07-09 02:29:41 +00:00
defmacro temple([do: block] = _block) do
quote location: :keep do
import Kernel, except: [div: 2, use: 1, use: 2]
import Temple.Html
import Temple.Svg
import Temple.Form
import Temple.Link
2019-05-11 16:49:34 +00:00
with {:ok, var!(buff, Temple.Html)} <- Temple.Utils.start_buffer([]) do
unquote(block)
2019-05-11 16:49:34 +00:00
markup = Temple.Utils.get_buffer(var!(buff, Temple.Html))
2019-05-11 16:49:34 +00:00
:ok = Temple.Utils.stop_buffer(var!(buff, Temple.Html))
2019-05-11 16:49:34 +00:00
Temple.Utils.join_and_escape(markup)
end
2019-05-11 16:49:34 +00:00
end
end
@doc """
Emits a text node into the markup.
```
2019-07-09 02:29:41 +00:00
temple do
2019-05-11 16:49:34 +00:00
div do
text "Hello, world!"
end
end
# {:safe, "<div>Hello, world!</div>"}
```
"""
defmacro text(text) do
quote location: :keep do
2019-07-02 02:48:51 +00:00
Temple.Utils.put_buffer(
var!(buff, Temple.Html),
unquote(text) |> Temple.Utils.escape_content()
2019-05-11 16:49:34 +00:00
)
end
end
@doc """
Emits a Phoenix partial into the markup.
```
2019-07-09 02:29:41 +00:00
temple do
2019-05-11 16:49:34 +00:00
html lang: "en" do
head do
title "MyApp"
link rel: "stylesheet", href: Routes.static_path(@conn, "/css/app.css")
end
body do
main role: "main", class: "container" do
p get_flash(@conn, :info), class: "alert alert-info", role: "alert"
p get_flash(@conn, :error), class: "alert alert-danger", role: "alert"
partial render(@view_module, @view_template, assigns)
end
script type: "text/javascript", src: Routes.static_path(@conn, "/js/app.js")
end
end
end
```
"""
defmacro partial(partial) do
quote location: :keep do
2019-07-02 02:48:51 +00:00
Temple.Utils.put_buffer(
var!(buff, Temple.Html),
2019-07-02 02:48:51 +00:00
unquote(partial) |> Temple.Utils.from_safe()
2019-05-11 16:49:34 +00:00
)
end
end
@doc """
Defines a custom component.
Components are the primary way to extract partials and markup helpers.
## Assigns
Components accept a keyword list or a map of assigns and can be referenced in the body of the component by a module attribute of the same name.
2019-05-11 16:49:34 +00:00
This works exactly the same as EEx templates.
## Children
If a block is passed to the component, it can be referenced by a special assign called `@children`.
## Example
2019-06-01 04:02:49 +00:00
2019-05-11 16:49:34 +00:00
```
defcomponent :flex do
div id: @id, class: "flex" do
@children
end
end
2019-07-09 02:29:41 +00:00
temple do
2019-05-11 16:49:34 +00:00
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 location: :keep do
defmacro unquote(name)() do
2019-05-11 16:49:34 +00:00
outer = unquote(Macro.escape(block))
Temple.Utils.__quote__(outer)
end
defmacro unquote(name)(props_or_block)
defmacro unquote(name)([{:do, inner}]) do
outer =
unquote(Macro.escape(block))
|> Temple.Utils.__insert_props__([], inner)
2019-05-11 16:49:34 +00:00
Temple.Utils.__quote__(outer)
end
defmacro unquote(name)(props) do
outer =
unquote(Macro.escape(block))
|> Temple.Utils.__insert_props__(props, nil)
2019-05-11 16:49:34 +00:00
Temple.Utils.__quote__(outer)
2019-05-11 16:49:34 +00:00
end
defmacro unquote(name)(props, inner) do
outer =
unquote(Macro.escape(block))
|> Temple.Utils.__insert_props__(props, inner)
2019-05-11 16:49:34 +00:00
Temple.Utils.__quote__(outer)
2019-05-11 16:49:34 +00:00
end
end
end
2019-04-15 01:44:39 +00:00
end