formatter.ex: Use Phoenix.HTML for mention/hashtag generation

Unlike concatenating strings, this makes sure everything is escaped.
Tests had to be changed because Phoenix.HTML runs attributes through
Enum.sort before generation for whatever reason.
This commit is contained in:
rinpatch 2020-04-08 22:58:31 +03:00
parent dd4d10b275
commit d067eaa7b3
7 changed files with 41 additions and 27 deletions

View file

@ -35,9 +35,19 @@ def mention_handler("@" <> nickname, buffer, opts, acc) do
nickname_text = get_nickname_text(nickname, opts) nickname_text = get_nickname_text(nickname, opts)
link = link =
~s(<span class="h-card"><a data-user="#{id}" class="u-url mention" href="#{ap_id}" rel="ugc">@<span>#{ Phoenix.HTML.Tag.content_tag(
nickname_text :span,
}</span></a></span>) Phoenix.HTML.Tag.content_tag(
:a,
["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
"data-user": id,
class: "u-url mention",
href: ap_id,
rel: "ugc"
),
class: "h-card"
)
|> Phoenix.HTML.safe_to_string()
{link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}} {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
@ -49,7 +59,15 @@ def mention_handler("@" <> nickname, buffer, opts, acc) do
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
tag = String.downcase(tag) tag = String.downcase(tag)
url = "#{Pleroma.Web.base_url()}/tag/#{tag}" url = "#{Pleroma.Web.base_url()}/tag/#{tag}"
link = ~s(<a class="hashtag" data-tag="#{tag}" href="#{url}" rel="tag ugc">#{tag_text}</a>)
link =
Phoenix.HTML.Tag.content_tag(:a, tag_text,
class: "hashtag",
"data-tag": tag,
href: url,
rel: "tag ugc"
)
|> Phoenix.HTML.safe_to_string()
{link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}} {link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}}
end end

View file

@ -150,13 +150,13 @@ test "gives a replacement for user links, using local nicknames in user links te
assert length(mentions) == 3 assert length(mentions) == 3
expected_text = expected_text =
~s(<span class="h-card"><a data-user="#{gsimg.id}" class="u-url mention" href="#{ ~s(<span class="h-card"><a class="u-url mention" data-user="#{gsimg.id}" href="#{
gsimg.ap_id gsimg.ap_id
}" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a data-user="#{ }" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a class="u-url mention" data-user="#{
archaeme.id archaeme.id
}" class="u-url mention" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a data-user="#{ }" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a class="u-url mention" data-user="#{
archaeme_remote.id archaeme_remote.id
}" class="u-url mention" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>) }" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>)
assert expected_text == text assert expected_text == text
end end
@ -171,7 +171,7 @@ test "gives a replacement for user links when the user is using Osada" do
assert length(mentions) == 1 assert length(mentions) == 1
expected_text = expected_text =
~s(<span class="h-card"><a data-user="#{mike.id}" class="u-url mention" href="#{ ~s(<span class="h-card"><a class="u-url mention" data-user="#{mike.id}" href="#{
mike.ap_id mike.ap_id
}" rel="ugc">@<span>mike</span></a></span> test) }" rel="ugc">@<span>mike</span></a></span> test)
@ -187,7 +187,7 @@ test "gives a replacement for single-character local nicknames" do
assert length(mentions) == 1 assert length(mentions) == 1
expected_text = expected_text =
~s(<span class="h-card"><a data-user="#{o.id}" class="u-url mention" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi) ~s(<span class="h-card"><a class="u-url mention" data-user="#{o.id}" href="#{o.ap_id}" rel="ugc">@<span>o</span></a></span> hi)
assert expected_text == text assert expected_text == text
end end
@ -209,17 +209,13 @@ test "given the 'safe_mention' option, it will only mention people in the beginn
assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}] assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}]
assert expected_text == assert expected_text ==
~s(<span class="h-card"><a data-user="#{user.id}" class="u-url mention" href="#{ ~s(<span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="#{
user.ap_id user.ap_id
}" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a data-user="#{ }" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{
other_user.id other_user.id
}" class="u-url mention" href="#{other_user.ap_id}" rel="ugc">@<span>#{ }" href="#{other_user.ap_id}" rel="ugc">@<span>#{other_user.nickname}</span></a></span> hey dudes i hate <span class="h-card"><a class="u-url mention" data-user="#{
other_user.nickname
}</span></a></span> hey dudes i hate <span class="h-card"><a data-user="#{
third_user.id third_user.id
}" class="u-url mention" href="#{third_user.ap_id}" rel="ugc">@<span>#{ }" href="#{third_user.ap_id}" rel="ugc">@<span>#{third_user.nickname}</span></a></span>)
third_user.nickname
}</span></a></span>)
end end
test "given the 'safe_mention' option, it will still work without any mention" do test "given the 'safe_mention' option, it will still work without any mention" do

View file

@ -1404,7 +1404,7 @@ test "preserves hosts in user links text" do
bio = "A.k.a. @nick@domain.com" bio = "A.k.a. @nick@domain.com"
expected_text = expected_text =
~s(A.k.a. <span class="h-card"><a data-user="#{remote_user.id}" class="u-url mention" href="#{ ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
remote_user.ap_id remote_user.ap_id
}" rel="ugc">@<span>nick@domain.com</span></a></span>) }" rel="ugc">@<span>nick@domain.com</span></a></span>)

View file

@ -159,11 +159,11 @@ test "works for text/markdown with mentions" do
{output, _, _} = Utils.format_input(text, "text/markdown") {output, _, _} = Utils.format_input(text, "text/markdown")
assert output == assert output ==
~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a data-user="#{ ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{
user.id user.id
}" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a data-user="#{ }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{
user.id user.id
}" class="u-url mention" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>) }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>)
end end
end end

View file

@ -82,9 +82,9 @@ test "updates the user's bio", %{conn: conn} do
assert user_data = json_response(conn, 200) assert user_data = json_response(conn, 200)
assert user_data["note"] == assert user_data["note"] ==
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user="#{ ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{
user2.id user2.id
}" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..) }" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
end end
test "updates the user's locking status", %{conn: conn} do test "updates the user's locking status", %{conn: conn} do

View file

@ -26,7 +26,7 @@ test "list of notifications" do
|> get("/api/v1/notifications") |> get("/api/v1/notifications")
expected_response = expected_response =
"hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{ "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
user.ap_id user.ap_id
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
@ -45,7 +45,7 @@ test "getting a single notification" do
conn = get(conn, "/api/v1/notifications/#{notification.id}") conn = get(conn, "/api/v1/notifications/#{notification.id}")
expected_response = expected_response =
"hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{ "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
user.ap_id user.ap_id
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"

View file

@ -109,7 +109,7 @@ test "it registers a new user and parses mentions in the bio" do
{:ok, user2} = TwitterAPI.register_user(data2) {:ok, user2} = TwitterAPI.register_user(data2)
expected_text = expected_text =
~s(<span class="h-card"><a data-user="#{user1.id}" class="u-url mention" href="#{ ~s(<span class="h-card"><a class="u-url mention" data-user="#{user1.id}" href="#{
user1.ap_id user1.ap_id
}" rel="ugc">@<span>john</span></a></span> test) }" rel="ugc">@<span>john</span></a></span> test)