Add RSS feed support for index and tag feeds
This commit is contained in:
parent
cd0d2ddf5b
commit
c81a9a430a
10 changed files with 145 additions and 22 deletions
|
@ -25,9 +25,4 @@ defmodule MebeEngine.Models do
|
|||
title: nil,
|
||||
content: nil
|
||||
end
|
||||
|
||||
defmodule Archive do
|
||||
defstruct key: nil,
|
||||
posts: nil
|
||||
end
|
||||
end
|
|
@ -17,8 +17,11 @@ config :mebe_web, MebeWeb.Endpoint,
|
|||
config :blog_config,
|
||||
blog_name: "My awesome blog",
|
||||
blog_author: "Author McAuthor",
|
||||
absolute_url: "http://localhost:4000", # Absolute URL to the site without trailing slash, including protocol
|
||||
enable_feeds: false, # Set to true to enable RSS feeds
|
||||
|
||||
posts_per_page: 10,
|
||||
posts_in_feed: 20,
|
||||
|
||||
# Disqus comments
|
||||
disqus_comments: false, # Use Disqus comments
|
||||
|
|
40
apps/mebe_web/web/controllers/controller_utils.ex
Normal file
40
apps/mebe_web/web/controllers/controller_utils.ex
Normal file
|
@ -0,0 +1,40 @@
|
|||
defmodule MebeWeb.ControllerUtils do
|
||||
use MebeWeb.Web, :controller
|
||||
|
||||
@moduledoc """
|
||||
This module contains the common functions for all controllers.
|
||||
"""
|
||||
|
||||
@blog_name Application.get_env(:blog_config, :blog_name)
|
||||
@blog_author Application.get_env(:blog_config, :blog_author)
|
||||
@absolute_url Application.get_env(:blog_config, :absolute_url)
|
||||
@posts_per_page Application.get_env(:blog_config, :posts_per_page)
|
||||
@disqus_comments Application.get_env(:blog_config, :disqus_comments)
|
||||
@page_commenting Application.get_env(:blog_config, :page_commenting)
|
||||
@disqus_shortname Application.get_env(:blog_config, :disqus_shortname)
|
||||
|
||||
@doc """
|
||||
Render a list of posts with the given template and params. The posts
|
||||
and generic configuration settings are assigned to the connection.
|
||||
"""
|
||||
def render_posts(conn, posts, template, _params) do
|
||||
conn
|
||||
|> insert_config
|
||||
|> assign(:posts, posts)
|
||||
|> render(template)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Insert common config variables to the assigns table for the connection
|
||||
"""
|
||||
def insert_config(conn) do
|
||||
conn
|
||||
|> assign(:blog_name, @blog_name)
|
||||
|> assign(:blog_author, @blog_author)
|
||||
|> assign(:absolute_url, @absolute_url)
|
||||
|> assign(:posts_per_page, @posts_per_page)
|
||||
|> assign(:disqus_comments, @disqus_comments)
|
||||
|> assign(:page_commenting, @page_commenting)
|
||||
|> assign(:disqus_shortname, @disqus_shortname)
|
||||
end
|
||||
end
|
35
apps/mebe_web/web/controllers/feed_controller.ex
Normal file
35
apps/mebe_web/web/controllers/feed_controller.ex
Normal file
|
@ -0,0 +1,35 @@
|
|||
defmodule MebeWeb.FeedController do
|
||||
use MebeWeb.Web, :controller
|
||||
|
||||
alias MebeEngine.DB
|
||||
import MebeWeb.ControllerUtils, only: [render_posts: 4]
|
||||
|
||||
plug :put_resp_content_type, "application/rss+xml"
|
||||
plug :put_layout_formats, ["xml"]
|
||||
plug :put_layout, "feed.xml"
|
||||
|
||||
@posts_in_feed Application.get_env(:blog_config, :posts_in_feed)
|
||||
|
||||
def index(conn, params) do
|
||||
posts = DB.get_reg_posts 0, @posts_in_feed
|
||||
|
||||
conn
|
||||
|> render_posts(posts, "postlist.xml", params)
|
||||
end
|
||||
|
||||
def tag(conn, params) do
|
||||
%{"tag" => tag} = params
|
||||
|
||||
posts = DB.get_tag_posts tag, 0, @posts_in_feed
|
||||
|
||||
conn
|
||||
|> assign(:tag, tag)
|
||||
|> render_posts(posts, "postlist.xml", params)
|
||||
end
|
||||
|
||||
defp put_headers(conn, key_values) do
|
||||
Enum.reduce key_values, conn, fn {k, v}, conn ->
|
||||
Plug.Conn.put_resp_header(conn, k, v)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,6 +2,7 @@ defmodule MebeWeb.PageController do
|
|||
use MebeWeb.Web, :controller
|
||||
|
||||
alias MebeEngine.DB
|
||||
import MebeWeb.ControllerUtils, only: [render_posts: 4, insert_config: 1]
|
||||
|
||||
@posts_per_page Application.get_env(:blog_config, :posts_per_page)
|
||||
|
||||
|
@ -119,7 +120,6 @@ defmodule MebeWeb.PageController do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
# Render a list page (a list of posts) or 404 if no posts could be found.
|
||||
# The postgetter should be an anonymous function which returns a list of
|
||||
# posts when called, or an empty list if none are found. The function gets
|
||||
|
@ -134,13 +134,11 @@ defmodule MebeWeb.PageController do
|
|||
|
||||
posts ->
|
||||
conn
|
||||
|> insert_config
|
||||
|> assign(:posts, posts)
|
||||
|> assign(:total_count, total_count)
|
||||
|> assign(:current_page, page)
|
||||
|> assign(:page_type, page_type)
|
||||
|> assign(:page_args, page_args)
|
||||
|> render(template)
|
||||
|> render_posts(posts, template, params)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -167,15 +165,4 @@ defmodule MebeWeb.PageController do
|
|||
|> put_status(:not_found)
|
||||
|> render(MebeWeb.ErrorView, :"404")
|
||||
end
|
||||
|
||||
# Insert config variables to the assigns table for the connection
|
||||
defp insert_config(conn) do
|
||||
conn
|
||||
|> assign(:blog_name, Application.get_env(:blog_config, :blog_name))
|
||||
|> assign(:blog_author, Application.get_env(:blog_config, :blog_author))
|
||||
|> assign(:posts_per_page, @posts_per_page)
|
||||
|> assign(:disqus_comments, Application.get_env(:blog_config, :disqus_comments))
|
||||
|> assign(:page_commenting, Application.get_env(:blog_config, :page_commenting))
|
||||
|> assign(:disqus_shortname, Application.get_env(:blog_config, :disqus_shortname))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
defmodule MebeWeb.Router do
|
||||
use Phoenix.Router
|
||||
|
||||
@enable_feeds Application.get_env(:blog_config, :enable_feeds)
|
||||
|
||||
pipeline :browser do
|
||||
plug MebeWeb.RequestStartTimePlug
|
||||
plug :accepts, ["html"]
|
||||
plug :accepts, ["html", "xml"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
end
|
||||
|
@ -14,9 +15,11 @@ defmodule MebeWeb.Router do
|
|||
|
||||
get "/p/:page", PageController, :index
|
||||
get "/", PageController, :index
|
||||
if @enable_feeds, do: (get "/feed", FeedController, :index)
|
||||
|
||||
get "/tag/:tag/p/:page", PageController, :tag
|
||||
get "/tag/:tag", PageController, :tag
|
||||
if @enable_feeds, do: (get "/tag/:tag/feed", FeedController, :tag)
|
||||
|
||||
get "/archive/:year/p/:page", PageController, :year
|
||||
get "/archive/:year", PageController, :year
|
||||
|
|
41
apps/mebe_web/web/templates/feed/postlist.xml.eex
Normal file
41
apps/mebe_web/web/templates/feed/postlist.xml.eex
Normal file
|
@ -0,0 +1,41 @@
|
|||
<%= for post <- @posts do %>
|
||||
<% {year, month, day} = post.date %>
|
||||
|
||||
<%
|
||||
# Justified versions of the month and day
|
||||
{j_month, j_day} = {
|
||||
String.rjust(Integer.to_string(month), 2, ?0),
|
||||
String.rjust(Integer.to_string(day), 2, ?0)
|
||||
}
|
||||
%>
|
||||
|
||||
<%
|
||||
# Quick and dirty RFC 822 month converter
|
||||
rfc_month = Enum.at(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], month - 1)
|
||||
|
||||
data = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
|
||||
dow_year = if month < 3, do: year - 1, else: year
|
||||
dow = rem(dow_year + div(dow_year, 4) - div(dow_year, 100) + div(dow_year, 400) + Enum.at(data, month - 1) + day, 7)
|
||||
dow_str = Enum.at(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], dow - 1)
|
||||
%>
|
||||
|
||||
<item>
|
||||
<title>
|
||||
<![CDATA[<%= post.title %>]]>
|
||||
</title>
|
||||
<link><%= @absolute_url %><%= page_path @conn, :post, year, j_month, j_day, post.slug %></link>
|
||||
<guid><%= @absolute_url %><%= page_path @conn, :post, year, j_month, j_day, post.slug %></guid>
|
||||
<description>
|
||||
<![CDATA[
|
||||
|
||||
<%= post.short_content %>
|
||||
|
||||
<a href="<%= @absolute_url %><%= page_path @conn, :post, year, j_month, j_day, post.slug %>">
|
||||
Read more…
|
||||
</a>
|
||||
|
||||
]]>
|
||||
</description>
|
||||
<pubDate><%= dow_str %>, <%= day %> <%= rfc_month %> <%= year %> 00:00:00 UT</pubDate>
|
||||
</item>
|
||||
<% end %>
|
|
@ -8,13 +8,19 @@
|
|||
|
||||
<title><%= title @conn %></title>
|
||||
<link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
|
||||
|
||||
<%= if assigns[:page_type] == :tag do %>
|
||||
<link href="<%= @absolute_url %><%= feed_path @conn, :tag, @tag %>" rel="alternate" type="application/rss+xml" title="RSS feed for tag <%= @tag %>" />
|
||||
<% else %>
|
||||
<link href="<%= @absolute_url %><%= feed_path @conn, :index %>" rel="alternate" type="application/rss+xml" title="RSS feed" />
|
||||
<% end %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a href="<%= page_path @conn, :index, 1 %>" class="navbar-brand">
|
||||
<a href="<%= @absolute_url %>" class="navbar-brand">
|
||||
<%= Application.get_env :blog_config, :blog_name %>
|
||||
</a>
|
||||
</div>
|
||||
|
|
10
apps/mebe_web/web/templates/layout/feed.xml.eex
Normal file
10
apps/mebe_web/web/templates/layout/feed.xml.eex
Normal file
|
@ -0,0 +1,10 @@
|
|||
<rss version="2.0">
|
||||
<channel>
|
||||
<title><%= title @conn %></title>
|
||||
<link><%= @absolute_url %></link>
|
||||
<description></description>
|
||||
<generator>Mebe</generator>
|
||||
|
||||
<%= @inner %>
|
||||
</channel>
|
||||
</rss>
|
3
apps/mebe_web/web/views/feed_view.ex
Normal file
3
apps/mebe_web/web/views/feed_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule MebeWeb.FeedView do
|
||||
use MebeWeb.Web, :view
|
||||
end
|
Reference in a new issue