refactor: extract feed and sitemap helpers into FeedHelpers module
Move feed_xml, feed_item, feed_json, json_feed_item, rfc822_date, iso_date, and sitemap_xml out of Server into a dedicated FeedHelpers module included via helpers. Reduces Server from ~500 to ~400 lines and separates feed generation concerns from routing.
This commit is contained in:
@@ -0,0 +1,104 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Volumen
|
||||||
|
# RSS, JSON Feed, and sitemap helpers extracted from Server to keep the
|
||||||
|
# main class focused on configuration and routing.
|
||||||
|
module FeedHelpers
|
||||||
|
private
|
||||||
|
|
||||||
|
def feed_xml
|
||||||
|
site = config.site
|
||||||
|
items = published_posts.first(20).map { |post| feed_item(post) }.join("\n")
|
||||||
|
<<~XML
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<channel>
|
||||||
|
<title>#{escape(site["title"])}</title>
|
||||||
|
<link>#{escape(base_url)}</link>
|
||||||
|
<description>#{escape(site["description"])}</description>
|
||||||
|
<language>#{escape(site["language"])}</language>
|
||||||
|
#{items}
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
|
XML
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed_item(post)
|
||||||
|
link = "#{base_url}/#{post.slug}"
|
||||||
|
pub = if post.metadata["date"]
|
||||||
|
"\n <pubDate>#{escape(rfc822_date(post))}</pubDate>"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
creator = post.fediverse_creator
|
||||||
|
creator_tag = creator ? "\n <dc:creator>#{escape(creator)}</dc:creator>" : ""
|
||||||
|
<<~XML.chomp
|
||||||
|
<item>
|
||||||
|
<title>#{escape(post.title)}</title>
|
||||||
|
<link>#{escape(link)}</link>
|
||||||
|
<guid>#{escape(link)}</guid>
|
||||||
|
<description>#{escape(post.excerpt)}</description>#{pub}#{creator_tag}
|
||||||
|
</item>
|
||||||
|
XML
|
||||||
|
end
|
||||||
|
|
||||||
|
def rfc822_date(post)
|
||||||
|
value = post.metadata["date"]
|
||||||
|
case value
|
||||||
|
when Date then value.to_time.rfc822
|
||||||
|
when Time then value.rfc822
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed_json
|
||||||
|
site = config.site
|
||||||
|
feed_url = "#{base_url}/api/volumen/feed.json"
|
||||||
|
{
|
||||||
|
"version" => "https://jsonfeed.org/version/1.1",
|
||||||
|
"title" => site["title"],
|
||||||
|
"home_page_url" => base_url,
|
||||||
|
"feed_url" => feed_url,
|
||||||
|
"description" => site["description"],
|
||||||
|
"language" => site["language"],
|
||||||
|
"items" => published_posts.first(20).map { |post| json_feed_item(post) }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def json_feed_item(post)
|
||||||
|
link = "#{base_url}/#{post.slug}"
|
||||||
|
item = {
|
||||||
|
"id" => link,
|
||||||
|
"url" => link,
|
||||||
|
"title" => post.title,
|
||||||
|
"content_html" => post.html,
|
||||||
|
"summary" => post.excerpt,
|
||||||
|
"date_published" => iso_date(post.metadata["date"]),
|
||||||
|
"tags" => post.tags
|
||||||
|
}
|
||||||
|
author = post.fediverse_creator || site_fediverse_creator
|
||||||
|
item["authors"] = [{ "name" => author }] if author
|
||||||
|
item.reject { |_k, v| v.nil? || v == "" || v == [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def iso_date(value)
|
||||||
|
case value
|
||||||
|
when Date then value.iso8601
|
||||||
|
when Time then value.to_date.iso8601
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def sitemap_xml
|
||||||
|
urls = published_posts.map do |post|
|
||||||
|
url = " <url><loc>#{escape("#{base_url}/#{post.slug}")}</loc>"
|
||||||
|
url << "<lastmod>#{escape(post.date_string)}</lastmod>" if post.date_string
|
||||||
|
url << "</url>"
|
||||||
|
end.join("\n")
|
||||||
|
<<~XML
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
#{urls}
|
||||||
|
</urlset>
|
||||||
|
XML
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+2
-95
@@ -10,6 +10,7 @@ require_relative "markdown"
|
|||||||
require_relative "password"
|
require_relative "password"
|
||||||
require_relative "api_routes"
|
require_relative "api_routes"
|
||||||
require_relative "admin_routes"
|
require_relative "admin_routes"
|
||||||
|
require_relative "feed_helpers"
|
||||||
|
|
||||||
module Volumen
|
module Volumen
|
||||||
# Sinatra application: the public JSON API at /api/volumen and the
|
# Sinatra application: the public JSON API at /api/volumen and the
|
||||||
@@ -25,6 +26,7 @@ module Volumen
|
|||||||
|
|
||||||
register ApiRoutes
|
register ApiRoutes
|
||||||
register AdminRoutes
|
register AdminRoutes
|
||||||
|
helpers FeedHelpers
|
||||||
|
|
||||||
configure do
|
configure do
|
||||||
set :show_exceptions, false
|
set :show_exceptions, false
|
||||||
@@ -167,101 +169,6 @@ module Volumen
|
|||||||
config.site["base_url"].to_s.chomp("/")
|
config.site["base_url"].to_s.chomp("/")
|
||||||
end
|
end
|
||||||
|
|
||||||
def feed_xml
|
|
||||||
site = config.site
|
|
||||||
items = published_posts.first(20).map { |post| feed_item(post) }.join("\n")
|
|
||||||
<<~XML
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
||||||
<channel>
|
|
||||||
<title>#{escape(site["title"])}</title>
|
|
||||||
<link>#{escape(base_url)}</link>
|
|
||||||
<description>#{escape(site["description"])}</description>
|
|
||||||
<language>#{escape(site["language"])}</language>
|
|
||||||
#{items}
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def feed_item(post)
|
|
||||||
link = "#{base_url}/#{post.slug}"
|
|
||||||
pub = if post.metadata["date"]
|
|
||||||
"\n <pubDate>#{escape(rfc822_date(post))}</pubDate>"
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
creator = post.fediverse_creator
|
|
||||||
creator_tag = creator ? "\n <dc:creator>#{escape(creator)}</dc:creator>" : ""
|
|
||||||
<<~XML.chomp
|
|
||||||
<item>
|
|
||||||
<title>#{escape(post.title)}</title>
|
|
||||||
<link>#{escape(link)}</link>
|
|
||||||
<guid>#{escape(link)}</guid>
|
|
||||||
<description>#{escape(post.excerpt)}</description>#{pub}#{creator_tag}
|
|
||||||
</item>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def rfc822_date(post)
|
|
||||||
value = post.metadata["date"]
|
|
||||||
case value
|
|
||||||
when Date then value.to_time.rfc822
|
|
||||||
when Time then value.rfc822
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def feed_json
|
|
||||||
site = config.site
|
|
||||||
feed_url = "#{base_url}/api/volumen/feed.json"
|
|
||||||
{
|
|
||||||
"version" => "https://jsonfeed.org/version/1.1",
|
|
||||||
"title" => site["title"],
|
|
||||||
"home_page_url" => base_url,
|
|
||||||
"feed_url" => feed_url,
|
|
||||||
"description" => site["description"],
|
|
||||||
"language" => site["language"],
|
|
||||||
"items" => published_posts.first(20).map { |post| json_feed_item(post) }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def json_feed_item(post)
|
|
||||||
link = "#{base_url}/#{post.slug}"
|
|
||||||
item = {
|
|
||||||
"id" => link,
|
|
||||||
"url" => link,
|
|
||||||
"title" => post.title,
|
|
||||||
"content_html" => post.html,
|
|
||||||
"summary" => post.excerpt,
|
|
||||||
"date_published" => iso_date(post.metadata["date"]),
|
|
||||||
"tags" => post.tags
|
|
||||||
}
|
|
||||||
author = post.fediverse_creator || site_fediverse_creator
|
|
||||||
item["authors"] = [{ "name" => author }] if author
|
|
||||||
item.reject { |_k, v| v.nil? || v == "" || v == [] }
|
|
||||||
end
|
|
||||||
|
|
||||||
def iso_date(value)
|
|
||||||
case value
|
|
||||||
when Date then value.iso8601
|
|
||||||
when Time then value.to_date.iso8601
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def sitemap_xml
|
|
||||||
urls = published_posts.map do |post|
|
|
||||||
url = " <url><loc>#{escape("#{base_url}/#{post.slug}")}</loc>"
|
|
||||||
url << "<lastmod>#{escape(post.date_string)}</lastmod>" if post.date_string
|
|
||||||
url << "</url>"
|
|
||||||
end.join("\n")
|
|
||||||
<<~XML
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
||||||
#{urls}
|
|
||||||
</urlset>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def escape(text)
|
def escape(text)
|
||||||
Rack::Utils.escape_html(text.to_s)
|
Rack::Utils.escape_html(text.to_s)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user