fix: issue #6 post bodies missing for asides
This commit is contained in:
@@ -54,6 +54,7 @@ defmodule BDS.BoundedAtoms do
|
||||
:fill_missing_translations,
|
||||
:find_duplicates,
|
||||
:generate_sitemap,
|
||||
:force_render_site,
|
||||
:validate_site,
|
||||
:upload_site,
|
||||
:documentation,
|
||||
|
||||
@@ -188,6 +188,7 @@ defmodule BDS.Desktop.MenuBar do
|
||||
defp item_label(:fill_missing_translations), do: dgettext("ui", "Fill Missing Translations")
|
||||
defp item_label(:find_duplicates), do: dgettext("ui", "Find Duplicate Posts")
|
||||
defp item_label(:generate_sitemap), do: dgettext("ui", "Generate Site")
|
||||
defp item_label(:force_render_site), do: dgettext("ui", "Force Render Site")
|
||||
defp item_label(:validate_site), do: dgettext("ui", "Validate Site")
|
||||
defp item_label(:upload_site), do: dgettext("ui", "Upload Site")
|
||||
defp item_label(:about), do: dgettext("ui", "About")
|
||||
|
||||
@@ -239,33 +239,13 @@ defmodule BDS.Desktop.ShellCommands do
|
||||
end
|
||||
|
||||
defp dispatch("generate_sitemap", project, _params) do
|
||||
group_id = task_group_id("generate_sitemap")
|
||||
attrs = %{group_id: group_id, group_name: "Render Site"}
|
||||
queue_render_site(project, "generate_sitemap", "Render Site", [])
|
||||
end
|
||||
|
||||
{:ok, first_task} =
|
||||
Tasks.submit_task(
|
||||
section_task_name(:core),
|
||||
fn report ->
|
||||
{:ok, _result} = Generation.render_site_section(project.id, :core, on_progress: report)
|
||||
report.(1.0, section_complete_message(:core))
|
||||
:ok
|
||||
end,
|
||||
attrs
|
||||
)
|
||||
|
||||
Task.start(fn -> run_render_site_sequence(project, group_id, attrs) end)
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
kind: "task_queued",
|
||||
action: "generate_sitemap",
|
||||
title: "Render Site",
|
||||
message: "Render Site tasks queued",
|
||||
project_id: project.id,
|
||||
task_id: first_task.id,
|
||||
task_group_id: group_id,
|
||||
panel_tab: "tasks"
|
||||
}}
|
||||
# Forced variant of the site render: ignores the stored content hashes and
|
||||
# rewrites every output file, repairing any drift on disk.
|
||||
defp dispatch("force_render_site", project, _params) do
|
||||
queue_render_site(project, "force_render_site", "Force Render Site", force: true)
|
||||
end
|
||||
|
||||
defp dispatch("validate_site", project, _params) do
|
||||
@@ -490,7 +470,43 @@ defmodule BDS.Desktop.ShellCommands do
|
||||
end
|
||||
end
|
||||
|
||||
defp run_render_site_sequence(project, group_id, attrs) do
|
||||
defp queue_render_site(project, action, title, render_opts) do
|
||||
group_id = task_group_id(action)
|
||||
attrs = %{group_id: group_id, group_name: title}
|
||||
|
||||
{:ok, first_task} =
|
||||
Tasks.submit_task(
|
||||
section_task_name(:core),
|
||||
fn report ->
|
||||
{:ok, _result} =
|
||||
Generation.render_site_section(
|
||||
project.id,
|
||||
:core,
|
||||
[on_progress: report] ++ render_opts
|
||||
)
|
||||
|
||||
report.(1.0, section_complete_message(:core))
|
||||
:ok
|
||||
end,
|
||||
attrs
|
||||
)
|
||||
|
||||
Task.start(fn -> run_render_site_sequence(project, group_id, attrs, render_opts) end)
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
kind: "task_queued",
|
||||
action: action,
|
||||
title: title,
|
||||
message: title <> " tasks queued",
|
||||
project_id: project.id,
|
||||
task_id: first_task.id,
|
||||
task_group_id: group_id,
|
||||
panel_tab: "tasks"
|
||||
}}
|
||||
end
|
||||
|
||||
defp run_render_site_sequence(project, group_id, attrs, render_opts) do
|
||||
remaining_sections = [:single, :category, :tag, :date]
|
||||
|
||||
Enum.each(remaining_sections, fn section ->
|
||||
@@ -499,7 +515,11 @@ defmodule BDS.Desktop.ShellCommands do
|
||||
section_task_name(section),
|
||||
fn report ->
|
||||
{:ok, _result} =
|
||||
Generation.render_site_section(project.id, section, on_progress: report)
|
||||
Generation.render_site_section(
|
||||
project.id,
|
||||
section,
|
||||
[on_progress: report] ++ render_opts
|
||||
)
|
||||
|
||||
report.(1.0, section_complete_message(section))
|
||||
:ok
|
||||
@@ -515,7 +535,12 @@ defmodule BDS.Desktop.ShellCommands do
|
||||
Tasks.submit_task(
|
||||
"Build Search Index",
|
||||
fn report ->
|
||||
{:ok, _result} = Generation.build_site_search_index(project.id, on_progress: report)
|
||||
{:ok, _result} =
|
||||
Generation.build_site_search_index(
|
||||
project.id,
|
||||
[on_progress: report] ++ render_opts
|
||||
)
|
||||
|
||||
report.(1.0, "Build Search Index complete")
|
||||
:ok
|
||||
end,
|
||||
|
||||
@@ -137,7 +137,9 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|> MapSet.union(
|
||||
MapSet.new([:validate_translations, :fill_missing_translations, :find_duplicates])
|
||||
)
|
||||
|> MapSet.union(MapSet.new([:generate_sitemap, :validate_site, :upload_site]))
|
||||
|> MapSet.union(
|
||||
MapSet.new([:generate_sitemap, :force_render_site, :validate_site, :upload_site])
|
||||
)
|
||||
end
|
||||
|
||||
embed_templates("shell_live/*")
|
||||
|
||||
@@ -99,6 +99,10 @@ defmodule BDS.Generation do
|
||||
than just the affected ones). The `:core` section also writes the complete
|
||||
sitemap, feeds, calendar and preview assets. The Pagefind search index is
|
||||
built separately by `build_site_search_index/2`.
|
||||
|
||||
Pass `force: true` to ignore the stored content hashes and rewrite every
|
||||
output file, repairing any drift between the tracked hashes and what is
|
||||
actually on disk.
|
||||
"""
|
||||
@spec render_site_section(String.t(), section(), generation_opts()) ::
|
||||
{:ok, map()} | {:error, term()}
|
||||
@@ -115,7 +119,12 @@ defmodule BDS.Generation do
|
||||
|
||||
rendered_url_count =
|
||||
stream_render(project_id, on_progress, route_total,
|
||||
[verb: "Generated", gerund: "Generating", refresh_route_timestamps: false],
|
||||
[
|
||||
verb: "Generated",
|
||||
gerund: "Generating",
|
||||
refresh_route_timestamps: false,
|
||||
force: Keyword.get(opts, :force, false)
|
||||
],
|
||||
fn on_output -> full_section_outputs(plan, render_data, section, on_output) end
|
||||
)
|
||||
|
||||
@@ -143,7 +152,12 @@ defmodule BDS.Generation do
|
||||
pagefind_outputs = BDS.Generation.Pagefind.build_outputs(plan, html_outputs)
|
||||
total = max(length(pagefind_outputs), 1)
|
||||
|
||||
write_ctx = stream_context(project_id, nil, 0, verb: "Built", gerund: "Building")
|
||||
write_ctx =
|
||||
stream_context(project_id, nil, 0,
|
||||
verb: "Built",
|
||||
gerund: "Building",
|
||||
force: Keyword.get(opts, :force, false)
|
||||
)
|
||||
|
||||
pagefind_outputs
|
||||
|> Enum.with_index(1)
|
||||
@@ -953,7 +967,9 @@ defmodule BDS.Generation do
|
||||
%{
|
||||
project_id: project_id,
|
||||
project: Projects.get_project!(project_id),
|
||||
existing_hashes: existing_hash_map(project_id),
|
||||
# force: pretend nothing was ever generated so every output is written.
|
||||
existing_hashes:
|
||||
if(Keyword.get(opts, :force, false), do: %{}, else: existing_hash_map(project_id)),
|
||||
pending_hashes: :ets.new(:bds_generation_pending_hashes, [:set, :public]),
|
||||
on_progress: on_progress,
|
||||
route_total: route_total,
|
||||
|
||||
@@ -44,30 +44,18 @@ defmodule BDS.Generation.Renderers do
|
||||
|> IO.iodata_to_binary()
|
||||
end
|
||||
|
||||
@doc "Render an archive page (category, tag, year) with pagination."
|
||||
@doc "Render an archive page (category, tag) with pagination."
|
||||
@spec render_archive_page(map(), String.t(), [map()], String.t() | nil, String.t(), map()) ::
|
||||
String.t()
|
||||
def render_archive_page(plan, title, posts, language, kind, pagination) do
|
||||
fallback = fn -> render_inline_list_page(title, posts, language, kind) end
|
||||
|
||||
render_list_output(
|
||||
render_archive_list_page(
|
||||
plan,
|
||||
language,
|
||||
title,
|
||||
Enum.map(posts, fn post ->
|
||||
%{
|
||||
id: post.id,
|
||||
slug: post.slug,
|
||||
title: post.title,
|
||||
href: "#",
|
||||
excerpt: post.excerpt,
|
||||
content: nil,
|
||||
language: post.language
|
||||
}
|
||||
end),
|
||||
%{kind: kind, name: title},
|
||||
pagination,
|
||||
fallback
|
||||
posts,
|
||||
language,
|
||||
kind,
|
||||
pagination
|
||||
)
|
||||
end
|
||||
|
||||
@@ -75,12 +63,18 @@ defmodule BDS.Generation.Renderers do
|
||||
@spec render_date_archive_page(map(), String.t(), map(), [map()], String.t() | nil, map()) ::
|
||||
String.t()
|
||||
def render_date_archive_page(plan, label, archive_context, posts, language, pagination) do
|
||||
fallback = fn -> render_inline_list_page(label, posts, language, "date") end
|
||||
render_archive_list_page(plan, label, archive_context, posts, language, "date", pagination)
|
||||
end
|
||||
|
||||
# Shared by every archive kind so category/tag pages get the same post
|
||||
# payloads (loaded bodies, real hrefs) as date archives.
|
||||
defp render_archive_list_page(plan, title, archive_context, posts, language, kind, pagination) do
|
||||
fallback = fn -> render_inline_list_page(title, posts, language, kind) end
|
||||
|
||||
render_list_output(
|
||||
plan,
|
||||
language,
|
||||
label,
|
||||
title,
|
||||
build_list_posts(plan, posts, Paths.route_language(plan.language, language)),
|
||||
archive_context,
|
||||
pagination,
|
||||
|
||||
@@ -102,19 +102,34 @@ defmodule BDS.Rendering.RenderContext do
|
||||
|
||||
@doc """
|
||||
Return the cached value for `key`, computing and caching it with `fun` on the
|
||||
first call. Safe to call from concurrently rendering processes; concurrent
|
||||
first calls may compute twice but always return a consistent value.
|
||||
first call. Single-flight: concurrent first calls for the same key compute
|
||||
exactly once — later callers wait for the winner instead of duplicating the
|
||||
work (template parses, file reads) and its queries.
|
||||
"""
|
||||
@spec memoize(t(), term(), (-> value)) :: value when value: term()
|
||||
def memoize(%__MODULE__{cache: cache}, key, fun) when is_function(fun, 0) do
|
||||
def memoize(%__MODULE__{cache: cache} = ctx, key, fun) when is_function(fun, 0) do
|
||||
case :ets.lookup(cache, key) do
|
||||
[{^key, value}] ->
|
||||
value
|
||||
[{^key, value}] -> value
|
||||
[] -> compute_memoized(ctx, key, fun)
|
||||
end
|
||||
end
|
||||
|
||||
[] ->
|
||||
defp compute_memoized(%__MODULE__{cache: cache} = ctx, key, fun) do
|
||||
lock_key = {:memoize_lock, key}
|
||||
|
||||
if :ets.insert_new(cache, {lock_key, self()}) do
|
||||
try do
|
||||
value = fun.()
|
||||
:ets.insert(cache, {key, value})
|
||||
true = :ets.insert(cache, {key, value})
|
||||
value
|
||||
after
|
||||
:ets.delete(cache, lock_key)
|
||||
end
|
||||
else
|
||||
# Another process is computing this key; poll until its value lands (or
|
||||
# its lock disappears because it crashed, in which case we take over).
|
||||
Process.sleep(2)
|
||||
memoize(ctx, key, fun)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ defmodule BDS.UI.Commands do
|
||||
%{id: :publish_selected, accelerator: "CTRL+SHIFT+P"},
|
||||
%{id: :preview_post, accelerator: "CTRL+SHIFT+V"},
|
||||
%{id: :generate_sitemap, accelerator: "CTRL+R"},
|
||||
%{id: :force_render_site, accelerator: "CTRL+SHIFT+R"},
|
||||
%{id: :validate_site, accelerator: "CTRL+SHIFT+L"},
|
||||
%{id: :upload_site, accelerator: "CTRL+SHIFT+U"}
|
||||
]
|
||||
|
||||
@@ -63,6 +63,7 @@ defmodule BDS.UI.MenuBar do
|
||||
%{id: :find_duplicates},
|
||||
%{separator: true},
|
||||
%{id: :generate_sitemap},
|
||||
%{id: :force_render_site},
|
||||
%{id: :validate_site},
|
||||
%{id: :upload_site}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user