RichMedia: skip the quote fallback link when picking the card URL

Mastodon, Misskey and InlineQuotePolicy put "RE: <url>" in a .quote-inline
element at the start of a quote post. Its link was taken for the link card,
which then showed the quoted post a second time.
This commit is contained in:
Lain Soykaf 2026-10-13 21:39:43 +04:00
commit d13000b2b9
No known key found for this signature in database
3 changed files with 43 additions and 3 deletions

View file

@ -0,0 +1 @@
Link preview cards skip the fallback link of quote posts (`RE: <url>`), which pointed at the quoted post and showed it twice.

View file

@ -66,14 +66,16 @@ defmodule Pleroma.HTML do
end
@spec extract_first_external_url_from_object(Pleroma.Object.t()) :: String.t() | nil
def extract_first_external_url_from_object(%{data: %{"content" => content}})
def extract_first_external_url_from_object(%{data: %{"content" => content} = data})
when is_binary(content) do
# A quote post's fallback link ("RE: <url>", in a .quote-inline element or
# bare) points at the quoted post, which is shown already.
content
|> Floki.parse_fragment!()
|> Floki.filter_out(".quote-inline")
|> Floki.find("a:not(.mention,.hashtag,.attachment,[rel~=\"tag\"])")
|> Enum.take(1)
|> Floki.attribute("href")
|> Enum.at(0)
|> Enum.find(&(&1 != data["quoteUrl"]))
end
def extract_first_external_url_from_object(_), do: nil

View file

@ -299,5 +299,42 @@ defmodule Pleroma.HTMLTest do
assert nil == HTML.extract_first_external_url_from_object(object)
end
test "skips the link in a Mastodon quote fallback paragraph" do
object = %Object{
data: %{
"quoteUrl" => "https://raru.re/users/ocean/statuses/116235427788617987",
"content" =>
"<p class=\"quote-inline\">RE: <a href=\"https://raru.re/@ocean/116235427788617987\">raru.re/@ocean/116235427788617987</a></p>" <>
"<p>Berapa lapis?</p><p><a href=\"https://www.youtube.com/watch?v=S0dJMhWDRDE\">youtube.com/watch?v=S0dJMhWDRDE</a></p>"
}
}
assert HTML.extract_first_external_url_from_object(object) ==
"https://www.youtube.com/watch?v=S0dJMhWDRDE"
end
test "skips the link in a quote fallback span (Misskey, InlineQuotePolicy)" do
object = %Object{
data: %{
"content" =>
"hello<span class=\"quote-inline\"><br/><br/>RE: <a href=\"https://misskey.example/notes/abc\">https://misskey.example/notes/abc</a></span>"
}
}
assert nil == HTML.extract_first_external_url_from_object(object)
end
test "skips a link to the quoted post without fallback markup" do
object = %Object{
data: %{
"quoteUrl" => "https://remote.example/objects/1",
"content" =>
"RE: <a href=\"https://remote.example/objects/1\">https://remote.example/objects/1</a> <a href=\"https://cofe.example/\">cofe</a>"
}
}
assert HTML.extract_first_external_url_from_object(object) == "https://cofe.example/"
end
end
end