Skip to main content

use_friend_markdown/
lib.rs

1#![doc = include_str!("../README.md")]
2
3//! Simple deterministic markdown rendering for Fellow Friends records.
4
5use use_friend::Friend;
6
7/// Markdown rendering helpers for Fellow Friends records.
8pub struct FriendMarkdown;
9
10impl FriendMarkdown {
11    /// Renders one friend as a compact markdown card.
12    #[must_use]
13    pub fn card(friend: &Friend) -> String {
14        let mut markdown = format!(
15            "### {}\n\n- Ecosystem: {}\n- Technology kind: {}\n- Identity kind: {}\n- Figure: {}",
16            friend.name,
17            friend.ecosystem,
18            friend.technology_kind,
19            friend.identity_kind,
20            friend.figure_kind
21        );
22
23        if let Some(form) = friend.form {
24            markdown.push_str(&format!("\n- Form: {form}"));
25        }
26
27        markdown.push('\n');
28        markdown
29    }
30
31    /// Renders friends as a simple markdown table.
32    #[must_use]
33    pub fn table(friends: &[Friend]) -> String {
34        let mut markdown = String::from(
35            "| Name | Ecosystem | Technology kind | Identity kind | Figure | Form |\n| --- | --- | --- | --- | --- | --- |\n",
36        );
37
38        for friend in friends {
39            markdown.push_str(&format!(
40                "| {} | {} | {} | {} | {} | {} |\n",
41                friend.name,
42                friend.ecosystem,
43                friend.technology_kind,
44                friend.identity_kind,
45                friend.figure_kind,
46                friend.form.unwrap_or("unknown")
47            ));
48        }
49
50        markdown
51    }
52
53    /// Renders friends as a simple markdown list.
54    #[must_use]
55    pub fn list(friends: &[Friend]) -> String {
56        let mut markdown = String::new();
57
58        for friend in friends {
59            markdown.push_str(&format!("- {} ({})\n", friend.name, friend.ecosystem));
60        }
61
62        markdown
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::FriendMarkdown;
69    use use_friend_fixture::FriendFixtures;
70
71    #[test]
72    fn renders_card_with_expected_lines() {
73        let card = FriendMarkdown::card(&FriendFixtures::tiny()[0]);
74
75        assert_eq!(
76            card,
77            "### Ferris\n\n- Ecosystem: Rust\n- Technology kind: Programming language\n- Identity kind: Unofficial mascot\n- Figure: Animal\n- Form: crab\n"
78        );
79    }
80
81    #[test]
82    fn renders_card_for_new_friend() {
83        let duke = FriendFixtures::all()
84            .iter()
85            .find(|friend| friend.id == "java-duke")
86            .expect("Duke should be in the fixture set");
87        let card = FriendMarkdown::card(duke);
88
89        assert_eq!(
90            card,
91            "### Duke\n\n- Ecosystem: Java\n- Technology kind: Programming language\n- Identity kind: Mascot\n- Figure: Creature\n- Form: creature\n"
92        );
93    }
94
95    #[test]
96    fn renders_deterministic_table() {
97        let table = FriendMarkdown::table(FriendFixtures::tiny());
98
99        assert!(table
100            .starts_with("| Name | Ecosystem | Technology kind | Identity kind | Figure | Form |"));
101        assert!(table.contains(
102            "| Ferris | Rust | Programming language | Unofficial mascot | Animal | crab |"
103        ));
104        assert!(table.contains("| Tux | Linux | Operating system | Mascot | Animal | penguin |"));
105    }
106
107    #[test]
108    fn renders_deterministic_list() {
109        assert_eq!(
110            FriendMarkdown::list(FriendFixtures::tiny()),
111            "- Ferris (Rust)\n- Go Gopher (Go)\n- Tux (Linux)\n"
112        );
113    }
114}