about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2022-05-23 18:19:39 +0300
committerVika <vika@fireburn.ru>2022-05-23 18:22:07 +0300
commit20867384e36fba1d33113dbdbb0bdd94aabf6760 (patch)
treede8b0ed59e86b5aa1adcf87d9ed6df91c03a7792
parent067d6c4c08120bb9b93190911bd00adf9159bba1 (diff)
downloadkittybox-20867384e36fba1d33113dbdbb0bdd94aabf6760.tar.zst
templates: render like and bookmark posts correctly
They really use the same framework, so for now a unit test for like
posts is sufficient. Of course, for proper coverage, one can introduce
tests for bookmarks too, especially if one chooses to render them
differently. The logic will be pretty much the same though.

Replies might use the same logic, since those are also
Webmention-oriented posts.

(It looks like another way to classify MF2 documents is slowly forming
in my brain. Maybe I should write about it on my blog.)
-rw-r--r--templates/src/lib.rs61
-rw-r--r--templates/src/templates.rs49
2 files changed, 109 insertions, 1 deletions
diff --git a/templates/src/lib.rs b/templates/src/lib.rs
index 45d1894..39f1075 100644
--- a/templates/src/lib.rs
+++ b/templates/src/lib.rs
@@ -7,6 +7,7 @@ pub use login::LoginPage;
 
 #[cfg(test)]
 mod tests {
+    use faker_rand::lorem::Word;
     use serde_json::json;
     use microformats::types::{Document, Item, PropertyValue, Url};
     use std::cell::RefCell;
@@ -37,7 +38,7 @@ mod tests {
     }
     
     fn gen_random_post(domain: &str, kind: PostType) -> serde_json::Value {
-        use faker_rand::lorem::{Paragraph, Word, Sentence};
+        use faker_rand::lorem::{Paragraph, Sentence};
 
         fn html(content: Paragraph) -> serde_json::Value {
             json!({
@@ -285,4 +286,62 @@ mod tests {
             unreachable!()
         }
     }
+
+    #[test]
+    fn test_like_of() {
+        test_logger::ensure_env_logger_initialized();
+
+        for likeof in [
+            PostType::LikeOf(gen_random_post(
+                &rand::random::<Domain>().to_string(),
+                PostType::Note
+            )),
+            PostType::LikeOfLink(format!(
+                "https://{}/posts/{}-{}-{}",
+                &rand::random::<Domain>(),
+                &rand::random::<Word>(),
+                &rand::random::<Word>(),
+                &rand::random::<Word>(),
+            ))
+        ] {
+            let mf2 = gen_random_post(
+                &rand::random::<Domain>().to_string(),
+                likeof
+            );
+            let url: Url = mf2.pointer("/properties/uid/0")
+                .and_then(|i| i.as_str())
+                .and_then(|u| u.parse().ok())
+                .unwrap();
+            let html = crate::templates::Entry {
+                post: &mf2
+            }.to_string();
+            let parsed: Document = microformats::from_html(&html, url.clone()).unwrap();
+
+            if let Some(item) = parsed.items.get(0) {
+                let _item = item.borrow();
+                let props = _item.properties.borrow();
+
+                check_dt_published(&mf2, item);
+                assert!(props.contains_key("like-of"));
+                match props.get("like-of").and_then(|v| v.first()) {
+                    Some(PropertyValue::Url(url)) => {
+                        assert_eq!(
+                            url,
+                            &mf2.pointer("/properties/like-of/0")
+                                .and_then(|i| i.as_str())
+                                .or_else(|| mf2.pointer("/properties/like-of/0/properties/uid/0").and_then(|i| i.as_str()))
+                                .and_then(|u| u.parse::<Url>().ok())
+                                .unwrap()
+                        );
+                    }
+                    Some(PropertyValue::Item(_cite)) => {
+                        todo!()
+                    }
+                    other => panic!("Unexpected value in like-of: {:?}", other)
+                }
+            } else {
+                unreachable!()
+            }
+        }
+    }
 }
diff --git a/templates/src/templates.rs b/templates/src/templates.rs
index f2040fc..66edc9a 100644
--- a/templates/src/templates.rs
+++ b/templates/src/templates.rs
@@ -77,6 +77,55 @@ markup::define! {
         }
     }
     Entry<'a>(post: &'a serde_json::Value) {
+        @if post.pointer("/properties/like-of").is_none() && post.pointer("/properties/bookmark-of").is_none() {
+            @FullEntry { post }
+        } else {
+            // Show a mini-post.
+            @MiniEntry { post }
+        }
+    }
+    MiniEntry<'a>(post: &'a serde_json::Value) {
+        article."h-entry mini-entry" {
+            @if let Some(author) = post["properties"]["author"][0].as_object() {
+                span."mini-h-card"."u-author" {
+                    a."u-author"[href=author["properties"]["uid"][0].as_str().unwrap()] {
+                        @if let Some(photo) = author["properties"]["photo"][0].as_str() {
+                            img[src=photo, loading="lazy"];
+                        }
+                        @author["properties"]["name"][0].as_str().unwrap()
+                    }
+                }
+                @if let Some(likeof) = post["properties"]["like-of"][0].as_str() {
+                    " ❤️ "
+                    a."u-like-of"[href=likeof] { @likeof }
+                } else if let Some(likeof) = post["properties"]["like-of"][0].as_object() {
+                    a."u-like-of"[href=likeof["properties"]["url"][0].as_str().unwrap()] {
+                        @likeof["properties"]["name"][0]
+                            .as_str()
+                            .unwrap_or_else(|| likeof["properties"]["url"][0].as_str().unwrap())
+                    }
+                }
+                @if let Some(bookmarkof) = post["properties"]["bookmark-of"][0].as_str() {
+                    " 🔖 "
+                    a."u-bookmark-of"[href=bookmarkof] { @bookmarkof }
+                } else if let Some(bookmarkof) = post["properties"]["bookmark-of"][0].as_object() {
+                    a."u-bookmark-of"[href=bookmarkof["properties"]["url"][0].as_str().unwrap()] {
+                        @bookmarkof["properties"]["name"][0]
+                            .as_str()
+                            .unwrap_or_else(|| bookmarkof["properties"]["url"][0].as_str().unwrap())
+                    }
+                }
+                @if let Some(published) = post["properties"]["published"][0].as_str() {
+                    time."dt-published"[datetime=published] {
+                        @chrono::DateTime::parse_from_rfc3339(published)
+                            .map(|dt| dt.format("on %a %b %e %T %Y").to_string())
+                            .unwrap_or("sometime in the past".to_string())
+                    }
+                }
+            }
+        }
+    }
+    FullEntry<'a>(post: &'a serde_json::Value) {
         article."h-entry" {
             header.metadata {
                 @if let Some(name) = post["properties"]["name"][0].as_str() {