metadata_gen/
lib.rs

1// src/lib.rs
2
3#![doc = include_str!("../README.md")]
4#![doc(
5    html_favicon_url = "https://kura.pro/metadata-gen/images/favicon.ico",
6    html_logo_url = "https://kura.pro/metadata-gen/images/logos/metadata-gen.svg",
7    html_root_url = "https://docs.rs/metadata-gen"
8)]
9#![crate_name = "metadata_gen"]
10#![crate_type = "lib"]
11
12use std::collections::HashMap;
13
14/// The `error` module contains error types for metadata processing.
15pub mod error;
16/// The `metadata` module contains functions for extracting and processing metadata.
17pub mod metadata;
18/// The `metatags` module contains functions for generating meta tags.
19pub mod metatags;
20/// The `utils` module contains utility functions for metadata processing.
21pub mod utils;
22
23pub use error::MetadataError;
24pub use metadata::{extract_metadata, process_metadata, Metadata};
25pub use metatags::{generate_metatags, MetaTagGroups};
26pub use utils::{async_extract_metadata_from_file, escape_html};
27
28/// Type alias for a map of metadata key-value pairs.
29pub type MetadataMap = HashMap<String, String>;
30/// Type alias for a list of keywords.
31pub type Keywords = Vec<String>;
32/// Type alias for the result of metadata extraction and processing.
33pub type MetadataResult =
34    Result<(MetadataMap, Keywords, MetaTagGroups), MetadataError>;
35
36/// Extracts metadata from the content, generates keywords based on the metadata,
37/// and prepares meta tag groups.
38///
39/// This function performs three key tasks:
40/// 1. It extracts metadata from the front matter of the content.
41/// 2. It generates keywords based on this metadata.
42/// 3. It generates various meta tags required for the page.
43///
44/// # Arguments
45///
46/// * `content` - A string slice representing the content from which to extract metadata.
47///
48/// # Returns
49///
50/// Returns a Result containing a tuple with:
51/// * `HashMap<String, String>`: Extracted metadata
52/// * `Vec<String>`: A list of keywords
53/// * `MetaTagGroups`: A structure containing various meta tags
54///
55/// # Errors
56///
57/// This function will return a `MetadataError` if metadata extraction or processing fails.
58///
59/// # Example
60///
61/// ```
62/// use metadata_gen::extract_and_prepare_metadata;
63///
64/// let content = r#"---
65/// title: My Page
66/// description: A sample page
67/// ---
68/// # Content goes here
69/// "#;
70///
71/// let result = extract_and_prepare_metadata(content);
72/// assert!(result.is_ok());
73/// ```
74pub fn extract_and_prepare_metadata(content: &str) -> MetadataResult {
75    // Ensure the front matter format is correct
76    if !content.contains(":") {
77        return Err(MetadataError::ExtractionError {
78            message: "No valid front matter found".to_string(),
79        });
80    }
81
82    let metadata = extract_metadata(content)?;
83    let metadata_map = metadata.into_inner();
84    let keywords = extract_keywords(&metadata_map);
85    let all_meta_tags = generate_metatags(&metadata_map);
86
87    Ok((metadata_map, keywords, all_meta_tags))
88}
89
90/// Extracts keywords from the metadata.
91///
92/// This function looks for a "keywords" key in the metadata and splits its value into a vector of strings.
93///
94/// # Arguments
95///
96/// * `metadata` - A reference to a HashMap containing the metadata.
97///
98/// # Returns
99///
100/// A vector of strings representing the keywords.
101pub fn extract_keywords(
102    metadata: &HashMap<String, String>,
103) -> Vec<String> {
104    metadata
105        .get("keywords")
106        .map(|k| k.split(',').map(|s| s.trim().to_string()).collect())
107        .unwrap_or_default()
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_extract_and_prepare_metadata() {
116        let content = r#"---
117title: Test Page
118description: A test page for metadata extraction
119keywords: test, metadata, extraction
120---
121# Test Content
122This is a test file for metadata extraction."#;
123
124        let result = extract_and_prepare_metadata(content);
125        assert!(result.is_ok());
126
127        let (metadata, keywords, meta_tags) = result.unwrap();
128        assert_eq!(
129            metadata.get("title"),
130            Some(&"Test Page".to_string())
131        );
132        assert_eq!(
133            metadata.get("description"),
134            Some(&"A test page for metadata extraction".to_string())
135        );
136        assert_eq!(keywords, vec!["test", "metadata", "extraction"]);
137        assert!(!meta_tags.primary.is_empty());
138    }
139
140    #[test]
141    fn test_extract_keywords() {
142        let mut metadata = HashMap::new();
143        metadata.insert(
144            "keywords".to_string(),
145            "rust, programming, metadata".to_string(),
146        );
147
148        let keywords = extract_keywords(&metadata);
149        assert_eq!(keywords, vec!["rust", "programming", "metadata"]);
150    }
151
152    #[test]
153    fn test_extract_keywords_empty() {
154        let metadata = HashMap::new();
155        let keywords = extract_keywords(&metadata);
156        assert!(keywords.is_empty());
157    }
158}