Merge branch 'fix/tag-feed-crashes' into 'develop'
fix: atom/rss feed issues Closes #3045 See merge request pleroma/pleroma!3851
This commit is contained in:
commit
5cc23dc382
8 changed files with 56 additions and 17 deletions
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.Feed.FeedView do
|
||||||
use Phoenix.HTML
|
use Phoenix.HTML
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
alias Pleroma.Formatter
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.Gettext
|
alias Pleroma.Web.Gettext
|
||||||
|
@ -72,7 +71,9 @@ def logo(user) do
|
||||||
|
|
||||||
def last_activity(activities), do: List.last(activities)
|
def last_activity(activities), do: List.last(activities)
|
||||||
|
|
||||||
def activity_title(%{"content" => content, "summary" => summary} = data, opts \\ %{}) do
|
def activity_title(%{"content" => content} = data, opts \\ %{}) do
|
||||||
|
summary = Map.get(data, "summary", "")
|
||||||
|
|
||||||
title =
|
title =
|
||||||
cond do
|
cond do
|
||||||
summary != "" -> summary
|
summary != "" -> summary
|
||||||
|
@ -81,9 +82,8 @@ def activity_title(%{"content" => content, "summary" => summary} = data, opts \\
|
||||||
end
|
end
|
||||||
|
|
||||||
title
|
title
|
||||||
|> Pleroma.Web.Metadata.Utils.scrub_html()
|
|> Pleroma.Web.Metadata.Utils.scrub_html_and_truncate(opts[:max_length], opts[:omission])
|
||||||
|> Pleroma.Emoji.Formatter.demojify()
|
|> HtmlEntities.encode()
|
||||||
|> Formatter.truncate(opts[:max_length], opts[:omission])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def activity_description(data) do
|
def activity_description(data) do
|
||||||
|
|
|
@ -30,12 +30,13 @@ def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do
|
||||||
|> scrub_html_and_truncate_object_field(object)
|
|> scrub_html_and_truncate_object_field(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrub_html_and_truncate(content, max_length \\ 200) when is_binary(content) do
|
def scrub_html_and_truncate(content, max_length \\ 200, omission \\ "...")
|
||||||
|
when is_binary(content) do
|
||||||
content
|
content
|
||||||
|> scrub_html
|
|> scrub_html
|
||||||
|> Emoji.Formatter.demojify()
|
|> Emoji.Formatter.demojify()
|
||||||
|> HtmlEntities.decode()
|
|> HtmlEntities.decode()
|
||||||
|> Formatter.truncate(max_length)
|
|> Formatter.truncate(max_length, omission)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrub_html(content) when is_binary(content) do
|
def scrub_html(content) when is_binary(content) do
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
<id><%= @data["id"] %></id>
|
<id><%= @data["id"] %></id>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<content type="html"><%= activity_description(@data) %></content>
|
<content type="html"><%= activity_description(@data) %></content>
|
||||||
<published><%= to_rfc3339(@activity.data["published"]) %></published>
|
<published><%= to_rfc3339(@data["published"]) %></published>
|
||||||
<updated><%= to_rfc3339(@activity.data["published"]) %></updated>
|
<updated><%= to_rfc3339(@data["published"]) %></updated>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<guid><%= @data["id"] %></guid>
|
<guid><%= @data["id"] %></guid>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<description><%= activity_description(@data) %></description>
|
<description><%= activity_description(@data) %></description>
|
||||||
<pubDate><%= to_rfc2822(@activity.data["published"]) %></pubDate>
|
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<id><%= @data["id"] %></id>
|
<id><%= @data["id"] %></id>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<content type="html"><%= activity_description(@data) %></content>
|
<content type="html"><%= activity_description(@data) %></content>
|
||||||
<published><%= to_rfc3339(@activity.data["published"]) %></published>
|
<published><%= to_rfc3339(@data["published"]) %></published>
|
||||||
<updated><%= to_rfc3339(@activity.data["published"]) %></updated>
|
<updated><%= to_rfc3339(@data["published"]) %></updated>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<guid isPermalink="true"><%= activity_context(@activity) %></guid>
|
<guid isPermalink="true"><%= activity_context(@activity) %></guid>
|
||||||
<link><%= activity_context(@activity) %></link>
|
<link><%= activity_context(@activity) %></link>
|
||||||
<pubDate><%= to_rfc2822(@activity.data["published"]) %></pubDate>
|
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
|
||||||
|
|
||||||
<description><%= activity_description(@data) %></description>
|
<description><%= activity_description(@data) %></description>
|
||||||
<%= for attachment <- @data["attachment"] || [] do %>
|
<%= for attachment <- @data["attachment"] || [] do %>
|
||||||
|
|
|
@ -57,9 +57,23 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
||||||
)
|
)
|
||||||
|
|
||||||
note_activity2 = insert(:note_activity, note: note2)
|
note_activity2 = insert(:note_activity, note: note2)
|
||||||
|
|
||||||
|
note3 =
|
||||||
|
insert(:note,
|
||||||
|
user: user,
|
||||||
|
data: %{
|
||||||
|
"content" => "This note tests whether HTML entities are truncated properly",
|
||||||
|
"summary" => "Won't, didn't fail",
|
||||||
|
"inReplyTo" => note_activity2.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
_note_activity3 = insert(:note_activity, note: note3)
|
||||||
object = Object.normalize(note_activity, fetch: false)
|
object = Object.normalize(note_activity, fetch: false)
|
||||||
|
|
||||||
[user: user, object: object, max_id: note_activity2.id]
|
encoded_title = FeedView.activity_title(note3.data)
|
||||||
|
|
||||||
|
[user: user, object: object, max_id: note_activity2.id, encoded_title: encoded_title]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
|
test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
|
||||||
|
@ -74,7 +88,7 @@ test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_
|
||||||
|> SweetXml.parse()
|
|> SweetXml.parse()
|
||||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||||
|
|
||||||
assert activity_titles == ['2hu', '2hu & as']
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
assert resp =~ FeedView.escape(object.data["content"])
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
assert resp =~ FeedView.escape(object.data["summary"])
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
assert resp =~ FeedView.escape(object.data["context"])
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
@ -105,7 +119,7 @@ test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id
|
||||||
|> SweetXml.parse()
|
|> SweetXml.parse()
|
||||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||||
|
|
||||||
assert activity_titles == ['2hu', '2hu & as']
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
assert resp =~ FeedView.escape(object.data["content"])
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
assert resp =~ FeedView.escape(object.data["summary"])
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
assert resp =~ FeedView.escape(object.data["context"])
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
@ -176,6 +190,30 @@ test "does not require authentication on non-federating instances", %{conn: conn
|
||||||
|> get("/users/#{user.nickname}/feed.rss")
|
|> get("/users/#{user.nickname}/feed.rss")
|
||||||
|> response(200)
|
|> response(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does not mangle HTML entities midway", %{
|
||||||
|
conn: conn,
|
||||||
|
user: user,
|
||||||
|
object: object,
|
||||||
|
encoded_title: encoded_title
|
||||||
|
} do
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/atom+xml")
|
||||||
|
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
activity_titles =
|
||||||
|
resp
|
||||||
|
|> SweetXml.parse()
|
||||||
|
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||||
|
|
||||||
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
assert resp =~ encoded_title
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note: see ActivityPubControllerTest for JSON format tests
|
# Note: see ActivityPubControllerTest for JSON format tests
|
||||||
|
|
|
@ -72,7 +72,7 @@ test "it does not return old content after editing" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "scrub_html_and_truncate/2" do
|
describe "scrub_html_and_truncate/3" do
|
||||||
test "it returns text without encode HTML" do
|
test "it returns text without encode HTML" do
|
||||||
assert Utils.scrub_html_and_truncate("Pleroma's really cool!") == "Pleroma's really cool!"
|
assert Utils.scrub_html_and_truncate("Pleroma's really cool!") == "Pleroma's really cool!"
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue