Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Specs #1

Merged
merged 2 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 25 additions & 24 deletions lib/francis_htmx.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,27 @@ defmodule FrancisHtmx do
@doc """
Renders htmx content by loading htmx.js and rendering binary content.
"""
@spec htmx((Plug.Conn.t() -> binary()), Keyword.t()) :: Macro.t()
defmacro htmx(content, opts \\ []) do
title = Keyword.get(opts, :title, "")
head = Keyword.get(opts, :head, "")

quote location: :keep do
get("/", fn conn ->
root(unquote(content).(conn), unquote(opts))
"""
<!DOCTYPE html>
<html>
<head>
#{unquote(head)}

<script src="https://unpkg.com/htmx.org/dist/htmx.js"></script>
<title>#{unquote(title)}</title>
</head>
<body>
#{unquote(content).(conn)}
</body>
</html>
"""
end)
end
end
Expand All @@ -52,35 +69,19 @@ defmodule FrancisHtmx do

Requires a variable named "assigns" to exist and be set to a map.
"""
@spec sigil_E(String.t(), Keyword.t()) :: Macro.t()
defmacro sigil_E(content, _opts \\ []) do
unless Macro.Env.has_var?(__CALLER__, {:assigns, nil}) do
raise "~E requires a variable named \"assigns\" to exist and be set to a map"
end

quote location: :keep do
unquote(content)
|> EEx.eval_string([assigns: var!(assigns)], engine: Phoenix.HTML.Engine)
|> then(fn {:safe, content} -> Enum.join(content) end)
end
end
content =
EEx.eval_string(unquote(content), [assigns: var!(assigns)], engine: Phoenix.HTML.Engine)

@doc """
Renders the root content with htmx.js loaded required for the htmx/1 macro.
"""
def root(content, opts) when is_binary(content) do
title = Keyword.get(opts, :title, "")

"""
<!DOCTYPE html>
<html>
<head>
<title>#{title}</title>
<script src="https://unpkg.com/htmx.org/dist/htmx.js"></script>
</head>
<body>
#{content}
</body>
</html>
"""
content
|> Phoenix.HTML.html_escape()
|> Phoenix.HTML.safe_to_string()
end
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule FrancisHtmx.MixProject do
use Mix.Project
@version "0.1.0"
@version "0.1.1"
def project do
[
name: "Francis HTMX",
Expand Down
30 changes: 24 additions & 6 deletions test/francis_htmx_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,18 @@ defmodule FrancisHtmxTest do

assert html
|> Floki.find("script")
|> Floki.attribute("src") == ["https://unpkg.com/htmx.org/dist/htmx.js"]
|> Floki.attribute("src") == [
"https://cdn.tailwindcss.com",
"https://unpkg.com/htmx.org/dist/htmx.js"
]

assert html
|> Floki.find("link")
|> Floki.attribute("href") == ["/app.css"]

assert html
|> Floki.find("title")
|> Floki.text() == "Testing HTMX"

assert html
|> Floki.find("body")
Expand All @@ -23,11 +34,18 @@ defmodule FrancisHtmxTestHandler do
use Francis
import FrancisHtmx

htmx(fn _ ->
assigns = %{title: "test"}
htmx(
fn _ ->
assigns = %{title: "test"}

~E"""
<div><%= @title %></div>
~E"""
<div><%= @title %></div>
"""
end,
title: "Testing HTMX",
head: """
<script src="https://cdn.tailwindcss.com"></script>
<link href="/app.css" rel="stylesheet">
"""
end)
)
end
Loading