defmodule PreDotHn do @moduledoc """ Documentation for `PreDotHn`. """ use Phoenix.Component require Logger import Phoenix.LiveViewTest, only: [rendered_to_string: 1] alias PreDotHn.Frontmatter alias PreDotHn.Markdown def read(path) do path |> File.read!() |> Frontmatter.front_matter_split() |> then(fn {frontmatter_text, body_text} -> {Frontmatter.make_frontmatter(path, frontmatter_text), body_text} end) |> then(fn {frontmatter, body_text} -> body = Markdown.render(body_text) Map.merge(frontmatter, %{"body" => body, "path" => path}) end) end def validate(%{"slug" => nil, "path" => path}) do {:error, "slug missing from #{path}"} end def validate(%{"slug" => "", "path" => path}) do {:error, "slug missing from #{path}"} end def validate(other), do: {:ok, other} def run() do posts = "site/**/*.md" |> Path.wildcard() |> Enum.map(&read/1) |> Enum.map(&validate/1) |> Enum.filter(fn {:error, error} -> Logger.warn(error) false {:ok, _other} -> true end) |> Enum.map(&elem(&1, 1)) |> Enum.sort_by(&Map.get(&1, "date"), :desc) |> Enum.map(&atomize_keys/1) index = make_index(posts) Enum.map([index | posts], &write_page/1) end def atomize_keys(page) do page |> Enum.map(fn {key, value} -> {String.to_atom(key), value} end) |> Enum.into(%{}) end def make_index(posts) do assigns = %{posts: posts} body = ~H""" """ |> rendered_to_string() %{ title: "Blog", slug: "blog", date: "2023-09-23", body: body } end attr(:title, :string, required: true) attr(:description, :string) slot(:inner_block, required: true) def layout(assigns) do ~H""" <%= @title %> | Robert Prehn <%= if assigns[:description] do %> <% end %> <.menu /> <%= render_slot(@inner_block) %> """ end def menu(assigns) do ~H""" """ end def write_page(%{slug: slug} = assigns) do path = if slug == "index" do Path.join(["priv", "static", "index.html"]) else directory = Path.join(["priv", "static", slug]) File.mkdir_p!(directory) Path.join(["priv", "static", slug, "index.html"]) end ~H""" <.layout title={@title} description={assigns[:description]}>
<%= {:safe, @body} %>
""" |> rendered_to_string() |> then(&File.write!(path, &1)) end end