summaryrefslogtreecommitdiffstats
path: root/front_end/src/urler.rs
blob: d3ab409d221a4977696e04db19d2ac264b4d73e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use categories::Category;
use kitchen_sink::CrateAuthor;
use kitchen_sink::UserType;
use rich_crate::Origin;
use rich_crate::RichCrateVersion;
use rich_crate::RichDep;
use urlencoding::encode;

/// One thing responsible for link URL scheme on the site.
/// Should be used for every internal `<a href>`.
pub struct Urler {
    own_crate_name: Option<String>,
}

impl Urler {
    pub fn new(own_crate_name: Option<String>) -> Self {
        Self { own_crate_name }
    }

    /// Link to a dependency of a crate
    pub fn dependency(&self, dep: &RichDep) -> String {
        if let Some(git) = dep.dep.git() {
            git.to_string()
        } else {
            format!("/crates/{}", encode(&dep.package))
        }
    }

    /// Summary of all dependencies
    pub fn deps(&self, krate: &RichCrateVersion) -> String {
        format!("https://deps.rs/crate/{}/{}", encode(krate.short_name()), encode(krate.version()))
    }

    pub fn reverse_deps(&self, krate: &RichCrateVersion) -> String {
        format!("https://crates.io/crates/{}/reverse_dependencies", encode(krate.short_name()))
    }

    pub fn crates_io_crate(&self, krate: &RichCrateVersion) -> Option<String> {
        Some(self.crates_io_crate_by_name(krate.short_name()))
    }

    fn crates_io_crate_by_name(&self, crate_name: &str) -> String {
        format!("https://crates.io/crates/{}", encode(crate_name))
    }

    /// Link to crate individual page
    pub fn krate(&self, krate: &RichCrateVersion) -> String {
        self.crate_by_name(krate.short_name())
    }

    pub fn crate_by_origin(&self, o: &Origin) -> String {
        format!("/crates/{}", encode(o.short_crate_name()))
    }

    pub fn crate_by_name(&self, crate_name: &str) -> String {
        if self.own_crate_name.as_ref().map_or(false, |n| n == crate_name) {
            self.crates_io_crate_by_name(crate_name)
        } else {
            format!("/crates/{}", encode(crate_name))
        }
    }

    pub fn keyword(&self, name: &str) -> String {
        format!("/keywords/{}", encode(&name.to_lowercase()))
    }

    /// First page of category listing
    pub fn category(&self, cat: &Category) -> String {
        let mut out = String::with_capacity(1 + cat.slug.len());
        for s in cat.slug.split("::") {
            out.push('/');
            out.push_str(s);
        }
        out
    }

    /// n-th page (1-indexed) of category listing
    pub fn category_page(&self, cat: &Category, p: usize) -> String {
        if p < 2 {
            return self.category(cat);
        }
        format!("https://crates.io/categories/{}?page={}", cat.slug, p)
    }

    /// Crate author's URL
    ///
    /// This will probably change to a listing page rather than arbitrary personal URL
    pub fn author(&self, author: &CrateAuthor<'_>) -> Option<String> {
        if let Some(ref gh) = author.github {
            Some(match gh.user_type {
                UserType::User => format!("https://crates.io/users/{}", encode(&gh.login)),
                UserType::Org | UserType::Bot => format!("https://github.com/{}", encode(&gh.login)),
            })
        } else if let Some(ref info) = author.info {
            if let Some(ref em) = info.email {
                Some(format!("mailto:{}", em)) // add name? encode?
            } else if let Some(ref url) = info.url {
                assert!(url.starts_with("http:") || url.starts_with("https:") || url.starts_with("mailto:"));
                Some(url.to_owned())
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn search_crates_io(&self, query: &str) -> String {
        format!("https://crates.io/search?q={}", encode(query))
    }

    pub fn search_crates_rs(&self, query: &str) -> String {
        format!("https://lib.rs/search?q={}", encode(query))
    }

    pub fn search_ddg(&self, query: &str) -> String {
        format!("https://duckduckgo.com/?q=site%3Alib.rs+{}", encode(query))
    }
}