Link hashtags in posts to corresponding tag timeline pages
This commit is contained in:
parent
da918d2296
commit
816cae6b78
5 changed files with 27 additions and 13 deletions
|
@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::{json, Value};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::frontend::get_tag_page_url;
|
||||
use crate::models::posts::types::Post;
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use crate::models::users::types::User;
|
||||
|
@ -186,10 +187,11 @@ pub fn create_note(
|
|||
tags.push(tag);
|
||||
};
|
||||
for tag_name in &post.tags {
|
||||
let tag_page_url = get_tag_page_url(instance_url, tag_name);
|
||||
let tag = Tag {
|
||||
name: format!("#{}", tag_name),
|
||||
tag_type: HASHTAG.to_string(),
|
||||
href: None,
|
||||
href: Some(tag_page_url),
|
||||
};
|
||||
tags.push(tag);
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ async fn actor_view(
|
|||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
let user = get_user_by_name(db_client, &username).await?;
|
||||
if !is_activitypub_request(&request) {
|
||||
let page_url = get_profile_page_url(&user.id, &config.instance_url());
|
||||
let page_url = get_profile_page_url(&config.instance_url(), &user.id);
|
||||
let response = HttpResponse::Found()
|
||||
.header("Location", page_url)
|
||||
.finish();
|
||||
|
@ -203,7 +203,7 @@ pub async fn object_view(
|
|||
.find(|post| post.id == internal_object_id && post.author.is_local())
|
||||
.ok_or(HttpError::NotFoundError("post"))?;
|
||||
if !is_activitypub_request(&request) {
|
||||
let page_url = get_post_page_url(&post.id, &config.instance_url());
|
||||
let page_url = get_post_page_url(&config.instance_url(), &post.id);
|
||||
let response = HttpResponse::Found()
|
||||
.header("Location", page_url)
|
||||
.finish();
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
use uuid::Uuid;
|
||||
|
||||
// Assuming frontend is on the same host as backend
|
||||
pub fn get_profile_page_url(profile_id: &Uuid, instance_url: &str) -> String {
|
||||
pub fn get_profile_page_url(instance_url: &str, profile_id: &Uuid) -> String {
|
||||
format!("{}/profile/{}", instance_url, profile_id)
|
||||
}
|
||||
|
||||
pub fn get_post_page_url(post_id: &Uuid, instance_url: &str) -> String {
|
||||
pub fn get_post_page_url(instance_url: &str, post_id: &Uuid) -> String {
|
||||
format!("{}/post/{}", instance_url, post_id)
|
||||
}
|
||||
|
||||
pub fn get_tag_page_url(instance_url: &str, tag_name: &str) -> String {
|
||||
format!("{}/tag/{}", instance_url, tag_name)
|
||||
}
|
||||
|
|
|
@ -72,7 +72,11 @@ async fn create_status(
|
|||
post_data.mentions = mention_map.values()
|
||||
.map(|profile| profile.id).collect();
|
||||
post_data.tags = find_tags(&post_data.content);
|
||||
post_data.content = replace_tags(&post_data.content, &post_data.tags);
|
||||
post_data.content = replace_tags(
|
||||
&instance.url(),
|
||||
&post_data.content,
|
||||
&post_data.tags,
|
||||
);
|
||||
let post = create_post(db_client, ¤t_user.id, post_data).await?;
|
||||
// Federate
|
||||
let maybe_in_reply_to = match post.in_reply_to_id {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use regex::{Captures, Regex};
|
||||
|
||||
use crate::errors::ConversionError;
|
||||
use crate::frontend::get_tag_page_url;
|
||||
|
||||
const HASHTAG_RE: &str = r"(?m)(?P<before>^|\s)#(?P<tag>\S+)";
|
||||
const HASHTAG_SECONDARY_RE: &str = r"^(?P<tag>[0-9A-Za-z]+)(?P<after>(\.|<br>|\.<br>)?)$";
|
||||
|
@ -23,7 +24,7 @@ pub fn find_tags(text: &str) -> Vec<String> {
|
|||
}
|
||||
|
||||
/// Replaces hashtags with links
|
||||
pub fn replace_tags(text: &str, tags: &[String]) -> String {
|
||||
pub fn replace_tags(instance_url: &str, text: &str, tags: &[String]) -> String {
|
||||
let hashtag_re = Regex::new(HASHTAG_RE).unwrap();
|
||||
let hashtag_secondary_re = Regex::new(HASHTAG_SECONDARY_RE).unwrap();
|
||||
let result = hashtag_re.replace_all(text, |caps: &Captures| {
|
||||
|
@ -33,10 +34,11 @@ pub fn replace_tags(text: &str, tags: &[String]) -> String {
|
|||
let tag_name = tag.to_lowercase();
|
||||
let after = secondary_caps["after"].to_string();
|
||||
if tags.contains(&tag_name) {
|
||||
let tag_page_url = get_tag_page_url(instance_url, &tag_name);
|
||||
format!(
|
||||
r#"{}<a class="hashtag" href="/tag/{}">#{}</a>{}"#,
|
||||
r#"{}<a class="hashtag" href="{}">#{}</a>{}"#,
|
||||
before,
|
||||
tag_name,
|
||||
tag_page_url,
|
||||
tag,
|
||||
after,
|
||||
)
|
||||
|
@ -63,6 +65,8 @@ pub fn normalize_tag(tag: &str) -> Result<String, ConversionError> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const INSTANCE_URL: &str = "https://example.com";
|
||||
|
||||
#[test]
|
||||
fn test_find_tags() {
|
||||
let text = concat!(
|
||||
|
@ -87,13 +91,13 @@ mod tests {
|
|||
"more text #tag2",
|
||||
);
|
||||
let tags = find_tags(text);
|
||||
let output = replace_tags(&text, &tags);
|
||||
let output = replace_tags(INSTANCE_URL, &text, &tags);
|
||||
|
||||
let expected_output = concat!(
|
||||
r#"@user1@server1 some text <a class="hashtag" href="/tag/testtag">#TestTag</a>."#, "\n",
|
||||
r#"<a class="hashtag" href="/tag/tag1">#TAG1</a> <a class="hashtag" href="/tag/tag1">#tag1</a> "#,
|
||||
r#"@user1@server1 some text <a class="hashtag" href="https://example.com/tag/testtag">#TestTag</a>."#, "\n",
|
||||
r#"<a class="hashtag" href="https://example.com/tag/tag1">#TAG1</a> <a class="hashtag" href="https://example.com/tag/tag1">#tag1</a> "#,
|
||||
r#"#test_underscore #test*special "#,
|
||||
r#"more text <a class="hashtag" href="/tag/tag2">#tag2</a>"#,
|
||||
r#"more text <a class="hashtag" href="https://example.com/tag/tag2">#tag2</a>"#,
|
||||
);
|
||||
assert_eq!(output, expected_output);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue