Skip to content
Open
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ See more examples below:
* [`examples/demo_hooks.exs`]
* [`examples/demo_endpoint.exs`]
* [`examples/demo_live_pubsub.exs`]
* [`examples/demo_static_files/demo_static_files.exs`]
* [`examples/demo_static_files/demo_static_files_test.exs`]

## License

Expand All @@ -87,3 +89,5 @@ limitations under the License.
[`examples/demo_hooks.exs`]: examples/demo_hooks.exs
[`examples/demo_endpoint.exs`]: examples/demo_endpoint.exs
[`examples/demo_live_pubsub.exs`]: examples/demo_live_pubsub.exs
[`examples/demo_static_files/demo_static_files.exs`]: examples/demo_static_files/demo_static_files.exs
[`examples/demo_static_files/demo_static_files_test.exs`]: examples/demo_static_files/demo_static_files_test.exs
5 changes: 5 additions & 0 deletions examples/demo_static_files/assets/inc.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions examples/demo_static_files/assets/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* app.css */
body {
font-family: "Helvetica", "Arial", sans-serif;
background-color: #f9fafb;
color: #333;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 1em;
padding: 1em;
}

span {
font-size: 2.5rem;
font-weight: 600;
margin-bottom: 1rem;
color: #1e293b;
}

button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
margin-left: 20px;
border-radius: 30%;
background-color: #2563eb;
cursor: pointer;
transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out;
}

button img {
width: 32px;
height: 32px;
filter: invert(100%) brightness(200%);
}

button:hover {
background-color: #1d4ed8;
transform: scale(1.05);
}

button:active {
background-color: #1e40af;
transform: scale(0.98);
}
41 changes: 41 additions & 0 deletions examples/demo_static_files/demo_static_files.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Mix.install([
# TODO: Update when stable/released?
# {:phoenix_playground, "~> 0.1.9"}
{:phoenix_playground, path: Path.expand("../..", __DIR__)}
])

defmodule DemoStatic do
use Phoenix.LiveView

def mount(_params, _session, socket) do
{:ok, assign(socket, count: 0)}
end

def render(assigns) do
~H"""
<span>{@count}</span>
<button phx-click="inc">
<img src="/assets/inc.svg" alt="increment"/>
</button>

<style type="text/css">
@import url("/assets/style.css");
</style>
"""
end

def handle_event("inc", _params, socket) do
{:noreply, assign(socket, count: socket.assigns.count + 1)}
end
end

defmodule DemoPlug do
use Plug.Builder

plug Plug.Static, at: "/assets", from: Path.expand("assets", __DIR__)
end

PhoenixPlayground.start(
live: DemoStatic,
plug: DemoPlug
)
52 changes: 52 additions & 0 deletions examples/demo_static_files/demo_static_files_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Mix.install([
# TODO: Update when stable/released?
# {:phoenix_playground, "~> 0.1.9"}
{:phoenix_playground, path: Path.expand("../..", __DIR__)}
])

defmodule DemoStatic do
use Phoenix.LiveView

def mount(_params, _session, socket) do
{:ok, assign(socket, count: 0)}
end

def render(assigns) do
~H"""
<span>{@count}</span>
<button phx-click="inc">
<img src="/assets/inc.svg" alt="increment"/>
</button>

<style type="text/css">
@import url("/assets/style.css");
</style>
"""
end

def handle_event("inc", _params, socket) do
{:noreply, assign(socket, count: socket.assigns.count + 1)}
end
end

defmodule DemoPlug do
use Plug.Builder

plug Plug.Static, at: "/assets", from: Path.expand("assets", __DIR__)
end

Logger.configure(level: :warning)
ExUnit.start()

defmodule DemoStaticTest do
use ExUnit.Case
use PhoenixPlayground.Test, live: DemoStatic, plug: DemoPlug

test "static assets are served" do
conn = get(build_conn(), "/assets/inc.svg")
assert response(conn, 200) =~ "<svg"

conn = get(build_conn(), "/assets/style.css")
assert response(conn, 200) =~ "background-color"
end
end
47 changes: 33 additions & 14 deletions lib/phoenix_playground/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ defmodule PhoenixPlayground.Router do

options = endpoint.config(:phoenix_playground)

conn =
if plug = options[:plug] do
call_custom_plug(conn, plug)
else
conn
end

if conn.halted or conn.state == :sent do
conn
else
call_router(conn, options)
end
end

defp call_router(conn, options) do
cond do
options[:live] ->
PhoenixPlayground.Router.LiveRouter.call(conn, [])
Expand All @@ -23,25 +38,29 @@ defmodule PhoenixPlayground.Router do
PhoenixPlayground.Router.ControllerRouter.call(conn, [])

options[:plug] ->
# always fetch plug from app env to allow code reloading anonymous functions
plug = Application.fetch_env!(:phoenix_playground, :plug)
conn # already handled

case plug do
module when is_atom(module) ->
module.call(conn, module.init([]))
true ->
raise ArgumentError, "expected :live, :controller, or :plug, got: #{inspect(options)}"
end
end

{module, options} when is_atom(module) ->
module.call(conn, module.init(options))
defp call_custom_plug(conn, _plug) do
# always fetch plug from app env to allow code reloading anonymous functions
plug = Application.fetch_env!(:phoenix_playground, :plug)

fun when is_function(fun, 1) ->
fun.(conn)
case plug do
module when is_atom(module) ->
module.call(conn, module.init([]))

fun when is_function(fun, 2) ->
fun.(conn, [])
end
{module, options} when is_atom(module) ->
module.call(conn, module.init(options))

true ->
raise ArgumentError, "expected :live, :controller, or :plug, got: #{inspect(options)}"
fun when is_function(fun, 1) ->
fun.(conn)

fun when is_function(fun, 2) ->
fun.(conn, [])
end
end

Expand Down
9 changes: 6 additions & 3 deletions lib/phoenix_playground/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ defmodule PhoenixPlayground.Test do
Keyword.validate!(options, [
:live,
:controller,
:plug,
endpoint: PhoenixPlayground.Endpoint
])

Expand All @@ -70,9 +71,11 @@ defmodule PhoenixPlayground.Test do
setup do
options = unquote(options)

if live = options[:live] do
Application.put_env(:phoenix_playground, :live, live)
end
Enum.each([:live, :plug], fn key ->
if config = options[key] do
Application.put_env(:phoenix_playground, key, config)
end
end)

start_supervised!(
{@endpoint,
Expand Down
1 change: 1 addition & 0 deletions test/examples_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ end

Examples.run("#{__DIR__}/../examples/demo_controller_test.exs")
Examples.run("#{__DIR__}/../examples/demo_live_test.exs")
Examples.run("#{__DIR__}/../examples/demo_static_files/demo_static_files_test.exs")