Replace hardcoded ["de/", "fr/", "it/", "es/"] with prefixes computed from plan.blog_languages, so arbitrary language codes work correctly. Also mark CSM-024 as fixed (done in CSM-005). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.5 KiB
Elixir
81 lines
2.5 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
|
|
languages = Enum.uniq(plan.blog_languages)
|
|
|
|
other_prefixes =
|
|
languages
|
|
|> Enum.reject(&(&1 == plan.language))
|
|
|> Enum.map(&(&1 <> "/"))
|
|
|
|
Enum.flat_map(languages, fn language ->
|
|
route_language = route_language(plan.language, language)
|
|
pages = pages_for_language(html_outputs, route_language, other_prefixes)
|
|
|
|
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, other_prefixes) do
|
|
html_outputs
|
|
|> Enum.filter(fn {relative_path, _content} ->
|
|
String.ends_with?(relative_path, ".html") and
|
|
language_match?(relative_path, route_language, other_prefixes)
|
|
end)
|
|
|> Enum.map(fn {relative_path, content} ->
|
|
%{
|
|
"url" => "/" <> relative_path,
|
|
"text" => text(content)
|
|
}
|
|
end)
|
|
end
|
|
|
|
defp language_match?(relative_path, nil, other_prefixes),
|
|
do: not String.starts_with?(relative_path, other_prefixes)
|
|
|
|
defp language_match?(relative_path, "", other_prefixes),
|
|
do: language_match?(relative_path, nil, other_prefixes)
|
|
|
|
defp language_match?(relative_path, route_language, _other_prefixes),
|
|
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
|