59 lines
1.7 KiB
Elixir
59 lines
1.7 KiB
Elixir
defmodule SloaneSH.Context do
|
|
@moduledoc """
|
|
A SloaneSH build context containing configuration and reference to content
|
|
files.
|
|
"""
|
|
use TypedStruct
|
|
require Logger
|
|
|
|
alias SloaneSH.Config
|
|
alias SloaneSH.Asset
|
|
alias SloaneSH.Assets.Page
|
|
alias SloaneSH.Assets.Post
|
|
alias SloaneSH.Assets.Image
|
|
alias __MODULE__
|
|
|
|
typedstruct do
|
|
field :config, Config.t(), enforce: true
|
|
field :pages, [Asset.t()], default: []
|
|
field :posts, [Asset.t()], default: []
|
|
field :images, [Asset.t()], default: []
|
|
end
|
|
|
|
def new(cfg \\ Config.default()) do
|
|
pages = load_assets(cfg, Page, cfg.pages_dir)
|
|
posts = load_assets(cfg, Post, cfg.posts_dir)
|
|
images = load_assets(cfg, Image, cfg.images_dir)
|
|
|
|
%Context{config: cfg, pages: pages, posts: posts, images: images}
|
|
end
|
|
|
|
defp load_assets(cfg, mod, src_dir) do
|
|
exts = mod.extensions(cfg)
|
|
|
|
for src <- collect_src_files(src_dir, exts) do
|
|
contents = File.read!(src)
|
|
|
|
case mod.attrs(cfg, src, contents) do
|
|
{:ok, attrs, src_contents} ->
|
|
%Asset{mod: mod, src: src, src_contents: src_contents, attrs: attrs}
|
|
|
|
{:ok, attrs} ->
|
|
%Asset{mod: mod, src: src, src_contents: contents, attrs: attrs}
|
|
|
|
_ ->
|
|
Logger.warning("Failed to parse attrs for #{inspect(src)}")
|
|
%Asset{mod: mod, src: src, src_contents: contents, attrs: %{}}
|
|
end
|
|
end
|
|
end
|
|
|
|
defp collect_src_files(src_dir, exts) do
|
|
files = src_dir |> File.ls!() |> Enum.map(&Path.join(src_dir, &1))
|
|
{src_files, rest} = Enum.split_with(files, &String.ends_with?(&1, exts))
|
|
|
|
other_dirs = Enum.filter(rest, &File.dir?/1)
|
|
|
|
src_files ++ Enum.flat_map(other_dirs, &collect_src_files(&1, exts))
|
|
end
|
|
end
|