Skip to main content

setu_cli/
checker.rs

1use core::fmt;
2use std::path::PathBuf;
3
4use colored::Colorize;
5
6use crate::checker;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum LocalLinkStatus {
10    Valid,
11    DoesNotExist,
12    InvalidPrefix,
13}
14
15impl fmt::Display for LocalLinkStatus {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            LocalLinkStatus::Valid => write!(f, "The local link is valid"),
19            LocalLinkStatus::DoesNotExist => write!(f, "The local link does not exist"),
20            LocalLinkStatus::InvalidPrefix => {
21                write!(f, "The local link's path is malformatted")
22            }
23        }
24    }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum RemoteLinkStatus {
29    Reachable,       // Could this be changed?
30    Concern(u16),    // Status code - 404, 501 etc.
31    Invalid(String), // Err message - not to be confused with 404 which is a Concern
32}
33
34impl fmt::Display for RemoteLinkStatus {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            Self::Concern(code) => {
38                write!(f, "The URL returned an unsuccessful status code: {}", code)
39            }
40            Self::Invalid(err) => {
41                write!(f, "The URL could not be reached: {}", err)
42            }
43            Self::Reachable => write!(f, "The URL returns 200 OK"),
44        }
45    }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub enum LinkStatus {
50    Local(LocalLinkStatus),
51    Remote(RemoteLinkStatus),
52}
53
54impl LinkStatus {
55    pub fn is_broken(&self) -> bool {
56        match self {
57            LinkStatus::Local(local_link_status) => match local_link_status {
58                LocalLinkStatus::Valid => false,
59                _ => true,
60            },
61            LinkStatus::Remote(remote_link_status) => match remote_link_status {
62                RemoteLinkStatus::Reachable | RemoteLinkStatus::Concern(_) => false, // Concerns are not broken as such
63                _ => true,
64            },
65        }
66    }
67}
68
69impl fmt::Display for LinkStatus {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        match self {
72            LinkStatus::Local(status) => fmt::Display::fmt(status, f),
73            LinkStatus::Remote(status) => fmt::Display::fmt(status, f),
74        }
75    }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct LinkCheckResult {
80    pub source_file: PathBuf,
81    pub raw_link: String,
82    pub status: LinkStatus,
83}
84
85#[derive(Debug)]
86pub struct MarkdownCheckResult {
87    pub success: bool,
88    pub checks: Vec<LinkCheckResult>,
89}
90
91impl fmt::Display for MarkdownCheckResult {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        if self.success {
94            for check in &self.checks {
95                match &check.status {
96                    checker::LinkStatus::Local(status) if *status != LocalLinkStatus::Valid => {
97                        write!(
98                            f,
99                            "{} Faulty local link {} at {} | {}\n",
100                            "FAIL".red().bold(),
101                            check.raw_link.cyan(),
102                            check.source_file.to_string_lossy().green(),
103                            check.status
104                        )?;
105                    }
106                    checker::LinkStatus::Remote(RemoteLinkStatus::Concern(_))
107                    | checker::LinkStatus::Remote(RemoteLinkStatus::Invalid(_)) => {
108                        write!(
109                            f,
110                            "{} Faulty remote URL {} at {} | {}\n",
111                            "FAIL".red().bold(),
112                            check.raw_link.cyan(),
113                            check.source_file.to_string_lossy().green(),
114                            check.status
115                        )?;
116                    }
117                    _ => {}
118                }
119            }
120        } else {
121            write!(
122                f,
123                "{} Failed to locate/parse markdown file",
124                "FAIL".red().bold()
125            )?;
126        }
127        Ok(())
128    }
129}
130
131pub mod local;
132pub mod remote;