// Copyright ยฉ 2024 StaticDataGen. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT //! # StaticDataGen Tags Examples //! //! This program demonstrates the usage of tag generation and handling //! in the StaticDataGen library, showing various ways to create and //! manage content tags, tag pages, and tag-based navigation. use staticdatagen::models::data::{FileData, PageData, TagsData}; use staticdatagen::modules::tags::{ create_tags_data, generate_tags, generate_tags_html, }; use std::collections::HashMap; /// Entry point for the StaticDataGen Tags Examples program. /// /// Demonstrates various tag generation scenarios and shows different /// ways to organize and display content tags. /// /// # Errors /// /// Returns a `Result` containing a `Box` if any error /// occurs during the execution of the examples. pub fn main() -> Result<(), Box> { println!("\n๐Ÿงช StaticDataGen Tags Examples\n"); basic_tags_example()?; multiple_tags_example()?; tag_page_example()?; hierarchical_tags_example()?; tag_cloud_example()?; tag_metadata_example()?; tag_filtering_example()?; validation_example()?; println!("\n๐ŸŽ‰ All tags examples completed successfully!"); Ok(()) } /// Demonstrates basic tag generation. fn basic_tags_example() -> Result<(), Box> { println!("๐Ÿฆ€ Basic Tags Example"); println!("---------------------------------------------"); let file = FileData::new( "post.md".to_string(), "A post about Rust and web development".to_string(), ); let mut metadata = HashMap::new(); let _ = metadata.insert("tags".to_string(), "rust, web".to_string()); let _ = metadata .insert("title".to_string(), "Learning Rust".to_string()); let _ = metadata.insert("date".to_string(), "2024-02-20".to_string()); let tags = generate_tags(&file, &metadata); match TagsData::new( "2024-02-20".to_string(), "Learning Rust".to_string(), "A post about Rust".to_string(), "/blog/learning-rust".to_string(), "rust, web".to_string(), ) .validate() { Ok(_) => { println!(" โœ… Generated tags:"); for (tag, pages) in &tags { println!(" ๐Ÿท๏ธ {}: {} pages", tag, pages.len()); } } Err(e) => println!(" โŒ Validation error: {:?}", e), } Ok(()) } /// Demonstrates handling multiple tags per content. fn multiple_tags_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Multiple Tags Example"); println!("---------------------------------------------"); let posts = vec![ ( "Rust Web Development", "rust, web, programming", "/blog/rust-web", ), ( "Advanced Rust Tips", "rust, advanced, tips", "/blog/rust-tips", ), ( "Web Security", "web, security, best-practices", "/blog/web-security", ), ]; let mut global_tags_data: HashMap> = HashMap::new(); for (title, tags, permalink) in posts { let mut metadata = HashMap::new(); let _ = metadata.insert("title".to_string(), title.to_string()); let _ = metadata.insert("tags".to_string(), tags.to_string()); let _ = metadata .insert("permalink".to_string(), permalink.to_string()); let page_data = PageData::new( title.to_string(), "Description".to_string(), "2024-02-20".to_string(), permalink.to_string(), ); for tag in tags.split(", ") { global_tags_data .entry(tag.to_string()) .or_default() .push(page_data.clone()); } } println!(" โœ… Generated tag groupings:"); for (tag, pages) in &global_tags_data { println!(" ๐Ÿท๏ธ {}: {} articles", tag, pages.len()); } Ok(()) } /// Demonstrates tag page generation. fn tag_page_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Tag Page Example"); println!("---------------------------------------------"); let mut tag_pages: HashMap> = HashMap::new(); // Add some sample pages for a tag let _ = tag_pages.insert( "rust".to_string(), vec![ PageData::new( "Rust Basics".to_string(), "Introduction to Rust".to_string(), "2024-02-20".to_string(), "/blog/rust-basics".to_string(), ), PageData::new( "Advanced Rust".to_string(), "Advanced Rust concepts".to_string(), "2024-02-21".to_string(), "/blog/advanced-rust".to_string(), ), ], ); let html_content = generate_tags_html(&tag_pages); println!(" โœ… Generated tag page HTML:"); println!("{}", html_content); Ok(()) } /// Demonstrates hierarchical tag organization. fn hierarchical_tags_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Hierarchical Tags Example"); println!("---------------------------------------------"); let hierarchical_tags = vec![ "programming/rust/basics", "programming/rust/advanced", "programming/web/frontend", "programming/web/backend", ]; for tag_path in hierarchical_tags { let mut metadata = HashMap::new(); let _ = metadata.insert("tags".to_string(), tag_path.to_string()); let tags_data = create_tags_data(&metadata); println!(" โœ… Processed tag path: {}", tag_path); println!(" Keywords: {}", tags_data.keywords); } Ok(()) } /// Demonstrates tag cloud generation. fn tag_cloud_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Tag Cloud Example"); println!("---------------------------------------------"); let mut tag_counts: HashMap = HashMap::new(); // Sample tag frequencies let _ = tag_counts.insert("rust".to_string(), 15); let _ = tag_counts.insert("web".to_string(), 10); let _ = tag_counts.insert("programming".to_string(), 8); let _ = tag_counts.insert("tutorial".to_string(), 5); println!(" โœ… Tag cloud weights:"); for (tag, count) in &tag_counts { let weight = match count { 0..=5 => "small", 6..=10 => "medium", _ => "large", }; println!(" ๐Ÿท๏ธ {} ({}): {}", tag, count, weight); } Ok(()) } /// Demonstrates tag metadata handling. fn tag_metadata_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Tag Metadata Example"); println!("---------------------------------------------"); let tags_data = TagsData::new( "2024-02-20".to_string(), "Programming Topics".to_string(), "Collection of programming articles".to_string(), "/tags".to_string(), "programming, development, tutorials".to_string(), ); match tags_data.validate() { Ok(_) => { println!(" โœ… Tag metadata:"); println!(" ๐Ÿ“… Date: {}", tags_data.dates); println!(" ๐Ÿ“ Title: {}", tags_data.titles); println!(" ๐Ÿ”— Permalink: {}", tags_data.permalinks); println!(" ๐Ÿท๏ธ Keywords: {}", tags_data.keywords); println!( " Keywords list: {:?}", tags_data.keywords_list() ); } Err(e) => println!(" โŒ Validation error: {:?}", e), } Ok(()) } /// Demonstrates tag filtering and sorting. fn tag_filtering_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Tag Filtering Example"); println!("---------------------------------------------"); let mut tag_pages: HashMap> = HashMap::new(); // Add sample pages with dates let rust_pages = vec![ PageData::new( "Recent Rust".to_string(), "Recent post".to_string(), "2024-02-20".to_string(), "/blog/recent".to_string(), ), PageData::new( "Old Rust".to_string(), "Older post".to_string(), "2024-01-01".to_string(), "/blog/old".to_string(), ), ]; let _ = tag_pages.insert("rust".to_string(), rust_pages); println!(" โœ… Filtered and sorted pages:"); for (tag, mut pages) in tag_pages { // Sort pages by date pages.sort_by(|a, b| b.date.cmp(&a.date)); println!(" ๐Ÿท๏ธ {}:", tag); for page in pages { println!(" ๐Ÿ“… {} - {}", page.date, page.title); } } Ok(()) } /// Demonstrates validation of tag data. fn validation_example() -> Result<(), Box> { println!("\n๐Ÿฆ€ Validation Example"); println!("---------------------------------------------"); let test_cases = vec![ ( TagsData::new( "invalid-date".to_string(), "Title".to_string(), "Description".to_string(), "/permalink".to_string(), "tags".to_string(), ), false, "Invalid date format", ), ( TagsData::new( "2024-02-20".to_string(), "".to_string(), "Description".to_string(), "/permalink".to_string(), "tags".to_string(), ), false, "Empty title", ), ( TagsData::new( "2024-02-20".to_string(), "Title".to_string(), "Description".to_string(), "invalid-permalink".to_string(), "tags".to_string(), ), false, "Invalid permalink format", ), ( TagsData::new( "2024-02-20".to_string(), "Valid Title".to_string(), "Valid Description".to_string(), "/valid/permalink".to_string(), "valid, tags".to_string(), ), true, "Valid tag data", ), ]; for (data, should_be_valid, case) in test_cases { match data.validate() { Ok(_) => { if should_be_valid { println!(" โœ… Valid case: {}", case); } else { println!( " โŒ Unexpected validation success: {}", case ); } } Err(e) => { if !should_be_valid { println!( " โœ… Expected validation failure: {}", case ); } else { println!( " โŒ Unexpected validation error for {}: {:?}", case, e ); } } } } Ok(()) }