Skip to content

Commit

Permalink
generate <meta> og:image in individual thread pages (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
delan committed Oct 26, 2024
1 parent f3847e5 commit 0c408c5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 21 deletions.
34 changes: 21 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub struct ExtractedPost {
pub dom: RcDom,
pub meta: PostMeta,
pub needs_attachments: BTreeSet<SitePath>,
pub og_image: Option<String>,
}

#[derive(Clone, Debug)]
Expand All @@ -74,6 +75,7 @@ pub struct Thread {
pub posts: Vec<TemplatedPost>,
pub meta: PostMeta,
pub needs_attachments: BTreeSet<SitePath>,
pub og_image: Option<String>,
}

#[derive(Clone, Debug)]
Expand All @@ -83,6 +85,7 @@ pub struct TemplatedPost {
pub original_html: String,
pub safe_html: String,
pub needs_attachments: BTreeSet<SitePath>,
pub og_image: Option<String>,
}

impl Thread {
Expand Down Expand Up @@ -199,21 +202,24 @@ impl TryFrom<TemplatedPost> for Thread {
// TODO: skip threads with private or logged-in-only authors?
// TODO: gate sensitive posts behind an interaction?

// for the thread title, take the last post that is not a transparent share (which MAY have
// tags, but SHOULD NOT have a title and MUST NOT have a body), and use its title if any.
meta.title = posts
// for thread metadata, take the last post that is not a transparent share (which MAY have
// tags, but SHOULD NOT have a title and MUST NOT have a body), and use its metadata if any.
let last_non_transparent_share_post = posts
.iter()
.rev()
.find(|post| !post.meta.is_transparent_share)
.map(|post| {
if let Some(title) = post.meta.title.clone().filter(|t| !t.is_empty()) {
title
} else if let Some(author) = post.meta.author.as_ref() {
format!("untitled post by {}", author.display_handle)
} else {
"untitled post".to_owned()
}
});
.find(|post| !post.meta.is_transparent_share);
meta.title = last_non_transparent_share_post.map(|post| {
if let Some(title) = post.meta.title.clone().filter(|t| !t.is_empty()) {
title
} else if let Some(author) = post.meta.author.as_ref() {
format!("untitled post by {}", author.display_handle)
} else {
"untitled post".to_owned()
}
});
let og_image = last_non_transparent_share_post
.and_then(|post| post.og_image.as_deref())
.map(|og_image| SETTINGS.base_url_relativise(og_image));

let needs_attachments = posts
.iter()
Expand All @@ -226,6 +232,7 @@ impl TryFrom<TemplatedPost> for Thread {
posts,
meta,
needs_attachments,
og_image,
})
}
}
Expand Down Expand Up @@ -272,6 +279,7 @@ impl TemplatedPost {
original_html: unsafe_html.to_owned(),
safe_html,
needs_attachments: post.needs_attachments,
og_image: post.og_image,
})
}
}
Expand Down
26 changes: 18 additions & 8 deletions src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub fn extract_metadata(unsafe_html: &str) -> eyre::Result<ExtractedPost> {

let mut meta = PostMeta::default();
let mut needs_attachments = BTreeSet::default();
let mut og_image = None;
let mut author_href = None;
let mut author_name = None;
let mut author_display_name = None;
Expand Down Expand Up @@ -74,17 +75,25 @@ pub fn extract_metadata(unsafe_html: &str) -> eyre::Result<ExtractedPost> {
_ => {}
}
continue;
} else if let Some(attr_names) = html_attributes_with_urls().get(name) {
for attr in attrs.iter() {
if attr_names.contains(&attr.name) {
if let Ok(url) =
SitePath::from_rendered_attachment_url(attr.value.to_str())
{
trace!("found attachment url in rendered post: {url:?}");
needs_attachments.insert(url);
} else {
if let Some(attr_names) = html_attributes_with_urls().get(name) {
for attr in attrs.iter() {
if attr_names.contains(&attr.name) {
if let Ok(url) =
SitePath::from_rendered_attachment_url(attr.value.to_str())
{
trace!("found attachment url in rendered post: {url:?}");
needs_attachments.insert(url);
}
}
}
}
// use the first <img src>, if any, as the <meta> og:image.
if og_image.is_none() && name == &QualName::html("img") {
if let Some(src) = attrs.attr_str("src")?.map(|t| t.to_owned()) {
og_image = Some(src);
}
}
}
}
_ => {}
Expand All @@ -111,6 +120,7 @@ pub fn extract_metadata(unsafe_html: &str) -> eyre::Result<ExtractedPost> {
dom,
meta,
needs_attachments,
og_image,
})
}

Expand Down
1 change: 1 addition & 0 deletions templates/thread-or-post-meta.html
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
<meta property="og:title" content="{% if let Some(title) = thread.meta.title %}{{ title }}{% endif %}">
{%~ if let Some(og_image) = thread.og_image ~%}<meta property="og:image" content="{{ og_image }}">{%~ endif ~%}

0 comments on commit 0c408c5

Please sign in to comment.