Fix TwitterCard meta tags
TwitterCard meta tags are supposed to use the attributes "name" and "content". OpenGraph tags use the attributes "property" and "content". Twitter itself is smart enough to detect broken meta tags and discover the TwitterCard using "property" and "content", but other platforms that only implement parsing of TwitterCards and not OpenGraph may fail to correctly detect the tags as they're under the wrong attributes. > "Open Graph protocol also specifies the use of property and content attributes for markup while > Twitter cards use name and content. Twitter’s parser will fall back to using property and content, > so there is no need to modify existing Open Graph protocol markup if it already exists." [0] [0] https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started
This commit is contained in:
parent
8db82932a7
commit
72d4d1b392
|
@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fixed lowercase HTTP HEAD method in the Media Proxy Preview code
|
- Fixed lowercase HTTP HEAD method in the Media Proxy Preview code
|
||||||
- Removed useless notification call on Delete activities
|
- Removed useless notification call on Delete activities
|
||||||
- Improved performance for filtering out deactivated and invisible users
|
- Improved performance for filtering out deactivated and invisible users
|
||||||
|
- TwitterCard meta tags conformance
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Quack, the logging backend that pushes to Slack channels
|
- Quack, the logging backend that pushes to Slack channels
|
||||||
|
|
|
@ -20,12 +20,12 @@ def build_tags(%{activity_id: id, object: object, user: user}) do
|
||||||
|
|
||||||
[
|
[
|
||||||
title_tag(user),
|
title_tag(user),
|
||||||
{:meta, [property: "twitter:description", content: scrubbed_content], []}
|
{:meta, [name: "twitter:description", content: scrubbed_content], []}
|
||||||
] ++
|
] ++
|
||||||
if attachments == [] or Metadata.activity_nsfw?(object) do
|
if attachments == [] or Metadata.activity_nsfw?(object) do
|
||||||
[
|
[
|
||||||
image_tag(user),
|
image_tag(user),
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
attachments
|
attachments
|
||||||
|
@ -37,20 +37,19 @@ def build_tags(%{user: user}) do
|
||||||
with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
|
with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
|
||||||
[
|
[
|
||||||
title_tag(user),
|
title_tag(user),
|
||||||
{:meta, [property: "twitter:description", content: truncated_bio], []},
|
{:meta, [name: "twitter:description", content: truncated_bio], []},
|
||||||
image_tag(user),
|
image_tag(user),
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp title_tag(user) do
|
defp title_tag(user) do
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []}
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_tag(user) do
|
def image_tag(user) do
|
||||||
{:meta, [property: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))],
|
{:meta, [name: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))], []}
|
||||||
[]}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
|
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
|
||||||
|
@ -60,10 +59,10 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
|
||||||
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
|
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
|
||||||
"audio" ->
|
"audio" ->
|
||||||
[
|
[
|
||||||
{:meta, [property: "twitter:card", content: "player"], []},
|
{:meta, [name: "twitter:card", content: "player"], []},
|
||||||
{:meta, [property: "twitter:player:width", content: "480"], []},
|
{:meta, [name: "twitter:player:width", content: "480"], []},
|
||||||
{:meta, [property: "twitter:player:height", content: "80"], []},
|
{:meta, [name: "twitter:player:height", content: "80"], []},
|
||||||
{:meta, [property: "twitter:player", content: player_url(id)], []}
|
{:meta, [name: "twitter:player", content: player_url(id)], []}
|
||||||
| acc
|
| acc
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -74,10 +73,10 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
|
||||||
# workaround.
|
# workaround.
|
||||||
"image" ->
|
"image" ->
|
||||||
[
|
[
|
||||||
{:meta, [property: "twitter:card", content: "summary_large_image"], []},
|
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||||
{:meta,
|
{:meta,
|
||||||
[
|
[
|
||||||
property: "twitter:player",
|
name: "twitter:player",
|
||||||
content: MediaProxy.url(url["href"])
|
content: MediaProxy.url(url["href"])
|
||||||
], []}
|
], []}
|
||||||
| acc
|
| acc
|
||||||
|
@ -90,14 +89,14 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
|
||||||
width = url["width"] || 480
|
width = url["width"] || 480
|
||||||
|
|
||||||
[
|
[
|
||||||
{:meta, [property: "twitter:card", content: "player"], []},
|
{:meta, [name: "twitter:card", content: "player"], []},
|
||||||
{:meta, [property: "twitter:player", content: player_url(id)], []},
|
{:meta, [name: "twitter:player", content: player_url(id)], []},
|
||||||
{:meta, [property: "twitter:player:width", content: "#{width}"], []},
|
{:meta, [name: "twitter:player:width", content: "#{width}"], []},
|
||||||
{:meta, [property: "twitter:player:height", content: "#{height}"], []},
|
{:meta, [name: "twitter:player:height", content: "#{height}"], []},
|
||||||
{:meta, [property: "twitter:player:stream", content: MediaProxy.url(url["href"])],
|
{:meta, [name: "twitter:player:stream", content: MediaProxy.url(url["href"])],
|
||||||
[]},
|
[]},
|
||||||
{:meta,
|
{:meta, [name: "twitter:player:stream:content_type", content: url["mediaType"]],
|
||||||
[property: "twitter:player:stream:content_type", content: url["mediaType"]], []}
|
[]}
|
||||||
| acc
|
| acc
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -123,8 +122,8 @@ defp maybe_add_dimensions(metadata, url) do
|
||||||
!is_nil(url["height"]) && !is_nil(url["width"]) ->
|
!is_nil(url["height"]) && !is_nil(url["width"]) ->
|
||||||
metadata ++
|
metadata ++
|
||||||
[
|
[
|
||||||
{:meta, [property: "twitter:player:width", content: "#{url["width"]}"], []},
|
{:meta, [name: "twitter:player:width", content: "#{url["width"]}"], []},
|
||||||
{:meta, [property: "twitter:player:height", content: "#{url["height"]}"], []}
|
{:meta, [name: "twitter:player:height", content: "#{url["height"]}"], []}
|
||||||
]
|
]
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
|
|
|
@ -22,10 +22,10 @@ test "it renders twitter card for user info" do
|
||||||
res = TwitterCard.build_tags(%{user: user})
|
res = TwitterCard.build_tags(%{user: user})
|
||||||
|
|
||||||
assert res == [
|
assert res == [
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||||
{:meta, [property: "twitter:description", content: "born 19 March 1994"], []},
|
{:meta, [name: "twitter:description", content: "born 19 March 1994"], []},
|
||||||
{:meta, [property: "twitter:image", content: avatar_url], []},
|
{:meta, [name: "twitter:image", content: avatar_url], []},
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,11 +47,11 @@ test "it uses summary twittercard if post has no attachment" do
|
||||||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||||
{:meta, [property: "twitter:description", content: "pleroma in a nutshell"], []},
|
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
|
||||||
{:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
{:meta, [name: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
||||||
[]},
|
[]},
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
] == result
|
] == result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -73,15 +73,15 @@ test "it uses summary as description if post has one" do
|
||||||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||||
{:meta,
|
{:meta,
|
||||||
[
|
[
|
||||||
property: "twitter:description",
|
name: "twitter:description",
|
||||||
content: "Public service announcement on caffeine consumption"
|
content: "Public service announcement on caffeine consumption"
|
||||||
], []},
|
], []},
|
||||||
{:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
{:meta, [name: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
||||||
[]},
|
[]},
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
] == result
|
] == result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,11 +123,11 @@ test "it renders avatar not attachment if post is nsfw and unfurl_nsfw is disabl
|
||||||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||||
{:meta, [property: "twitter:description", content: "pleroma in a nutshell"], []},
|
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
|
||||||
{:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
{:meta, [name: "twitter:image", content: "http://localhost:4001/images/avi.png"],
|
||||||
[]},
|
[]},
|
||||||
{:meta, [property: "twitter:card", content: "summary"], []}
|
{:meta, [name: "twitter:card", content: "summary"], []}
|
||||||
] == result
|
] == result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -179,26 +179,26 @@ test "it renders supported types of attachments and skips unknown types" do
|
||||||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id})
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []},
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||||
{:meta, [property: "twitter:description", content: "pleroma in a nutshell"], []},
|
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
|
||||||
{:meta, [property: "twitter:card", content: "summary_large_image"], []},
|
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||||
{:meta, [property: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []},
|
{:meta, [name: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []},
|
||||||
{:meta, [property: "twitter:player:width", content: "1280"], []},
|
{:meta, [name: "twitter:player:width", content: "1280"], []},
|
||||||
{:meta, [property: "twitter:player:height", content: "1024"], []},
|
{:meta, [name: "twitter:player:height", content: "1024"], []},
|
||||||
{:meta, [property: "twitter:card", content: "player"], []},
|
{:meta, [name: "twitter:card", content: "player"], []},
|
||||||
{:meta,
|
{:meta,
|
||||||
[
|
[
|
||||||
property: "twitter:player",
|
name: "twitter:player",
|
||||||
content: Router.Helpers.o_status_url(Endpoint, :notice_player, activity.id)
|
content: Router.Helpers.o_status_url(Endpoint, :notice_player, activity.id)
|
||||||
], []},
|
], []},
|
||||||
{:meta, [property: "twitter:player:width", content: "800"], []},
|
{:meta, [name: "twitter:player:width", content: "800"], []},
|
||||||
{:meta, [property: "twitter:player:height", content: "600"], []},
|
{:meta, [name: "twitter:player:height", content: "600"], []},
|
||||||
{:meta,
|
{:meta,
|
||||||
[
|
[
|
||||||
property: "twitter:player:stream",
|
name: "twitter:player:stream",
|
||||||
content: "https://pleroma.gov/about/juche.webm"
|
content: "https://pleroma.gov/about/juche.webm"
|
||||||
], []},
|
], []},
|
||||||
{:meta, [property: "twitter:player:stream:content_type", content: "video/webm"], []}
|
{:meta, [name: "twitter:player:stream:content_type", content: "video/webm"], []}
|
||||||
] == result
|
] == result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue