Packages
fermo
0.16.3
0.20.1
0.20.0
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.1
0.17.0
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.9
0.13.8
0.13.7
0.13.6
0.13.5
0.13.4
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.4
0.2.2
0.2.1
0.2.0
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
A static site generator
Current section
Files
Jump to
Current section
Files
lib/fermo/build.ex
defmodule Fermo.Build do
@moduledoc false
import Mix.Fermo.Paths, only: [source_path: 0]
@config Application.get_env(:fermo, :config, Fermo.Config)
@ffile Application.get_env(:fermo, :ffile, Fermo.File)
@sitemap Application.get_env(:fermo, :sitemap, Fermo.Sitemap)
@callback run(map()) :: {:ok, map()}
def run(config) do
# TODO: check if Webpack assets are ready before building HTML
config =
config
|> Map.put_new(:stats, %{})
|> put_in([:stats, :build_started], Time.utc_now)
{:ok} = Fermo.Assets.build()
{:ok} = Fermo.I18n.load()
config =
config
|> @config.post_config()
|> copy_statics()
|> @sitemap.build()
Task.async_stream(
config.pages,
&(render_cache_and_save(&1)),
[timeout: :infinity]
) |> Enum.to_list
config = put_in(config, [:stats, :build_completed], Time.utc_now)
{:ok, config}
end
def render_page(page) do
content = render_body(page.params.module, page)
if page.params.layout do
build_layout_with_content(page.params.layout, content, page)
else
content
end
end
defp copy_statics(config) do
statics = Map.get(config, :statics, [])
build_path = config.build_path
Enum.each(statics, fn (%{source: source, filename: filename}) ->
source_pathname = Path.join(source_path(), source)
destination_pathname = Path.join(build_path, filename)
@ffile.copy(source_pathname, destination_pathname)
end)
put_in(config, [:stats, :copy_statics_completed], Time.utc_now)
end
defp render_cache_and_save(page) do
with {:ok, hash} <- cache_key(page),
{:ok, cache_pathname} <- cached_page_path(hash),
{:ok} <- is_cached?(cache_pathname) do
@ffile.copy(cache_pathname, page.pathname)
else
{:build_and_cache, cache_pathname} ->
body = render_page(page)
@ffile.save(cache_pathname, body)
@ffile.save(page.pathname, body)
{:no_key} ->
body = render_page(page)
@ffile.save(page.pathname, body)
end
end
defp cache_key(%{params: %{surrogate_key: nil}}), do: {:no_key}
defp cache_key(%{params: %{surrogate_key: surrogate_key}}) do
hash = :crypto.hash(:sha256, surrogate_key) |> Base.encode16
{:ok, hash}
end
defp cache_key(_page), do: {:no_key}
defp cached_page_path(hash) do
{:ok, Path.join("tmp/page_cache", hash)}
end
defp is_cached?(cached_pathname) do
if File.regular?(cached_pathname) do
{:ok}
else
{:build_and_cache, cached_pathname}
end
end
defp render_body(module, %{template: template} = page) do
params = Fermo.Template.params_for(module, page)
Fermo.Template.render_template(module, template, page, params)
end
defp build_layout_with_content(layout, content, page) do
module = Fermo.Template.module_for_template(layout)
layout_params = Map.merge(page.params, %{content: content})
Fermo.Template.render_template(module, layout, page, layout_params)
end
end