Skip to content

Commit 4562799

Browse files
Merge pull request #11 from reddevilmidzy/#10-recursion
디렉터리 단위로 탐색하여 링크 추출
2 parents 590d535 + 08b223c commit 4562799

File tree

1 file changed

+60
-15
lines changed

1 file changed

+60
-15
lines changed

src/main.rs

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,31 @@ use std::fs;
33
use std::path::Path;
44
use tokio::time;
55

6-
fn extract_links_from_file<P: AsRef<Path>>(path: P) -> Vec<String> {
7-
let content = fs::read_to_string(&path).unwrap();
8-
let url_regex = Regex::new(r"https?://(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)").unwrap();
6+
fn process_path(path: &Path, url_regex: &Regex) -> Vec<String> {
7+
let mut links = Vec::new();
8+
9+
if path.is_file() {
10+
if let Ok(content) = fs::read_to_string(path) {
11+
links.extend(url_regex.find_iter(&content).map(|mat| {
12+
mat.as_str()
13+
.trim_end_matches(&[')', '>', '.', ',', ';'][..])
14+
.to_string()
15+
}));
16+
}
17+
} else if path.is_dir() {
18+
if let Ok(entries) = fs::read_dir(path) {
19+
for entry in entries.flatten() {
20+
links.extend(process_path(&entry.path(), url_regex));
21+
}
22+
}
23+
}
924

10-
url_regex
11-
.find_iter(&content)
12-
.map(|mat| {
13-
let url = mat.as_str();
14-
url.trim_end_matches(&[')', '>', '.', ',', ';'][..])
15-
.to_string()
16-
})
17-
.collect()
25+
links
26+
}
27+
28+
fn extract_links_from_path<P: AsRef<Path>>(path: P) -> Vec<String> {
29+
let url_regex = Regex::new(r"https?://(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)").unwrap();
30+
process_path(path.as_ref(), &url_regex)
1831
}
1932

2033
#[derive(Debug, Eq, PartialEq)]
@@ -55,7 +68,7 @@ async fn check_link(url: &str) -> LinkCheckResult {
5568
#[tokio::main]
5669
async fn main() {
5770
let file_path = "example.md";
58-
let links = extract_links_from_file(file_path);
71+
let links = extract_links_from_path(file_path);
5972

6073
let mut handles = Vec::new();
6174
for link in links {
@@ -78,11 +91,11 @@ async fn main() {
7891
#[cfg(test)]
7992
mod tests {
8093
use super::*;
81-
use std::fs::File;
94+
use std::fs::{self, File};
8295
use std::io::Write;
8396

8497
#[test]
85-
fn extracts_links_from_file() -> Result<(), std::io::Error> {
98+
fn test_extracts_links_from_file() -> Result<(), std::io::Error> {
8699
// 테스트용 파일 생성
87100
let test_file_path = "test_file.txt";
88101
let mut file = File::create(test_file_path)?;
@@ -93,7 +106,7 @@ mod tests {
93106
)?;
94107

95108
// 함수 호출 및 결과 확인
96-
let links = extract_links_from_file(test_file_path);
109+
let links = extract_links_from_path(test_file_path);
97110
assert_eq!(
98111
links,
99112
vec![
@@ -117,4 +130,36 @@ mod tests {
117130
let link = "https://lazypazy.tistory.com";
118131
assert_eq!(check_link(link).await, LinkCheckResult::Valid);
119132
}
133+
134+
#[test]
135+
fn test_process_path() -> Result<(), std::io::Error> {
136+
let test_dir = "test_dir";
137+
if Path::new(test_dir).exists() {
138+
fs::remove_dir_all(test_dir)?;
139+
}
140+
141+
fs::create_dir_all(test_dir)?;
142+
143+
let subdir = format!("{}/subdir", test_dir);
144+
fs::create_dir(&subdir)?;
145+
146+
let mut file1 = File::create(format!("{}/file1.txt", test_dir))?;
147+
writeln!(file1, "Visit https://example1.com for more info.")?;
148+
149+
let mut file2 = File::create(format!("{}/file2.txt", subdir))?;
150+
writeln!(file2, "Check https://example2.com and https://example3.com")?;
151+
152+
let url_regex = Regex::new(r"https?://(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)").unwrap();
153+
154+
let links = process_path(Path::new(test_dir), &url_regex);
155+
156+
fs::remove_dir_all(test_dir)?;
157+
158+
assert_eq!(links.len(), 3);
159+
assert!(links.contains(&"https://example1.com".to_string()));
160+
assert!(links.contains(&"https://example2.com".to_string()));
161+
assert!(links.contains(&"https://example3.com".to_string()));
162+
163+
Ok(())
164+
}
120165
}

0 commit comments

Comments
 (0)