From 1ccf15cea20239b87bbc2a768485c16367c587bd Mon Sep 17 00:00:00 2001
From: Mitchell Hanberg <mitch@mitchellhanberg.com>
Date: Mon, 2 Jun 2025 11:44:58 -0400
Subject: [PATCH] fix(rss): convert post body

---
 lib/tableau/extensions/post_extension.ex      | 35 +++++++++---------
 lib/tableau/extensions/rss_extension.ex       |  2 +-
 test/support/helpers.ex                       | 15 +++++---
 .../tableau/extensions/rss_extension_test.exs | 36 +++++++++----------
 4 files changed, 46 insertions(+), 42 deletions(-)

diff --git a/lib/tableau/extensions/post_extension.ex b/lib/tableau/extensions/post_extension.ex
index b0ff552..7c8ae7b 100644
--- a/lib/tableau/extensions/post_extension.ex
+++ b/lib/tableau/extensions/post_extension.ex
@@ -80,6 +80,7 @@ defmodule Tableau.PostExtension do
   @type post :: %{
           body: String.t(),
           file: String.t(),
+          renderer: fun(),
           layout: module(),
           date: DateTime.t()
         }
@@ -112,49 +113,47 @@ defmodule Tableau.PostExtension do
         |> Common.paths()
       end)
       |> Common.entries(fn %{path: path, front_matter: front_matter, pre_convert_body: body, ext: ext} ->
-        {
-          build(path, front_matter, body, config),
-          fn assigns ->
-            converter =
-              case front_matter[:converter] do
-                nil -> converters[ext]
-                converter -> Module.concat([converter])
-              end
-
-            converter.convert(path, front_matter, body, assigns)
-          end
-        }
+        build(path, front_matter, body, config, fn assigns ->
+          converter =
+            case front_matter[:converter] do
+              nil -> converters[ext]
+              converter -> Module.concat([converter])
+            end
+
+          converter.convert(path, front_matter, body, assigns)
+        end)
       end)
-      |> Enum.sort_by(fn {post, _} -> post.date end, {:desc, DateTime})
+      |> Enum.sort_by(fn post -> post.date end, {:desc, DateTime})
       |> then(fn posts ->
         if config.future do
           posts
         else
-          Enum.reject(posts, fn {post, _} -> DateTime.after?(post.date, DateTime.utc_now()) end)
+          Enum.reject(posts, fn post -> DateTime.after?(post.date, DateTime.utc_now()) end)
         end
       end)
 
     graph =
       Tableau.Graph.insert(
         token.graph,
-        Enum.map(posts, fn {post, renderer} ->
-          %Tableau.Page{parent: post.layout, permalink: post.permalink, template: renderer, opts: post}
+        Enum.map(posts, fn post ->
+          %Tableau.Page{parent: post.layout, permalink: post.permalink, template: post.renderer, opts: post}
         end)
       )
 
     {:ok,
      token
-     |> Map.put(:posts, posts |> Enum.unzip() |> elem(0))
+     |> Map.put(:posts, posts)
      |> Map.put(:graph, graph)}
   end
 
-  defp build(filename, attrs, body, posts_config) do
+  defp build(filename, attrs, body, posts_config, renderer) do
     Application.put_env(:date_time_parser, :include_zones_from, ~N[2010-01-01T00:00:00])
 
     attrs
     |> Map.put(:__tableau_post_extension__, true)
     |> Map.put(:body, body)
     |> Map.put(:file, filename)
+    |> Map.put(:renderer, renderer)
     |> Map.put(:layout, Module.concat([attrs[:layout] || posts_config.layout]))
     |> Map.put(:date, DateTimeParser.parse_datetime!(attrs.date, assume_time: true, assume_utc: true))
     |> Common.build_permalink(posts_config)
diff --git a/lib/tableau/extensions/rss_extension.ex b/lib/tableau/extensions/rss_extension.ex
index d3c3ce5..2e40c04 100644
--- a/lib/tableau/extensions/rss_extension.ex
+++ b/lib/tableau/extensions/rss_extension.ex
@@ -111,7 +111,7 @@ defmodule Tableau.RSSExtension do
                  <link>#{URI.merge(url, post.permalink)}</link>
                  <pubDate>#{Calendar.strftime(post.date, "%a, %d %b %Y %X %Z")}</pubDate>
                  <guid>#{URI.merge(url, post.permalink)}</guid>
-                 <description><![CDATA[ #{post.body} ]]></description>
+                 <description><![CDATA[ #{post.renderer.(token)} ]]></description>
               </item>
           """
         end
diff --git a/test/support/helpers.ex b/test/support/helpers.ex
index 30de4d2..756529c 100644
--- a/test/support/helpers.ex
+++ b/test/support/helpers.ex
@@ -1,15 +1,20 @@
 defmodule Tableau.Support.Helpers do
   @moduledoc false
   def post(idx, overrides) do
+    body = """
+    ## Welcome to Post #{idx}
+
+    Here, we post like crazy.
+    """
+
     base = %{
       title: "Post #{idx}",
       permalink: "/posts/post-#{1}",
       date: DateTime.utc_now(),
-      body: """
-      ## Welcome to Post #{idx}
-
-      Here, we post like crazy.
-      """
+      body: body,
+      renderer: fn _assigns ->
+        String.upcase(overrides[:body] || body)
+      end
     }
 
     Map.merge(base, Map.new(overrides))
diff --git a/test/tableau/extensions/rss_extension_test.exs b/test/tableau/extensions/rss_extension_test.exs
index 94c64ad..ba4aded 100644
--- a/test/tableau/extensions/rss_extension_test.exs
+++ b/test/tableau/extensions/rss_extension_test.exs
@@ -42,9 +42,9 @@ defmodule Tableau.RSSExtensionTest do
       assert File.exists?(feed_path)
       feed_content = File.read!(feed_path)
 
-      assert feed_content =~ "Post 1"
-      refute feed_content =~ "Post 2"
-      refute feed_content =~ "Post 3"
+      assert feed_content =~ "POST 1"
+      refute feed_content =~ "POST 2"
+      refute feed_content =~ "POST 3"
     end
   end
 
@@ -118,17 +118,17 @@ defmodule Tableau.RSSExtensionTest do
       assert File.exists?(feed_path)
       feed_content = File.read!(feed_path)
 
-      assert feed_content =~ "Post 1"
-      refute feed_content =~ "Post 2"
-      refute feed_content =~ "Post 3"
+      assert feed_content =~ "POST 1"
+      refute feed_content =~ "POST 2"
+      refute feed_content =~ "POST 3"
       # only contains posts with category as "casual"
       casual_path = Path.join(tmp_dir, "casual.xml")
       assert File.exists?(casual_path)
       casual_content = File.read!(casual_path)
 
-      refute casual_content =~ "Post 2"
-      refute casual_content =~ "Post 1"
-      assert casual_content =~ "Post 3"
+      refute casual_content =~ "POST 2"
+      refute casual_content =~ "POST 1"
+      assert casual_content =~ "POST 3"
     end
 
     test "includes everything if there is no includes key", %{token: token, tmp_dir: tmp_dir} do
@@ -149,9 +149,9 @@ defmodule Tableau.RSSExtensionTest do
       assert File.exists?(feed_path)
       feed_content = File.read!(feed_path)
 
-      assert feed_content =~ "Post 1"
-      assert feed_content =~ "Post 2"
-      assert feed_content =~ "Post 3"
+      assert feed_content =~ "POST 1"
+      assert feed_content =~ "POST 2"
+      assert feed_content =~ "POST 3"
     end
 
     test "excludes various frontmatter", %{token: token, tmp_dir: tmp_dir} do
@@ -180,18 +180,18 @@ defmodule Tableau.RSSExtensionTest do
       assert File.exists?(not_posts_path)
       not_posts_content = File.read!(not_posts_path)
 
-      refute not_posts_content =~ "Post 1"
-      assert not_posts_content =~ "Post 2"
-      assert not_posts_content =~ "Post 3"
+      refute not_posts_content =~ "POST 1"
+      assert not_posts_content =~ "POST 2"
+      assert not_posts_content =~ "POST 3"
 
       # only contains posts without category as "bar"
       not_casual_path = Path.join(tmp_dir, "not_casual.xml")
       assert File.exists?(not_casual_path)
       not_casual_content = File.read!(not_casual_path)
 
-      assert not_casual_content =~ "Post 2"
-      assert not_casual_content =~ "Post 1"
-      refute not_casual_content =~ "Post 3"
+      assert not_casual_content =~ "POST 2"
+      assert not_casual_content =~ "POST 1"
+      refute not_casual_content =~ "POST 3"
     end
   end
 end
