back to simple blog module, loading posts with elixir map frontmatter, avoiding yaml package
This commit is contained in:
parent
80da842416
commit
f6c316d4fa
11 changed files with 200 additions and 149 deletions
lib
home73k
home73k_web
|
@ -12,10 +12,9 @@ defmodule Home73k.Application do
|
|||
# Start the PubSub system
|
||||
{Phoenix.PubSub, name: Home73k.PubSub},
|
||||
# Start the Endpoint (http/https)
|
||||
Home73kWeb.Endpoint,
|
||||
Home73kWeb.Endpoint
|
||||
# Start a worker by calling: Home73k.Worker.start_link(arg)
|
||||
# {Home73k.Worker, arg}
|
||||
Home73k.Blog
|
||||
]
|
||||
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
|
|
|
@ -1,107 +1,29 @@
|
|||
defmodule Home73k.Blog do
|
||||
use GenServer
|
||||
alias Home73k.Blog.Post
|
||||
|
||||
#
|
||||
# Setup
|
||||
#
|
||||
Application.ensure_all_started(:earmark)
|
||||
|
||||
@repo Home73k.Repo.get()
|
||||
@content_path Application.compile_env(:home73k, [:content_repo, :path], "./priv/content")
|
||||
|> Path.expand()
|
||||
|
||||
#
|
||||
# Client
|
||||
#
|
||||
posts_paths =
|
||||
@content_path
|
||||
|> Path.join("**/*.md")
|
||||
|> Path.wildcard()
|
||||
|
||||
def start_link(_opts) do
|
||||
GenServer.start_link(__MODULE__, %{posts: [], tags: [], files: []}, name: __MODULE__)
|
||||
end
|
||||
posts =
|
||||
for post_path <- posts_paths do
|
||||
@external_resource Path.relative_to_cwd(post_path)
|
||||
Post.parse!(post_path)
|
||||
end
|
||||
|
||||
def get_posts() do
|
||||
GenServer.call(__MODULE__, :get_posts)
|
||||
end
|
||||
# @posts posts
|
||||
@posts Enum.sort_by(posts, & &1.date, {:desc, NaiveDateTime})
|
||||
|
||||
def get_files() do
|
||||
GenServer.call(__MODULE__, :get_files)
|
||||
end
|
||||
@tags posts |> Stream.flat_map(& &1.tags) |> Stream.uniq() |> Enum.sort()
|
||||
|
||||
# def push(pid, element) do
|
||||
# GenServer.cast(pid, {:push, element})
|
||||
# end
|
||||
|
||||
# def pop(pid) do
|
||||
# GenServer.call(pid, :pop)
|
||||
# end
|
||||
|
||||
# def put(server, key, value) do
|
||||
# GenServer.cast(server, {:put, key, value})
|
||||
# end
|
||||
|
||||
# def get(server, key) do
|
||||
# GenServer.call(server, {:get, key})
|
||||
# end
|
||||
|
||||
#
|
||||
# Server
|
||||
#
|
||||
|
||||
@impl true
|
||||
def init(state) do
|
||||
repo_all_paths = @repo.path |> Path.join("**/*.*") |> Path.wildcard()
|
||||
repo_post_paths = repo_all_paths |> Enum.filter(fn f -> String.ends_with?(f, ".md") end)
|
||||
repo_file_paths = repo_all_paths |> Enum.filter(fn f -> !String.ends_with?(f, ".md") end)
|
||||
{:ok, %{state | posts: repo_post_paths, files: repo_file_paths}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:get_posts, _from, %{posts: posts} = state) do
|
||||
{:reply, posts, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:get_files, _from, %{files: files} = state) do
|
||||
{:reply, files, state}
|
||||
end
|
||||
|
||||
# @impl true
|
||||
# def handle_call(:pop, _from, [head | tail]) do
|
||||
# {:reply, head, tail}
|
||||
# end
|
||||
|
||||
# @impl true
|
||||
# def handle_cast({:push, element}, state) do
|
||||
# {:noreply, [element | state]}
|
||||
# end
|
||||
|
||||
# def handle_cast({:put, key, value}, state) do
|
||||
# {:noreply, Map.put(state, key, value)}
|
||||
# end
|
||||
|
||||
# def handle_call({:get, key}, _from, state) do
|
||||
# {:reply, Map.fetch!(state, key), state}
|
||||
# end
|
||||
|
||||
# alias Home73k.Blog.Post
|
||||
|
||||
# @posts_dir Application.compile_env(:home73k, :blog_posts_dir, "posts")
|
||||
|
||||
# posts_paths =
|
||||
# @posts_dir
|
||||
# |> Path.join("**/*.md")
|
||||
# |> Path.wildcard()
|
||||
# |> Enum.sort()
|
||||
|
||||
# posts =
|
||||
# for post_path <- posts_paths do
|
||||
# @external_resource Path.relative_to_cwd(post_path)
|
||||
# Post.parse!(post_path)
|
||||
# end
|
||||
|
||||
# @posts Enum.sort_by(posts, & &1.date, {:desc, Date})
|
||||
|
||||
# @tags posts |> Enum.flat_map(& &1.tags) |> Enum.uniq() |> Enum.sort()
|
||||
|
||||
# def list_posts, do: @posts
|
||||
# def list_tags, do: @tags
|
||||
def list_posts, do: @posts
|
||||
def list_tags, do: @tags
|
||||
|
||||
# defmodule NotFoundError do
|
||||
# defexception [:message, plug_status: 404]
|
||||
|
|
71
lib/home73k/blog/post.ex
Normal file
71
lib/home73k/blog/post.ex
Normal file
|
@ -0,0 +1,71 @@
|
|||
defmodule Home73k.Blog.Post do
|
||||
@enforce_keys [:title, :slug, :date, :author, :tags, :summary, :body]
|
||||
defstruct [:title, :slug, :date, :author, :tags, :summary, :body]
|
||||
|
||||
@title_slug_regex ~r/[^a-zA-Z0-9 ]/
|
||||
|
||||
def parse!(post_path) do
|
||||
post_path
|
||||
|> File.read()
|
||||
|> parse_raw_file_data()
|
||||
end
|
||||
|
||||
defp parse_raw_file_data({:ok, post_data}) do
|
||||
post_data
|
||||
|> String.split("---", parts: 3)
|
||||
|> parse_split_file_data()
|
||||
end
|
||||
|
||||
defp parse_raw_file_data(_), do: nil
|
||||
|
||||
defp parse_split_file_data(["", fm, md]) do
|
||||
Code.eval_string(fm)
|
||||
|> parse_summary(md)
|
||||
end
|
||||
|
||||
defp parse_split_file_data(_), do: nil
|
||||
|
||||
defp parse_summary({%{summary: summ} = fm, _}, md) do
|
||||
Earmark.as_html(md)
|
||||
|> parse_post(Earmark.as_html(summ), fm)
|
||||
end
|
||||
|
||||
defp parse_summary({%{} = fm, _}, md) do
|
||||
String.split(md, "<!--more-->", parts: 2)
|
||||
|> parse_summary(fm)
|
||||
end
|
||||
|
||||
defp parse_summary([summ, _] = parts, fm) do
|
||||
parts
|
||||
|> Enum.join(" ")
|
||||
|> Earmark.as_html()
|
||||
|> parse_post(Earmark.as_html(summ), fm)
|
||||
end
|
||||
|
||||
defp parse_summary(md, fm) do
|
||||
Earmark.as_html(md)
|
||||
|> parse_post({:ok, nil, []}, fm)
|
||||
end
|
||||
|
||||
defp parse_title_to_slug(title) do
|
||||
Regex.replace(@title_slug_regex, title, "")
|
||||
|> String.replace(" ", "-")
|
||||
|> String.downcase()
|
||||
end
|
||||
|
||||
defp build_post(main_html, summ_html, fm) do
|
||||
fm
|
||||
|> Map.put_new(:slug, parse_title_to_slug(fm.title))
|
||||
|> Map.put_new(:author, "Author Name")
|
||||
|> Map.put_new(:tags, [])
|
||||
|> Map.put(:summary, summ_html)
|
||||
|> Map.put(:body, main_html)
|
||||
end
|
||||
|
||||
defp parse_post({:ok, main_html, _}, {:ok, summ_html, _}, fm) do
|
||||
post = build_post(main_html, summ_html, fm)
|
||||
struct!(__MODULE__, post)
|
||||
end
|
||||
|
||||
defp parse_post(_, _, _), do: nil
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
defmodule Home73kWeb.BlogFileController do
|
||||
use Home73kWeb, :controller
|
||||
|
||||
@moduledoc """
|
||||
This controller handles path requests that didn't match an existing route,
|
||||
including the main Plug.Static for the / root path.
|
||||
|
||||
To handle this situation, we'll check if the requested resource exists as
|
||||
a file under the blog content repo folder, by querying the Blog genserve.
|
||||
|
||||
If it exists, we'll redirect to the blog content static path under /_
|
||||
Otherwise, we'll return 404 not found.
|
||||
"""
|
||||
|
||||
alias Home73k.Repo
|
||||
alias Home73k.Blog
|
||||
|
||||
def index(conn, _params) do
|
||||
# What would be the content path of this requested resource?
|
||||
content_path = Repo.content_path() |> Path.join(conn.request_path)
|
||||
|
||||
# Check if it exists in the Blog's known files
|
||||
Blog.get_files()
|
||||
|> Enum.member?(content_path)
|
||||
|> case do
|
||||
true -> redirect(conn, to: "/_#{conn.request_path}")
|
||||
false -> send_resp(conn, 404, "not found")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,18 +26,6 @@ defmodule Home73kWeb.Endpoint do
|
|||
gzip: true,
|
||||
only: ~w(css fonts images js favicon.ico robots.txt DF185CEE29A3D443_public_key.asc)
|
||||
|
||||
# Blog static path handler
|
||||
if File.dir?(Home73k.Repo.content_path()) do
|
||||
plug Plug.Static,
|
||||
at: "/_",
|
||||
from: Home73k.Repo.content_path(),
|
||||
gzip: false,
|
||||
only:
|
||||
Home73k.Repo.content_path()
|
||||
|> File.ls!()
|
||||
|> Enum.filter(fn f -> !String.starts_with?(f, ".") end)
|
||||
end
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
|
|
|
@ -43,9 +43,4 @@ defmodule Home73kWeb.Router do
|
|||
live_dashboard "/dashboard", metrics: Home73kWeb.Telemetry
|
||||
end
|
||||
end
|
||||
|
||||
# Wildcard path for handling Blog Files from repo
|
||||
scope "/", Home73kWeb do
|
||||
get "/*path", BlogFileController, :index
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue