Current section
Files
Jump to
Current section
Files
lib/serum/build/file_processor/post.ex
defmodule Serum.Build.FileProcessor.Post do
@moduledoc false
import Serum.IOProxy, only: [put_msg: 2]
alias Serum.Markdown
alias Serum.Plugin
alias Serum.Post
alias Serum.Project
alias Serum.Result
@doc false
@spec process_posts([Serum.File.t()], Project.t()) :: Result.t({[Post.t()], [map()]})
def process_posts(files, proj)
def process_posts([], _proj), do: {:ok, {[], []}}
def process_posts(files, proj) do
put_msg(:info, "Processing post files...")
result =
files
|> Task.async_stream(&process_post(&1, proj), timeout: :infinity)
|> Enum.map(&elem(&1, 1))
|> Result.aggregate_values(:file_processor)
with {:ok, posts} <- result,
sorted_posts = Enum.sort(posts, &(&1.raw_date > &2.raw_date)),
{:ok, posts2} <- Plugin.processed_posts(sorted_posts) do
{:ok, {posts2, Enum.map(posts2, &Post.compact/1)}}
else
{:error, _} = error -> error
end
end
@spec process_post(Serum.File.t(), Project.t()) :: Result.t(Post.t())
defp process_post(file, proj) do
import Serum.{HeaderParser, Build.FileNameHandler}
opts = [
title: :string,
tags: {:list, :string},
date: :datetime,
canonical_url: :string,
template: :string
]
required = [:title, :date]
with {:ok, %{in_data: data} = file2} <- Plugin.processing_post(file),
{:ok, {header, extras, rest}} <- parse_header(data, opts, required),
date <- header[:date] || parse_date_from_filename(file.src),
{html, %{} = meta} = Markdown.to_html(rest, proj) do
title = Map.get(meta, :title, "☆ ☆ ☆")
tags =
file.src
|> String.split("/")
|> Enum.slice(1..-2//1)
|> Kernel.++(Map.get(meta, :tags, []))
header =
header
|> Map.put_new(:date, date)
|> Map.put_new(:title, title)
|> Map.update(:tags, tags, &Enum.uniq(tags ++ &1))
post = Post.new(file2.src, {header, extras}, html, proj)
Plugin.processed_post(post)
else
{:invalid, message} -> {:error, {message, file.src, 0}}
{:error, _} = plugin_error -> plugin_error
end
end
end