use crate::error::{Result, ScraperError};
#[derive(Debug, Clone)]
pub struct Article {
pub title: String,
pub text_content: String,
pub excerpt: Option<String>,
pub byline: Option<String>,
pub published_time: Option<String>,
}
pub fn parse(html: &str, url: Option<&str>) -> Result<Article> {
let article = legible::parse(html, url, None)
.map_err(|e| ScraperError::Extraction(format!("Readability failed: {}", e)))?;
Ok(Article {
title: article.title,
text_content: article.text_content,
excerpt: article.excerpt,
byline: article.byline,
published_time: article.published_time,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_simple_html() {
let html = r#"
<html>
<head><title>Test Article</title></head>
<body>
<article>
<h1>Test Article</h1>
<p>This is the main content of the article.</p>
<p>Another paragraph with more content.</p>
</article>
</body>
</html>
"#;
let article = parse(html, Some("https://example.com")).unwrap();
assert_eq!(article.title, "Test Article");
assert!(article.text_content.contains("main content"));
}
#[test]
fn test_parse_with_byline() {
let html = r#"
<html>
<head><title>Article Title</title></head>
<body>
<article>
<h1>Article Title</h1>
<address>By John Doe</address>
<p>Article content here. This is a longer paragraph with more text to make legible recognize this as the main content of the article.</p>
<p>Another paragraph with even more content to ensure the article is properly detected.</p>
</article>
</body>
</html>
"#;
let result = parse(html, Some("https://example.com"));
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_parse_empty_html() {
let html = "<html><body></body></html>";
let result = parse(html, Some("https://example.com"));
assert!(result.is_ok() || result.is_err());
}
}