incorporating content and refining post parsing
This commit is contained in:
parent
f6c316d4fa
commit
b1b9c09a79
6 changed files with 118 additions and 107 deletions
|
@ -4,10 +4,10 @@ defmodule Home73k.Blog do
|
|||
Application.ensure_all_started(:earmark)
|
||||
|
||||
@content_path Application.compile_env(:home73k, [:content_repo, :path], "./priv/content")
|
||||
|> Path.expand()
|
||||
|
||||
posts_paths =
|
||||
@content_path
|
||||
|> Path.expand()
|
||||
|> Path.join("**/*.md")
|
||||
|> Path.wildcard()
|
||||
|
||||
|
@ -17,13 +17,13 @@ defmodule Home73k.Blog do
|
|||
Post.parse!(post_path)
|
||||
end
|
||||
|
||||
# @posts posts
|
||||
@posts Enum.sort_by(posts, & &1.date, {:desc, NaiveDateTime})
|
||||
@posts posts
|
||||
# @posts Enum.sort_by(posts, & &1.date, {:desc, NaiveDateTime})
|
||||
|
||||
@tags posts |> Stream.flat_map(& &1.tags) |> Stream.uniq() |> Enum.sort()
|
||||
# @tags posts |> Stream.flat_map(& &1.tags) |> Stream.uniq() |> Enum.sort()
|
||||
|
||||
def list_posts, do: @posts
|
||||
def list_tags, do: @tags
|
||||
# def list_tags, do: @tags
|
||||
|
||||
# defmodule NotFoundError do
|
||||
# defexception [:message, plug_status: 404]
|
||||
|
|
|
@ -1,71 +1,135 @@
|
|||
defmodule Home73k.Blog.Post do
|
||||
@enforce_keys [:title, :slug, :date, :author, :tags, :summary, :body]
|
||||
defstruct [:title, :slug, :date, :author, :tags, :summary, :body]
|
||||
@enforce_keys [:title, :slug, :date, :author, :tags, :lede, :body]
|
||||
defstruct [:title, :slug, :date, :author, :tags, :lede, :body]
|
||||
|
||||
@title_slug_regex ~r/[^a-zA-Z0-9 ]/
|
||||
|
||||
@doc """
|
||||
The public parse!/1 function begins the post parse process by reading
|
||||
the file. By passing through a series of other functions, it ultimately
|
||||
returns either a %Post{} or nil.
|
||||
"""
|
||||
def parse!(post_path) do
|
||||
post_path
|
||||
|> File.read()
|
||||
|> parse_raw_file_data()
|
||||
|> split_raw_file_data()
|
||||
|> parse_frontmatter()
|
||||
|> parse_lede()
|
||||
end
|
||||
|
||||
defp parse_raw_file_data({:ok, post_data}) do
|
||||
post_data
|
||||
|> String.split("---", parts: 3)
|
||||
|> parse_split_file_data()
|
||||
# """ split_raw_file_data/1
|
||||
# If we receive {:ok, file_data}, we split frontmatter from markdown
|
||||
# content and return [raw_frontmatter, markdown]. Otherwise return nil.
|
||||
# """
|
||||
defp split_raw_file_data({:ok, file_data}), do: String.split(file_data, ~r/\n-{3,}\n/, parts: 2)
|
||||
defp split_raw_file_data(_), do: nil
|
||||
|
||||
# """ parse_frontmatter/1
|
||||
# If we receive [raw_frontmatter, markdown], we parse the frontmatter.
|
||||
# Otherwise, return nil.
|
||||
# """
|
||||
defp parse_frontmatter([fm, md]) do
|
||||
case parse_frontmatter_string(fm) do
|
||||
{%{} = parsed_fm, _} -> {parsed_fm, md}
|
||||
{:error, _} -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_raw_file_data(_), do: nil
|
||||
defp parse_frontmatter(nil), do: nil
|
||||
|
||||
defp parse_split_file_data(["", fm, md]) do
|
||||
Code.eval_string(fm)
|
||||
|> parse_summary(md)
|
||||
# """ parse_lede/1
|
||||
# Look for lede/excerpt/summary in content and extract it if present.
|
||||
# We return updated frontmatter, and content with <!--more--> stripped.
|
||||
defp parse_lede({fm, md}) do
|
||||
{lede, body_md} = String.split(md, "<!--more-->", parts: 2) |> extract_lede()
|
||||
{Map.put(fm, :lede, lede), String.replace(body_md, "<!--more-->", " ")}
|
||||
end
|
||||
|
||||
defp parse_split_file_data(_), do: nil
|
||||
defp parse_lede(_), do: nil
|
||||
|
||||
defp parse_summary({%{summary: summ} = fm, _}, md) do
|
||||
Earmark.as_html(md)
|
||||
|> parse_post(Earmark.as_html(summ), fm)
|
||||
# TODO:
|
||||
# |> parse_body()
|
||||
# - convert to markdown
|
||||
# - extract any code parts to mark with pygments?
|
||||
# - figure that whole thing out
|
||||
|
||||
######################################################################
|
||||
# HELPERS
|
||||
######################################################################
|
||||
|
||||
# """ parse_frontmatter_string/1
|
||||
# We expect raw frontmatter as a string that evaluates to an elixir
|
||||
# map, so we try Code.eval_string/1 and rescue with nil if that raises
|
||||
# """
|
||||
defp parse_frontmatter_string(fm) do
|
||||
try do
|
||||
String.trim_leading(fm, "-")
|
||||
|> Code.eval_string()
|
||||
rescue
|
||||
_ -> {:error, nil}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_summary({%{} = fm, _}, md) do
|
||||
String.split(md, "<!--more-->", parts: 2)
|
||||
|> parse_summary(fm)
|
||||
end
|
||||
# """ extract_lede
|
||||
# Handle split of post body. If lede found, return as html with body.
|
||||
# Otherwise return nil with body.
|
||||
# """
|
||||
defp extract_lede([lede, body]), do: {Earmark.as_html!(lede), body}
|
||||
defp extract_lede([body]), do: {nil, body}
|
||||
|
||||
defp parse_summary([summ, _] = parts, fm) do
|
||||
parts
|
||||
|> Enum.join(" ")
|
||||
|> Earmark.as_html()
|
||||
|> parse_post(Earmark.as_html(summ), fm)
|
||||
end
|
||||
# ##################################################
|
||||
# ##################################################
|
||||
# ##################################################
|
||||
# ##################################################
|
||||
# ##################################################
|
||||
# defp parse_split_file_data(["", fm, md]) do
|
||||
# Code.eval_string(fm)
|
||||
# |> parse_lede(md)
|
||||
# end
|
||||
|
||||
defp parse_summary(md, fm) do
|
||||
Earmark.as_html(md)
|
||||
|> parse_post({:ok, nil, []}, fm)
|
||||
end
|
||||
# defp parse_split_file_data(_), do: nil
|
||||
|
||||
defp parse_title_to_slug(title) do
|
||||
Regex.replace(@title_slug_regex, title, "")
|
||||
|> String.replace(" ", "-")
|
||||
|> String.downcase()
|
||||
end
|
||||
# defp parse_lede({%{summary: summ} = fm, _}, md) do
|
||||
# Earmark.as_html(md)
|
||||
# |> parse_post(Earmark.as_html(summ), fm)
|
||||
# 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_lede({%{} = fm, _}, md) do
|
||||
# String.split(md, "<!--more-->", parts: 2)
|
||||
# |> parse_lede(fm)
|
||||
# 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_lede([summ, _] = parts, fm) do
|
||||
# parts
|
||||
# |> Enum.join(" ")
|
||||
# |> Earmark.as_html()
|
||||
# |> parse_post(Earmark.as_html(summ), fm)
|
||||
# end
|
||||
|
||||
defp parse_post(_, _, _), do: nil
|
||||
# defp parse_lede(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,43 +0,0 @@
|
|||
defmodule Home73k.Repo do
|
||||
@repo_url Application.compile_env(:home73k, [:content_repo, :url], nil)
|
||||
@content_path Application.compile_env(:home73k, [:content_repo, :path], "./priv/content")
|
||||
|> Path.expand()
|
||||
|
||||
######################################################################
|
||||
# REPO SETUP
|
||||
######################################################################
|
||||
def get do
|
||||
@content_path |> File.exists?() |> init_repo()
|
||||
end
|
||||
|
||||
def content_path, do: @content_path
|
||||
|
||||
# If content path is absent, clone repo if url is present
|
||||
defp init_repo(false) do
|
||||
if @repo_url do
|
||||
{:ok, repo} = Git.clone([@repo_url, @content_path])
|
||||
repo
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# If content path exists, check for .git child and pull or return nil
|
||||
defp init_repo(true) do
|
||||
if git_data_dir_ok?() do
|
||||
Git.new(@content_path)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp git_data_dir_ok? do
|
||||
git_data_dir = Path.join(@content_path, ".git")
|
||||
File.exists?(git_data_dir) && File.dir?(git_data_dir)
|
||||
end
|
||||
|
||||
######################################################################
|
||||
# REPO OPERATIONS
|
||||
######################################################################
|
||||
def update(repo), do: Git.pull(repo)
|
||||
end
|
|
@ -4,12 +4,7 @@
|
|||
slug: "markdown-for-blog-posts",
|
||||
date: ~N[2016-05-01 13:30:00],
|
||||
author: "Adam Piontek",
|
||||
tags: ["sample", "demo"],
|
||||
summary: """
|
||||
This summary could get long.
|
||||
|
||||
We might even have multiple lines!
|
||||
"""
|
||||
tags: ["sample", "demo"]
|
||||
}
|
||||
---
|
||||
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
}
|
||||
---
|
||||
|
||||
# Enable Visual Studio CLI environment in PowerShell
|
||||
|
||||
#coding #tech #elixir #windows #powershell #scripting
|
||||
|
||||
My initial problem: I have an elixir project I'm building primarily on linux, but I want it to work on Windows, too, and I'm using [bcrypt](https://github.com/riverrun/bcrypt_elixir), which [needs nmake to compile](https://github.com/riverrun/comeonin/wiki/Requirements#windows) on Windows.
|
||||
|
||||
One must install Visual Studio (VS), but that's not enough.<!--more--> Your terminal/PowerShell CLI environment won't know about VS by default. VS includes batch files to set up a dev environment, but if you run them in PowerShell, they bring you into a CMD environment, which is no help if you want to use PowerShell.
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
title: "Mom's Meatloaf",
|
||||
date: ~N[2020-12-29 01:00:00],
|
||||
author: "Adam Piontek",
|
||||
tags: ["food", "recipe", "mealprep", "pandemiceats", "plaguecooking"],
|
||||
summary: "A meatloaf recipe from a very special mom"
|
||||
tags: ["food", "recipe", "mealprep", "pandemiceats", "plaguecooking"]
|
||||
}
|
||||
---
|
||||
|
||||
|
|
Loading…
Reference in a new issue