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 => false,
63                RemoteLinkStatus::Concern(_) => true, // concerns are specified by user input so must be deemed broken if they are found
64                _ => true,
65            },
66        }
67    }
68}
69
70impl fmt::Display for LinkStatus {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            LinkStatus::Local(status) => fmt::Display::fmt(status, f),
74            LinkStatus::Remote(status) => fmt::Display::fmt(status, f),
75        }
76    }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct LinkCheckResult {
81    pub source_file: PathBuf,
82    pub raw_link: String,
83    pub status: LinkStatus,
84}
85
86#[derive(Debug)]
87pub struct MarkdownCheckResult {
88    pub success: bool,
89    pub checks: Vec<LinkCheckResult>,
90}
91
92impl fmt::Display for MarkdownCheckResult {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        if self.success {
95            for check in &self.checks {
96                match &check.status {
97                    checker::LinkStatus::Local(status) if *status != LocalLinkStatus::Valid => {
98                        write!(
99                            f,
100                            "{} Faulty local link {} at {} | {}\n",
101                            "FAIL".red().bold(),
102                            check.raw_link.cyan(),
103                            check.source_file.to_string_lossy().green(),
104                            check.status
105                        )?;
106                    }
107                    checker::LinkStatus::Remote(RemoteLinkStatus::Concern(_))
108                    | checker::LinkStatus::Remote(RemoteLinkStatus::Invalid(_)) => {
109                        write!(
110                            f,
111                            "{} Faulty remote URL {} at {} | {}\n",
112                            "FAIL".red().bold(),
113                            check.raw_link.cyan(),
114                            check.source_file.to_string_lossy().green(),
115                            check.status
116                        )?;
117                    }
118                    _ => {}
119                }
120            }
121        } else {
122            write!(
123                f,
124                "{} Failed to locate/parse markdown file",
125                "FAIL".red().bold()
126            )?;
127        }
128        Ok(())
129    }
130}
131
132pub mod local;
133pub mod remote;