fix: A1-7 implement 4-level template lookup cascade (post→tag→category→default)
This commit is contained in:
@@ -5,6 +5,8 @@ defmodule BDS.Generation.Outputs do
|
||||
import BDS.Generation.Renderers
|
||||
import BDS.Generation.Sitemap, only: [render_feed: 3, render_atom: 3, render_calendar: 1]
|
||||
|
||||
alias BDS.Rendering.TemplateSelection
|
||||
|
||||
@spec additional_languages(map()) :: [String.t()]
|
||||
def additional_languages(plan) do
|
||||
Enum.reject(plan.blog_languages, &(&1 == plan.language))
|
||||
@@ -391,10 +393,12 @@ defmodule BDS.Generation.Outputs do
|
||||
canonical_variant = Map.get(translations_by_post_language, {post.id, main_language}, post)
|
||||
body = load_body(project_id, canonical_variant.file_path, canonical_variant.content)
|
||||
|
||||
effective_slug = effective_template_slug(project_id, post)
|
||||
|
||||
{page_output_path(post.slug, nil),
|
||||
render_post_output(
|
||||
project_id,
|
||||
post.template_slug,
|
||||
effective_slug,
|
||||
%{
|
||||
id: canonical_variant.id,
|
||||
title: canonical_variant.title,
|
||||
@@ -423,10 +427,12 @@ defmodule BDS.Generation.Outputs do
|
||||
|> Enum.map(fn post ->
|
||||
body = load_body(project_id, post.file_path, post.content)
|
||||
|
||||
effective_slug = effective_template_slug(project_id, post)
|
||||
|
||||
{page_output_path(post.slug, language),
|
||||
render_post_output(
|
||||
project_id,
|
||||
post.template_slug,
|
||||
effective_slug,
|
||||
%{
|
||||
id: post.id,
|
||||
title: post.title,
|
||||
@@ -521,10 +527,12 @@ defmodule BDS.Generation.Outputs do
|
||||
canonical_variant = Map.get(translations_by_post_language, {post.id, main_language}, post)
|
||||
body = load_body(project_id, canonical_variant.file_path, canonical_variant.content)
|
||||
|
||||
effective_slug = effective_template_slug(project_id, post)
|
||||
|
||||
{post_output_path(post),
|
||||
render_post_output(
|
||||
project_id,
|
||||
post.template_slug,
|
||||
effective_slug,
|
||||
%{
|
||||
id: canonical_variant.id,
|
||||
title: canonical_variant.title,
|
||||
@@ -551,10 +559,12 @@ defmodule BDS.Generation.Outputs do
|
||||
Enum.map(posts, fn post ->
|
||||
body = load_body(project_id, post.file_path, post.content)
|
||||
|
||||
effective_slug = effective_template_slug(project_id, post)
|
||||
|
||||
{post_output_path(post, language),
|
||||
render_post_output(
|
||||
project_id,
|
||||
post.template_slug,
|
||||
effective_slug,
|
||||
%{
|
||||
id: post.id,
|
||||
title: post.title,
|
||||
@@ -571,4 +581,18 @@ defmodule BDS.Generation.Outputs do
|
||||
|
||||
post_outputs ++ translation_outputs
|
||||
end
|
||||
|
||||
defp effective_template_slug(project_id, post) do
|
||||
slug = Map.get(post, :template_slug)
|
||||
|
||||
if is_binary(slug) and slug != "" do
|
||||
slug
|
||||
else
|
||||
TemplateSelection.resolve_post_template_slug(
|
||||
project_id,
|
||||
Map.get(post, :tags) || [],
|
||||
Map.get(post, :categories) || []
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule BDS.Preview do
|
||||
alias BDS.Projects
|
||||
alias BDS.Repo
|
||||
alias BDS.Rendering
|
||||
alias BDS.Rendering.TemplateSelection
|
||||
|
||||
@host "127.0.0.1"
|
||||
@port 4123
|
||||
@@ -219,6 +220,7 @@ defmodule BDS.Preview do
|
||||
|
||||
defp draft_preview_payload(post, query_params) do
|
||||
requested_language = query_params |> Map.get("lang") |> normalize_requested_language()
|
||||
effective_slug = post.template_slug || TemplateSelection.resolve_post_template_slug(post.project_id, post.tags, post.categories)
|
||||
|
||||
case draft_preview_translation(post.id, requested_language, post.language) do
|
||||
%Translation{} = translation ->
|
||||
@@ -230,7 +232,7 @@ defmodule BDS.Preview do
|
||||
slug: post.slug,
|
||||
language: translation.language,
|
||||
excerpt: translation.excerpt,
|
||||
template_slug: post.template_slug
|
||||
template_slug: effective_slug
|
||||
}
|
||||
|
||||
nil ->
|
||||
@@ -242,7 +244,7 @@ defmodule BDS.Preview do
|
||||
slug: post.slug,
|
||||
language: post.language,
|
||||
excerpt: post.excerpt,
|
||||
template_slug: post.template_slug
|
||||
template_slug: effective_slug
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule BDS.Preview.Router do
|
||||
alias BDS.Posts.Post
|
||||
alias BDS.Posts.Translation
|
||||
alias BDS.Rendering
|
||||
alias BDS.Rendering.TemplateSelection
|
||||
alias BDS.Repo
|
||||
|
||||
@type route ::
|
||||
@@ -219,7 +220,9 @@ defmodule BDS.Preview.Router do
|
||||
_post_record: effective_record
|
||||
}
|
||||
|
||||
case Rendering.render_post_page(project_id, post.template_slug, assigns) do
|
||||
effective_slug = post.template_slug || TemplateSelection.resolve_post_template_slug(project_id, post.tags, post.categories)
|
||||
|
||||
case Rendering.render_post_page(project_id, effective_slug, assigns) do
|
||||
{:ok, rendered} -> {:ok, rendered}
|
||||
{:error, _reason} -> {:error, :not_found}
|
||||
end
|
||||
|
||||
@@ -4,13 +4,52 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
import Ecto.Query
|
||||
|
||||
alias BDS.Frontmatter
|
||||
alias BDS.Metadata
|
||||
alias BDS.Projects
|
||||
alias BDS.Rendering.FileSystem
|
||||
alias BDS.Rendering.Filters
|
||||
alias BDS.Repo
|
||||
alias BDS.StarterTemplates
|
||||
alias BDS.Tags.Tag
|
||||
alias BDS.Templates.Template
|
||||
|
||||
@spec resolve_post_template_slug(String.t(), [String.t()], [String.t()]) ::
|
||||
String.t() | nil
|
||||
def resolve_post_template_slug(project_id, tag_names, category_names) do
|
||||
resolve_from_tags(project_id, tag_names) ||
|
||||
resolve_from_categories(project_id, category_names)
|
||||
end
|
||||
|
||||
defp resolve_from_tags(_project_id, []), do: nil
|
||||
|
||||
defp resolve_from_tags(project_id, tag_names) do
|
||||
Repo.all(
|
||||
from tag in Tag,
|
||||
where:
|
||||
tag.project_id == ^project_id and
|
||||
tag.name in ^tag_names and
|
||||
not is_nil(tag.post_template_slug) and
|
||||
tag.post_template_slug != "",
|
||||
select: tag.post_template_slug,
|
||||
limit: 1
|
||||
)
|
||||
|> List.first()
|
||||
end
|
||||
|
||||
defp resolve_from_categories(_project_id, []), do: nil
|
||||
|
||||
defp resolve_from_categories(project_id, category_names) do
|
||||
{:ok, state} = Metadata.get_project_metadata(project_id)
|
||||
settings = state.category_settings || %{}
|
||||
|
||||
Enum.find_value(category_names, fn cat_name ->
|
||||
case Map.get(settings, cat_name) do
|
||||
%{"post_template_slug" => slug} when is_binary(slug) and slug != "" -> slug
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@spec load_template_source(String.t(), atom(), String.t() | nil) ::
|
||||
{:ok, String.t()} | {:error, term()}
|
||||
def load_template_source(project_id, kind, slug) do
|
||||
|
||||
Reference in New Issue
Block a user