Files
bDS2/lib/bds/generation/pagefind.ex
2026-05-01 17:49:50 +02:00

74 lines
2.3 KiB
Elixir

defmodule BDS.Generation.Pagefind do
@moduledoc false
@typedoc "An (relative_path, content) HTML output tuple."
@type html_output :: {String.t(), String.t()}
@typedoc "A (relative_path, content) generated file tuple."
@type generated_file :: {String.t(), String.t()}
@doc """
Build the per-language Pagefind index outputs (`pagefind/index.json`,
`pagefind/pagefind-ui.js`, `pagefind/pagefind-ui.css`) for every blog
language declared on the plan.
"""
@spec build_outputs(map(), [html_output()]) :: [generated_file()]
def build_outputs(plan, html_outputs) do
plan.blog_languages
|> Enum.uniq()
|> Enum.flat_map(fn language ->
route_language = route_language(plan.language, language)
pages = pages_for_language(html_outputs, route_language)
prefix =
if route_language in [nil, ""], do: ["pagefind"], else: [route_language, "pagefind"]
[
{Path.join(prefix ++ ["index.json"]),
Jason.encode!(%{"language" => language, "pages" => pages})},
{Path.join(prefix ++ ["pagefind-ui.js"]), ui_js(language)},
{Path.join(prefix ++ ["pagefind-ui.css"]), ui_css()}
]
end)
end
defp pages_for_language(html_outputs, route_language) do
html_outputs
|> Enum.filter(fn {relative_path, _content} ->
String.ends_with?(relative_path, ".html") and language_match?(relative_path, route_language)
end)
|> Enum.map(fn {relative_path, content} ->
%{
"url" => "/" <> relative_path,
"text" => text(content)
}
end)
end
defp language_match?(relative_path, nil),
do: not String.starts_with?(relative_path, ["de/", "fr/", "it/", "es/"])
defp language_match?(relative_path, ""), do: language_match?(relative_path, nil)
defp language_match?(relative_path, route_language),
do: String.starts_with?(relative_path, route_language <> "/")
defp text(content) do
content
|> String.replace(~r/<[^>]+>/, " ")
|> String.replace(~r/\s+/u, " ")
|> String.trim()
end
defp ui_js(language) do
"window.bDSPagefind = { language: #{Jason.encode!(language)} };\n"
end
defp ui_css do
".pagefind-ui{display:block;}\n"
end
defp route_language(main_language, language) when main_language == language, do: nil
defp route_language(_main_language, language), do: language
end