From 4cafb8a89a4b23f74cda5a6737803d8bb9e9ce8a Mon Sep 17 00:00:00 2001 From: Peter Zingg Date: Mon, 12 Dec 2022 18:18:13 -0800 Subject: [PATCH] passes w3c validator --- lib/pleroma/web/feed/feed_view.ex | 48 ++++++++++++++----- .../templates/feed/feed/_activity.atom.eex | 12 ++--- .../web/templates/feed/feed/_activity.rss.eex | 19 ++++---- .../web/templates/feed/feed/_author.atom.eex | 17 +++---- .../web/templates/feed/feed/_author.rss.eex | 22 +++++---- .../feed/feed/_tag_activity.atom.eex | 10 ++-- .../templates/feed/feed/_tag_activity.xml.eex | 2 +- .../web/templates/feed/feed/tag.atom.eex | 6 +-- .../web/templates/feed/feed/tag.rss.eex | 2 +- .../web/templates/feed/feed/user.atom.eex | 10 ++-- .../web/templates/feed/feed/user.rss.eex | 24 +++++++--- test/pleroma/web/feed/tag_controller_test.exs | 4 +- 12 files changed, 110 insertions(+), 66 deletions(-) diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex index 52771205e..f0c4709a1 100644 --- a/lib/pleroma/web/feed/feed_view.ex +++ b/lib/pleroma/web/feed/feed_view.ex @@ -14,14 +14,14 @@ defmodule Pleroma.Web.Feed.FeedView do require Pleroma.Constants - @spec pub_date(String.t() | DateTime.t()) :: String.t() - def pub_date(date) when is_binary(date) do + @spec pub_date(String.t() | DateTime.t() | NaiveDateTime.t(), String.t()) :: String.t() + def pub_date(date, format) when is_binary(date) do date |> Timex.parse!("{ISO:Extended}") - |> pub_date + |> pub_date(format) end - def pub_date(%DateTime{} = date), do: Timex.format!(date, "{RFC822}") + def pub_date(date, format), do: Timex.format!(date, format) def prepare_activity(activity, opts \\ []) do object = Object.normalize(activity, fetch: false) @@ -39,15 +39,14 @@ defmodule Pleroma.Web.Feed.FeedView do } end - def most_recent_update(activities) do + def most_recent_update(activities, format) do with %{updated_at: updated_at} <- List.first(activities) do - NaiveDateTime.to_iso8601(updated_at) + Timex.format!(updated_at, format) end end - def most_recent_update(activities, user) do - (List.first(activities) || user).updated_at - |> NaiveDateTime.to_iso8601() + def most_recent_update(activities, user, format) do + (List.first(activities) || user).updated_at |> Timex.format!(format) end def feed_logo do @@ -107,9 +106,36 @@ defmodule Pleroma.Web.Feed.FeedView do end end - def escape(html) do - html + def escape(str) do + str |> html_escape() |> safe_to_string() + |> xml_escape() end + + # Encoding newlines, e.g., per XML spec + def xml_escape(nil), do: "" + def xml_escape(str) when is_binary(str) do + str + |> xml_escape_string() + |> to_string() + end + + defp xml_escape_string(""), do: "" + defp xml_escape_string(<<"&"::utf8, rest::binary>>), do: xml_escape_entity(rest) + defp xml_escape_string(<<"<"::utf8, rest::binary>>), do: ["<" | xml_escape_string(rest)] + defp xml_escape_string(<<">"::utf8, rest::binary>>), do: [">" | xml_escape_string(rest)] + defp xml_escape_string(<<"\""::utf8, rest::binary>>), do: [""" | xml_escape_string(rest)] + defp xml_escape_string(<<"'"::utf8, rest::binary>>), do: ["'" | xml_escape_string(rest)] + defp xml_escape_string(<<"\t"::utf8, rest::binary>>), do: [" " | xml_escape_string(rest)] + defp xml_escape_string(<<"\n"::utf8, rest::binary>>), do: [" " | xml_escape_string(rest)] + defp xml_escape_string(<<"\r\n"::utf8, rest::binary>>), do: [" " | xml_escape_string(rest)] + defp xml_escape_string(<<"\r"::utf8, rest::binary>>), do: [" " | xml_escape_string(rest)] + defp xml_escape_string(<>), do: [c | xml_escape_string(rest)] + defp xml_escape_entity(<<"amp;"::utf8, rest::binary>>), do: ["&" | xml_escape_string(rest)] + defp xml_escape_entity(<<"lt;"::utf8, rest::binary>>), do: ["<" | xml_escape_string(rest)] + defp xml_escape_entity(<<"gt;"::utf8, rest::binary>>), do: [">" | xml_escape_string(rest)] + defp xml_escape_entity(<<"quot;"::utf8, rest::binary>>), do: [""" | xml_escape_string(rest)] + defp xml_escape_entity(<<"apos;"::utf8, rest::binary>>), do: ["'" | xml_escape_string(rest)] + defp xml_escape_entity(rest), do: ["&" | xml_escape_string(rest)] end diff --git a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex index 57bd92468..9fb14334c 100644 --- a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex +++ b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex @@ -4,8 +4,8 @@ <%= @data["id"] %> <%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %> <%= activity_content(@data) %> - <%= @activity.data["published"] %> - <%= @activity.data["published"] %> + <%= pub_date(@activity.data["published"], "{RFC3339z}") %> + <%= pub_date(@activity.data["published"], "{RFC3339z}") %> <%= activity_context(@activity) %> @@ -16,10 +16,10 @@ <% end %> <%= if @activity.local do %> - - + " rel="self"/> + " rel="alternate"/> <% else %> - + " rel="alternate"/> <% end %> <%= for tag <- Pleroma.Object.hashtags(@object) do %> @@ -31,7 +31,7 @@ <% end %> <%= if @data["inReplyTo"] do %> - + " href="<%= get_href(@data["inReplyTo"]) %>"/> <% end %> <%= for id <- @activity.recipients do %> diff --git a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex index 279f2171d..1410aa90b 100644 --- a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex +++ b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex @@ -4,14 +4,17 @@ <%= @data["id"] %> <%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %> <%= activity_content(@data) %> - <%= @activity.data["published"] %> - <%= @activity.data["published"] %> + <%= pub_date(@activity.data["published"], "{RFC822z}") %> <%= activity_context(@activity) %> <%= if @data["summary"] do %> - <%= escape(@data["summary"]) %> + <%= escape(@data["summary"]) %> + <% end %> + + <%= if get_in(@data, ["source", "mediaType"]) == "text/markdown" do %> + <%= escape(get_in(@data, ["source", "content"])) %> <% end %> <%= if @activity.local do %> @@ -20,26 +23,26 @@ <%= @data["external_url"] %> <% end %> - <%= activity_context(@activity) %> + <%= for tag <- Pleroma.Object.hashtags(@object) do %> <% end %> <%= for attachment <- @data["attachment"] || [] do %> - <%= attachment_href(attachment) %> + <% end %> <%= if @data["inReplyTo"] do %> - + " href="<%= get_href(@data["inReplyTo"]) %>"/> <% end %> <%= for id <- @activity.recipients do %> <%= if id == Pleroma.Constants.as_public() do %> - http://activityschema.org/collection/public + <% else %> <%= unless Regex.match?(~r/^#{Pleroma.Web.Endpoint.url()}.+followers$/, id) do %> - <%= id %> + <% end %> <% end %> <% end %> diff --git a/lib/pleroma/web/templates/feed/feed/_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_author.atom.eex index 25cbffada..7b1eaae19 100644 --- a/lib/pleroma/web/templates/feed/feed/_author.atom.eex +++ b/lib/pleroma/web/templates/feed/feed/_author.atom.eex @@ -1,17 +1,18 @@ - <%= @user.ap_id %> - http://activitystrea.ms/schema/1.0/person + <%= @user.nickname %> <%= @user.ap_id %> + <%= @user.email %> + http://activitystrea.ms/schema/1.0/person <%= @user.nickname %> <%= @user.name %> - <%= escape(@user.bio) %> - <%= escape(@user.bio) %> - <%= @user.nickname %> - + <%= if @user.bio do %> + <%= escape(@user.bio) %> + <% end %> + <%= if User.banner_url(@user) do %> - + <% end %> <%= if @user.local do %> - true + true <% end %> diff --git a/lib/pleroma/web/templates/feed/feed/_author.rss.eex b/lib/pleroma/web/templates/feed/feed/_author.rss.eex index 526aeddcf..fe82f4b02 100644 --- a/lib/pleroma/web/templates/feed/feed/_author.rss.eex +++ b/lib/pleroma/web/templates/feed/feed/_author.rss.eex @@ -1,17 +1,19 @@ - - <%= @user.ap_id %> +<%= @user.email %> + + <%= @user.nickname %> + <%= @user.ap_id %> + <%= @user.email %> http://activitystrea.ms/schema/1.0/person - <%= @user.ap_id %> <%= @user.nickname %> <%= @user.name %> - <%= escape(@user.bio) %> - <%= escape(@user.bio) %> - <%= @user.nickname %> - <%= User.avatar_url(@user) %> + <%= if @user.bio do %> + <%= escape(@user.bio) %> + <% end %> + <%= if User.banner_url(@user) do %> - <%= User.banner_url(@user) %> + <% end %> <%= if @user.local do %> - true + true <% end %> - + diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex index aa3035bca..eba64c27d 100644 --- a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex +++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex @@ -9,14 +9,14 @@ <%= activity_content(@data) %> <%= if @activity.local do %> - - + " rel="self"/> + " rel="alternate"/> <% else %> - + " rel="alternate"/> <% end %> - <%= @activity.data["published"] %> - <%= @activity.data["published"] %> + <%= pub_date(@activity.data["published"], "{RFC3339z}") %> + <%= pub_date(@activity.data["published"], "{RFC3339z}") %> <%= activity_context(@activity) %> diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex index 2334e24a2..2d387c3b7 100644 --- a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex +++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex @@ -4,7 +4,7 @@ <%= activity_context(@activity) %> <%= activity_context(@activity) %> - <%= pub_date(@activity.data["published"]) %> + <%= pub_date(@activity.data["published"], "{RFC822z}") %> <%= activity_content(@data) %> <%= for attachment <- @data["attachment"] || [] do %> diff --git a/lib/pleroma/web/templates/feed/feed/tag.atom.eex b/lib/pleroma/web/templates/feed/feed/tag.atom.eex index 6d497e84c..819359f20 100644 --- a/lib/pleroma/web/templates/feed/feed/tag.atom.eex +++ b/lib/pleroma/web/templates/feed/feed/tag.atom.eex @@ -9,13 +9,13 @@ xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:statusnet="http://status.net/schema/api/1/"> - <%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %> + <%= Routes.tag_feed_url(@conn, :feed, @tag) <> ".atom" %> #<%= @tag %> <%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %> <%= feed_logo() %> - <%= most_recent_update(@activities) %> - + <%= most_recent_update(@activities, "{RFC3339z}") %> + " type="application/atom+xml"/> <%= for activity <- @activities do %> <%= render @view_module, "_tag_activity.atom", Map.merge(assigns, prepare_activity(activity, actor: true)) %> <% end %> diff --git a/lib/pleroma/web/templates/feed/feed/tag.rss.eex b/lib/pleroma/web/templates/feed/feed/tag.rss.eex index edcc3e436..8b40a4e9c 100644 --- a/lib/pleroma/web/templates/feed/feed/tag.rss.eex +++ b/lib/pleroma/web/templates/feed/feed/tag.rss.eex @@ -5,7 +5,7 @@ #<%= @tag %> <%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %> - <%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %> + <%= "#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss" %> <%= feed_logo() %> 2b90d9 <%= for activity <- @activities do %> diff --git a/lib/pleroma/web/templates/feed/feed/user.atom.eex b/lib/pleroma/web/templates/feed/feed/user.atom.eex index 5c1f0ecbc..62b58ed09 100644 --- a/lib/pleroma/web/templates/feed/feed/user.atom.eex +++ b/lib/pleroma/web/templates/feed/feed/user.atom.eex @@ -1,21 +1,23 @@ + xmlns:ostatus="http://ostatus.org/schema/1.0" + xmlns:ap="https://www.w3.org/TR/activitypub/"> <%= Routes.user_feed_url(@conn, :feed, @user.nickname) <> ".atom" %> <%= @user.nickname <> "'s timeline" %> - <%= most_recent_update(@activities, @user) %> + <%= most_recent_update(@activities, @user, "{RFC3339z}") %> <%= logo(@user) %> - + " type="application/atom+xml"/> <%= render @view_module, "_author.atom", assigns %> <%= if last_activity(@activities) do %> - + " type="application/atom+xml"/> <% end %> <%= for activity <- @activities do %> diff --git a/lib/pleroma/web/templates/feed/feed/user.rss.eex b/lib/pleroma/web/templates/feed/feed/user.rss.eex index 6b842a085..5a1d01c98 100644 --- a/lib/pleroma/web/templates/feed/feed/user.rss.eex +++ b/lib/pleroma/web/templates/feed/feed/user.rss.eex @@ -1,18 +1,28 @@ - + - <%= Routes.user_feed_url(@conn, :feed, @user.nickname) <> ".rss" %> <%= @user.nickname <> "'s timeline" %> - <%= most_recent_update(@activities, @user) %> - <%= logo(@user) %> - <%= '#{Routes.user_feed_url(@conn, :feed, @user.nickname)}.rss' %> + Publicly visible items published by <%= @user.nickname %> + <%= Routes.user_feed_url(@conn, :feed, @user.nickname) <> ".rss" %> + <%= most_recent_update(@activities, @user, "{RFC822z}") %> + + <%= logo(@user) %> + <%= @user.nickname <> "'s avatar" %> + <%= logo(@user) %> + <%= render @view_module, "_author.rss", assigns %> <%= if last_activity(@activities) do %> - <%= '#{Routes.user_feed_url(@conn, :feed, @user.nickname)}.rss?max_id=#{last_activity(@activities).id}' %> +