Make SRD nicer :)

This commit is contained in:
🎷🐢 S. P. O. Clayton 2023-01-21 20:31:14 -05:00
parent d1d3c11c6c
commit aaa8de1d58
Signed by: sean
SSH Key Fingerprint: SHA256:zkuPrRvkEDiQQv1Y5yScWa6I4zhj+eiv7XnP8pxIxVU
23 changed files with 344 additions and 249 deletions

View File

@ -1,6 +1,6 @@
[
import_deps: [:ecto, :ecto_sql, :phoenix],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter],
plugins: [Phoenix.LiveView.HTMLFormatter, TailwindFormatter],
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
]

View File

@ -1,3 +1,18 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.text-shadow {
text-shadow: 0px 1px 2px rgb(0 0 0 / 50%);
}
.text-shadow-md {
text-shadow: 0px 3px 6px rgb(0 0 0 / 30%);
}
.text-shadow-lg {
text-shadow: 0px 3px 6px rgb(0 0 0 / 30%), 0px 14px 28px rgb(0 0 0 / 25%);
}
.text-shadow-none {
text-shadow: none;
}
}

View File

@ -6,10 +6,13 @@ defmodule Swornforged.Dataforged do
Req.get!("https://registry.npmjs.org/dataforged/")
|> Map.get(:body)
dataforged_raw =
manifest["versions"][version]["dist"]["tarball"]
dataforged =
get_in(manifest, ["versions", version, "dist", "tarball"])
|> Req.get!()
|> Map.get(:body)
dataforged_json =
dataforged
|> Enum.find(fn curr ->
case curr do
{'package/dist/starforged/dataforged.json', _str} -> true
@ -17,11 +20,8 @@ defmodule Swornforged.Dataforged do
end
end)
|> then(fn {_, json_str} -> json_str end)
|> Jason.decode!()
dataforged = Jason.decode!(dataforged_raw)
Cachex.put!(:swornforged, "dataforged", dataforged)
:ok
Cachex.put_many!(:swornforged, dataforged_raw: dataforged, dataforged_json: dataforged_json)
end
end

View File

@ -0,0 +1,8 @@
defmodule Swornforged.KernelHelpers do
def get_in(data, keys, default) do
case get_in(data, keys) do
nil -> default
result -> result
end
end
end

View File

@ -0,0 +1,13 @@
defmodule Swornforged.Markdown do
@cache_prefix "HTML_CACHE::"
def get_cache_html!(markdown, key, options \\ []) do
case Cachex.get(:swornforged, @cache_prefix <> key) do
{:ok, nil} ->
html = Earmark.as_html!(markdown, options)
Cachex.put!(:swornforged, @cache_prefix <> key, html)
html
{:ok, html} -> html
end
end
end

View File

@ -46,6 +46,9 @@ defmodule SwornforgedWeb do
import SwornforgedWeb.Gettext
unquote(verified_routes())
# Include general helpers for kernel functions
unquote(kernel_helpers())
end
end
@ -55,6 +58,9 @@ defmodule SwornforgedWeb do
layout: {SwornforgedWeb.Layouts, :app}
unquote(html_helpers())
# Include general helpers for kernel functions
unquote(kernel_helpers())
end
end
@ -63,6 +69,9 @@ defmodule SwornforgedWeb do
use Phoenix.LiveComponent
unquote(html_helpers())
# Include general helpers for kernel functions
unquote(kernel_helpers())
end
end
@ -76,6 +85,15 @@ defmodule SwornforgedWeb do
# Include general helpers for rendering HTML
unquote(html_helpers())
# Include general helpers for kernel functions
unquote(kernel_helpers())
end
end
defp kernel_helpers do
quote do
import Swornforged.KernelHelpers
end
end
@ -87,6 +105,9 @@ defmodule SwornforgedWeb do
import SwornforgedWeb.CoreComponents
import SwornforgedWeb.Gettext
# Markdown helpers
alias Swornforged.Markdown
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS

View File

@ -1,36 +1,26 @@
<header class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between border-b border-zinc-100 py-3">
<header class="sticky top-0 px-4 sm:px-6 dark:text-white lg:px-8 bg-white dark:bg-zinc-700 border-b border-zinc-200 dark:border-zinc-900 shadow">
<div class="flex items-center justify-between py-3">
<div class="flex items-center gap-4">
<a href="/">
<svg viewBox="0 0 71 48" class="h-6" aria-hidden="true">
<path
d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z"
fill="#FD4F00"
/>
</svg>
<h1 class="font-bold">Swornforged</h1>
</a>
<p class="rounded-full bg-brand/5 px-2 text-[0.8125rem] font-medium leading-6 text-brand">
v1.7
<p class="rounded-full bg-emerald-600/5 dark:bg-emerald-600/50 dark:text-emerald-300/75 px-2 text-[0.8125rem] font-medium leading-6 text-emerald-600">
<a href={"https://github.com/rsek/dataforged/releases/tag/v" <> Application.get_env(:swornforged, :dataforged_version)}>v<%= Application.get_env(:swornforged, :dataforged_version) %></a>
</p>
</div>
<div class="flex items-center gap-4">
<a
href="https://twitter.com/elixirphoenix"
class="text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
href="https://github.com/rsek/dataforged/"
class="text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:text-zinc-700 dark:text-zinc-100 dark:hover:text-zinc-300"
>
@elixirphoenix
Dataforged
</a>
<a
href="https://github.com/phoenixframework/phoenix"
class="text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
href="https://www.ironswornrpg.com/buy"
class="rounded-lg bg-teal-600 text-white hover:bg-teal-500 text-shadow focus:bg-teal-500 px-2 py-1 text-[0.8125rem] font-semibold leading-6 shadow-sm"
>
GitHub
</a>
<a
href="https://hexdocs.pm/phoenix/overview.html"
class="rounded-lg bg-zinc-100 px-2 py-1 text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:bg-zinc-200/80 active:text-zinc-900/70"
>
Get Started <span aria-hidden="true">&rarr;</span>
Buy Ironsworn <span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>
@ -52,4 +42,4 @@
</.flash>
<%= @inner_content %>
</div>
</main>
</main>

View File

@ -11,7 +11,7 @@
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script>
</head>
<body class="bg-gray-100 dark:bg-gray-900 antialiased">
<body class="bg-zinc-100 dark:bg-zinc-900 antialiased">
<%= @inner_content %>
</body>
</html>

View File

@ -2,8 +2,6 @@ defmodule SwornforgedWeb.PageController do
use SwornforgedWeb, :controller
def home(conn, _params) do
# The home page is often custom made,
# so skip the default app layout.
render(conn, :home, layout: false, dataforged: Cachex.get!(:swornforged, "dataforged"))
render(conn, :home, dataforged: Cachex.get!(:swornforged, :dataforged_json))
end
end

View File

@ -3,29 +3,31 @@ defmodule SwornforgedWeb.PageHTML do
embed_templates "page_html/*"
def get_in(data, keys, default) do
case get_in(data, keys) do
nil -> default
result -> result
end
def srd_header(assigns) do
~H"""
<header class="bg-white dark:bg-zinc-700 shadow-md p-4">
<h1 class="text-4xl font-bold text-center dark:text-white"><%= @title %></h1>
</header>
"""
end
def srd_category_card(assigns) do
assigns =
assign(assigns,
card_colors: %{
:asset_types => "bg-blue-500",
:encounters => "bg-rose-500",
:move_categories => "bg-violet-500",
:oracle_categories => "bg-amber-500"
:asset_types => "bg-sky-500 hover:bg-sky-400 dark:bg-sky-900 border-sky-500/50 dark:focus:border-sky-500/100 dark:focus:bg-sky-800 dark:hover:border-sky-500/100 dark:hover:bg-sky-800 light:shadow-sky-700/25 light:hover:shadow-sky-700/50",
:encounters => "bg-red-500 hover:bg-red-400 dark:bg-red-900 border-red-500/50 dark:focus:border-red-500/100 dark:focus:bg-red-800 dark:hover:border-red-500/100 dark:hover:bg-red-800 light:shadow-red-700/25 light:hover:shadow-red-700/50",
:move_categories => "bg-emerald-500 hover:bg-emerald-400 dark:bg-emerald-900 border-emerald-500/50 dark:focus:border-emerald-500/100 dark:focus:bg-emerald-800 dark:hover:border-emerald-500/100 dark:hover:bg-emerald-800 light:shadow-emerald-700/25 light:hover:shadow-emerald-700/50",
:oracle_categories => "bg-purple-500 hover:bg-purple-400 dark:bg-purple-900 border-purple-500/50 dark:focus:border-purple-500/100 dark:focus:bg-purple-800 dark:hover:border-purple-500/100 dark:hover:bg-purple-800 light:shadow-purple-700/25 light:hover:shadow-purple-700/50"
}
)
~H"""
<a
href="/"
href={@to}
class={[
"block grid place-items-center text-white text-xl text-center md:text-2xl lg:text-3xl text-white rounded shadow-xl focus:shadow-2xl hover:shadow-2xl transition-shadow border-2 border-solid border-black border-opacity-10",
"block py-8 md:py-12 lg:py-16 grid place-items-center text-white text-xl text-center md:text-2xl lg:text-3xl text-white rounded text-shadow
shadow-xl focus:shadow-2xl hover:shadow-2xl transition-shadow border-2 border-solid border-black border-opacity-10",
@card_colors[@category]
]}
>
@ -33,75 +35,4 @@ defmodule SwornforgedWeb.PageHTML do
</a>
"""
end
def srd_header(assigns) do
~H"""
<header class="bg-white dark:bg-slate-700 shadow-md p-4">
<h1 class="text-4xl font-bold text-center dark:text-white"><%= @title %></h1>
</header>
"""
end
def srd_type_title(assigns) do
~H"""
<h2 class="text-3xl dark:text-white font-bold"><%= render_slot(@inner_block) %></h2>
"""
end
def srd_subtype_title(assigns) do
~H"""
<h3 class="text-2xl font-bold mb-2 dark:text-white"><%= render_slot(@inner_block) %></h3>
"""
end
def srd_type_container(assigns) do
~H"""
<div class="flex flex-col gap-4">
<%= render_slot(@inner_block) %>
</div>
"""
end
def srd_item_inner_title(assigns) do
~H"""
<h4 class="font-bold dark:text-white"><%= render_slot(@inner_block) %></h4>
"""
end
def srd_item(assigns) do
~H"""
<div class="max-w-prose shadow bg-white dark:bg-slate-700 rounded-b">
<h3
class="font-bold text-white px-4 py-2 rounded-t"
style={"background-color: #{get_in(@item, ["Display", "Color"], "rgb(100 116 139)")}"}
>
<a href={"#" <> @item["$id"]}><%= render_slot(@title) %></a>
</h3>
<div class="flex flex-col gap-2">
<div :if={@inner_block != nil} class="p-4 flex flex-col gap-2">
<%= render_slot(@inner_block) %>
<p class="text-right text-sm text-gray-400 dark:text-gray-500">
<strong>Source</strong>
<br />
<%= get_in(@item, ["Source", "Title"]) %>
<span :if={get_in(@item, ["Source", "Page"])}>
p.<%= get_in(@item, ["Source", "Page"]) %>
</span>
</p>
</div>
<div
:if={false && Application.get_env(:swornforged, :datasworn_debug, false)}
class="bg-red-500 rounded-b p-2 text-white"
>
<details class="hover:cursor-default">
<summary>Raw JSON</summary>
<div class="prose align-left">
<pre><code><%= Jason.encode!(@item, pretty: true, escape: :html_safe) %></code></pre>
</div>
</details>
</div>
</div>
</div>
"""
end
end

View File

@ -1,129 +1,14 @@
<.srd_header title="Swornforged" />
<div>
<div class="p-4 grid gap-4 place-content-center
grid-cols-[repeat(2,180px)] grid-rows-[repeat(2,180px)]
md:grid-cols-[repeat(2,320px)] md:grid-rows-[repeat(2,128px)]
lg:grid-cols-[repeat(2,420px)] lg:grid-rows-[repeat(2,240px)]">
<.srd_category_card category={:asset_types} title="Asset Types" />
<.srd_category_card category={:oracle_categories} title="Oracle Categories" />
<.srd_category_card category={:move_categories} title="Move Categories" />
<.srd_category_card category={:encounters} title="Encounters" />
<section class="dark:text-zinc-100">
<div class="flex flex-col gap-2 text-center">
<h2 class="text-4xl font-black">Swornforged</h2>
<p class="text-xl">An unofficial online systems reference document<wbr /> for Ironsworn: Starforged</p>
</div>
</div>
<div class="flex flex-col gap-6 p-6">
<.srd_type_container>
<.srd_type_title>Assets</.srd_type_title>
<div :for={asset_type <- @dataforged["Asset Types"]} id={asset_type["$id"]}>
<.srd_subtype_title>
<a href={"#" <> asset_type["$id"]}><%= get_in(asset_type, ["Display", "Title"]) %></a>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={asset <- asset_type["Assets"]} id={asset["$id"]}>
<.srd_item item={asset}>
<:title><%= get_in(asset, ["Display", "Title"]) %></:title>
<ol class="flex flex-col gap-2">
<li :for={ability <- asset["Abilities"]} id={ability["$id"]}>
<div class="flex gap-6">
<input type="checkbox" disabled={true} checked={ability["Enabled"]} />
<div class="prose dark:prose-invert text-justify">
<%= raw(Earmark.as_html!(ability["Text"], compact_output: true)) %>
</div>
</div>
</li>
</ol>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>
<.srd_type_container>
<.srd_type_title>Oracles</.srd_type_title>
<div :for={oracle_category <- @dataforged["Oracle Categories"]} id={oracle_category["$id"]}>
<.srd_subtype_title>
<a href={"#" <> oracle_category["$id"]}>
<%= get_in(oracle_category, ["Display", "Title"]) %>
</a>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={oracle <- oracle_category["Oracles"]} id={oracle["$id"]}>
<.srd_item item={oracle}>
<:title><%= get_in(oracle, ["Display", "Title"]) %></:title>
<div :if={oracle["Table"]} class="prose dark:prose-invert prose-p:m-0">
<div :if={str = oracle["Description"]} class="text-justify">
<%= raw(Earmark.as_html!(str, compact_output: true)) %>
</div>
<table>
<thead>
<tr>
<th>Roll</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr :for={row <- get_in(oracle, ["Table"], [])} id={row["$id"]}>
<td style="text-align: left;"><%= row["Floor"] %>-<%= row["Ceiling"] %></td>
<td style="text-align: left;">
<%= raw(Earmark.as_html!(row["Result"], compact_output: true)) %>
</td>
</tr>
</tbody>
</table>
</div>
<div :if={oracle["Oracles"]}>
<div
:for={inner_oracle <- oracle["Oracles"]}
class="prose dark:prose-invert prose-p:m-0"
>
<.srd_item_inner_title>
<%= get_in(inner_oracle, ["Display", "Title"]) %>
</.srd_item_inner_title>
<hr class="h-px my-4 bg-slate-200 border-0 dark:bg-slate-600" />
<div :if={str = inner_oracle["Description"]} class="text-justify">
<%= raw(Earmark.as_html!(str, compact_output: true)) %>
</div>
<table>
<thead>
<tr>
<th>Roll</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr :for={row <- get_in(inner_oracle, ["Table"], [])} id={row["$id"]}>
<td style="text-align: left;"><%= row["Floor"] %>-<%= row["Ceiling"] %></td>
<td style="text-align: left;">
<%= raw(Earmark.as_html!(row["Result"], compact_output: true)) %>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>
<.srd_type_container>
<.srd_type_title>Moves</.srd_type_title>
<div :for={move_category <- @dataforged["Move Categories"]} id={move_category["$id"]}>
<.srd_subtype_title>
<a href={"#" <> move_category["$id"]}>
<%= get_in(move_category, ["Display", "Title"]) %>
</a>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={move <- move_category["Moves"]} id={move["$id"]}>
<.srd_item item={move}>
<:title><%= get_in(move, ["Display", "Title"]) %></:title>
<div class="prose dark:prose-invert">
<%= raw(
Earmark.as_html!(move["Text"], gfm: true, gfm_tables: true, compact_output: true)
) %>
</div>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>
</div>
</section>
<section class="my-8">
<div class="p-4 flex flex-col gap-4">
<.srd_category_card category={:move_categories} title="Moves" to={~p"/srd/moves"} />
<.srd_category_card category={:oracle_categories} title="Oracles" to={~p"/srd/oracles"} />
<.srd_category_card category={:asset_types} title="Assets" to={~p"/srd/assets/"} />
<.srd_category_card category={:encounters} title="Encounters" to={~p"/srd/encounters"} />
</div>
</section>

View File

@ -0,0 +1,19 @@
defmodule SwornforgedWeb.SrdController do
use SwornforgedWeb, :controller
def assets(conn, _params) do
render(conn, :assets, assets: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Asset Types"]))
end
def moves(conn, _params) do
render(conn, :moves, moves: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Move Categories"]))
end
def oracles(conn, _params) do
render(conn, :oracles, oracles: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Oracle Categories"]))
end
def encounters(conn, _params) do
render(conn, :encounters, encounters: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Encounters"]))
end
end

View File

@ -0,0 +1,68 @@
defmodule SwornforgedWeb.SrdHTML do
use SwornforgedWeb, :html
embed_templates "srd_html/*"
def srd_type_title(assigns) do
~H"""
<h2 class="text-4xl md:text-5xl lg:text-6xl dark:text-white font-bold"><%= render_slot(@inner_block) %></h2>
"""
end
def srd_subtype_title(assigns) do
~H"""
<h3 class="text-2xl font-bold mb-2 dark:text-white"><%= render_slot(@inner_block) %></h3>
"""
end
def srd_type_container(assigns) do
~H"""
<div class="flex flex-col gap-4">
<%= render_slot(@inner_block) %>
</div>
"""
end
def srd_item_inner_title(assigns) do
~H"""
<h4 class="font-bold dark:text-white"><%= render_slot(@inner_block) %></h4>
"""
end
def srd_item(assigns) do
~H"""
<div class="shadow-md dark:shadow-black/25 bg-white/50 dark:bg-zinc-700/60 rounded-b">
<h3
class="font-bold text-white px-4 py-2 rounded-t text-shadow"
style={"background-color: #{get_in(@item, ["Display", "Color"], "rgb(100 116 139)")}"}
>
<%= render_slot(@title) %>
</h3>
<div class="flex flex-col gap-2">
<div :if={@inner_block != nil} class="p-4 flex flex-col gap-2">
<%= render_slot(@inner_block) %>
<p class="text-right text-sm text-gray-400 dark:text-gray-500">
<strong>Source</strong>
<br />
<%= get_in(@item, ["Source", "Title"]) %>
<span :if={get_in(@item, ["Source", "Page"])}>
p.<%= get_in(@item, ["Source", "Page"]) %>
</span>
</p>
</div>
<div
:if={false && Application.get_env(:swornforged, :datasworn_debug, false)}
class="bg-red-500 rounded-b p-2 text-white"
>
<details>
<summary class="hover:cursor-default">Raw JSON</summary>
<div class="prose max-w-none align-left">
<pre><code><%= Jason.encode!(@item, pretty: true, escape: :html_safe) %></code></pre>
</div>
</details>
</div>
</div>
</div>
"""
end
end

View File

@ -0,0 +1,25 @@
<.srd_type_container>
<.srd_type_title>Assets</.srd_type_title>
<div :for={asset_type <- @assets} id={asset_type["$id"]}>
<.srd_subtype_title>
<%= get_in(asset_type, ["Display", "Title"]) %>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={asset <- asset_type["Assets"]} id={asset["$id"]}>
<.srd_item item={asset}>
<:title><%= get_in(asset, ["Display", "Title"]) %></:title>
<ol class="flex flex-col gap-2">
<li :for={ability <- asset["Abilities"]} id={ability["$id"]}>
<div class="flex gap-6">
<input type="checkbox" disabled={true} checked={ability["Enabled"]} />
<div class="max-w-none prose dark:prose-invert text-justify">
<%= raw(Markdown.get_cache_html!(ability["Text"], ability["$id"], compact_output: true)) %>
</div>
</div>
</li>
</ol>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>

View File

@ -0,0 +1,28 @@
<.srd_type_container>
<.srd_type_title>Encounters</.srd_type_title>
<div :for={item <- @encounters} id={item["$id"]}>
<.srd_item item={item}>
<:title>
<%= get_in(item, ["Display", "Title"]) %>
</:title>
<div class="flex flex-col gap-4">
<div class="prose max-w-none text-justify dark:prose-invert">
<%= raw Markdown.get_cache_html!(item["Description"], item["$id"]) %>
</div>
<div :for={variant <- item["Variants"]} class="p-2 md:p-4">
<.srd_item item={variant}>
<:title><%= get_in(variant, ["Display", "Title"]) %></:title>
<div class="prose max-w-none text-justify dark:prose-invert">
<%= raw Markdown.get_cache_html!(variant["Description"], item["$id"]) %>
</div>
</.srd_item>
</div>
<div class="prose max-w-none text-justify dark:prose-invert">
<blockquote>
Quest Starter: <%= item["Quest Starter"] %>
</blockquote>
</div>
</div>
</.srd_item>
</div>
</.srd_type_container>

View File

@ -0,0 +1,20 @@
<.srd_type_container>
<.srd_type_title>Moves</.srd_type_title>
<div :for={move_category <- @moves} id={move_category["$id"]}>
<.srd_subtype_title>
<%= get_in(move_category, ["Display", "Title"]) %>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={move <- move_category["Moves"]} id={move["$id"]}>
<.srd_item item={move}>
<:title><%= get_in(move, ["Display", "Title"]) %></:title>
<div class="max-w-none text-justify prose dark:prose-invert">
<%= raw(
Markdown.get_cache_html!(move["Text"], move["$id"], gfm: true, gfm_tables: true, compact_output: true)
) %>
</div>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>

View File

@ -0,0 +1,63 @@
<.srd_type_container>
<.srd_type_title>Oracles</.srd_type_title>
<div :for={oracle_category <- @oracles} id={oracle_category["$id"]}>
<.srd_subtype_title>
<%= get_in(oracle_category, ["Display", "Title"]) %>
</.srd_subtype_title>
<ul class="flex flex-col gap-6">
<li :for={oracle <- oracle_category["Oracles"]} id={oracle["$id"]}>
<.srd_item item={oracle}>
<:title><%= get_in(oracle, ["Display", "Title"]) %></:title>
<div :if={oracle["Table"]} class="text-justify max-w-none prose dark:prose-invert prose-p:m-0">
<div :if={str = oracle["Description"]} class="text-justify">
<%= raw(Markdown.get_cache_html!(str, oracle["$id"], compact_output: true)) %>
</div>
<table>
<thead>
<tr>
<th>Roll</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr :for={row <- get_in(oracle, ["Table"], [])} id={row["$id"]}>
<td style="text-align: left;"><%= row["Floor"] %>-<%= row["Ceiling"] %></td>
<td style="text-align: left;">
<%= raw(Markdown.get_cache_html!(row["Result"], row["$id"], compact_output: true)) %>
</td>
</tr>
</tbody>
</table>
</div>
<div :if={oracle["Oracles"]}>
<div
:for={inner_oracle <- oracle["Oracles"]} class="p-2 md:p-4"
>
<.srd_item item={inner_oracle}>
<:title><%= get_in(inner_oracle, ["Display", "Title"]) %></:title>
<div class="prose text-justify max-w-none dark:prose-invert prose-p:m-0">
<table>
<thead>
<tr>
<th>Roll</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr :for={row <- get_in(inner_oracle, ["Table"], [])} id={row["$id"]}>
<td style="text-align: left;"><%= row["Floor"] %>-<%= row["Ceiling"] %></td>
<td style="text-align: left;">
<%= raw(Markdown.get_cache_html!(row["Result"], row["$id"] || row["Result"], compact_output: true)) %>
</td>
</tr>
</tbody>
</table>
</div>
</.srd_item>
</div>
</div>
</.srd_item>
</li>
</ul>
</div>
</.srd_type_container>

View File

@ -20,6 +20,15 @@ defmodule SwornforgedWeb.Router do
get "/", PageController, :home
end
scope "/srd/", SwornforgedWeb do
pipe_through :browser
get "/assets/", SrdController, :assets
get "/moves/", SrdController, :moves
get "/oracles/", SrdController, :oracles
get "/encounters/", SrdController, :encounters
end
# Other scopes may use custom stacks.
# scope "/api", SwornforgedWeb do
# pipe_through :api

View File

@ -32,7 +32,7 @@ defmodule Swornforged.MixProject do
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, "~> 1.7.0-rc.1", override: true},
{:phoenix, "~> 1.7.0-rc.2", override: true},
{:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.6"},
{:ecto_sqlite3, ">= 0.0.0"},
@ -53,7 +53,8 @@ defmodule Swornforged.MixProject do
{:plug_cowboy, "~> 2.5"},
{:req, "~> 0.3"},
{:cachex, "~> 3.5"},
{:earmark, "~> 1.4"}
{:earmark, "~> 1.4"},
{:tailwind_formatter, "~> 0.3.2", only: :dev, runtime: false}
]
end

View File

@ -29,7 +29,7 @@
"mint": {:hex, :mint, "1.4.2", "50330223429a6e1260b2ca5415f69b0ab086141bc76dc2fbf34d7c389a6675b2", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "ce75a5bbcc59b4d7d8d70f8b2fc284b1751ffb35c7b6a6302b5192f8ab4ddd80"},
"nimble_options": {:hex, :nimble_options, "0.5.2", "42703307b924880f8c08d97719da7472673391905f528259915782bb346e0a1b", [:mix], [], "hexpm", "4da7f904b915fd71db549bcdc25f8d56f378ef7ae07dc1d372cbe72ba950dce0"},
"nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"},
"phoenix": {:hex, :phoenix, "1.7.0-rc.1", "28d6591441347ba68da9750771cec6fe18ce040c91095a46d5d332804d5037d5", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.4", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "96d98dcf161b2784fd08a52fd480729a9eeae33773440b4e7a89d1e7e804af52"},
"phoenix": {:hex, :phoenix, "1.7.0-rc.2", "8faaff6f699aad2fe6a003c627da65d0864c868a4c10973ff90abfd7286c1f27", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.4", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "71abde2f67330c55b625dcc0e42bf76662dbadc7553c4f545c2f3759f40f7487"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
"phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"},
@ -45,7 +45,8 @@
"sleeplocks": {:hex, :sleeplocks, "1.1.2", "d45aa1c5513da48c888715e3381211c859af34bee9b8290490e10c90bb6ff0ca", [:rebar3], [], "hexpm", "9fe5d048c5b781d6305c1a3a0f40bb3dfc06f49bf40571f3d2d0c57eaa7f59a5"},
"swoosh": {:hex, :swoosh, "1.9.1", "0a5d7bf9954eb41d7e55525bc0940379982b090abbaef67cd8e1fd2ed7f8ca1a", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "76dffff3ffcab80f249d5937a592eaef7cc49ac6f4cdd27e622868326ed6371e"},
"tailwind": {:hex, :tailwind, "0.1.9", "25ba09d42f7bfabe170eb67683a76d6ec2061952dc9bd263a52a99ba3d24bd4d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "9213f87709c458aaec313bb5f2df2b4d2cedc2b630e4ae821bf3c54c47a56d0b"},
"telemetry": {:hex, :telemetry, "1.2.0", "a8ce551485a9a3dac8d523542de130eafd12e40bbf76cf0ecd2528f24e812a44", [:rebar3], [], "hexpm", "1427e73667b9a2002cf1f26694c422d5c905df889023903c4518921d53e3e883"},
"tailwind_formatter": {:hex, :tailwind_formatter, "0.3.2", "82e38496c049e2da2df6e4f81edf68f3470ee83f4859ba637b57681dfabfb9ba", [:mix], [{:phoenix_live_view, ">= 0.17.6", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "e370e5af152cc7b4350bb6616999433929e01be9e82e895f12beebdbff33a2a2"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
"unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"},