pub mod image;
pub mod text;
pub mod url;
#[derive(Debug, Clone, Default)]
pub struct RecipeComponents {
pub text: String,
pub metadata: String,
pub name: String,
}
pub fn sanitize_name(name: &str) -> String {
name.split_whitespace().collect::<Vec<_>>().join(" ")
}
pub fn metadata_to_yaml(entries: &[(String, String)]) -> String {
use serde_yaml::Value;
let mut mapping = serde_yaml::Mapping::new();
for (key, value) in entries {
if value.starts_with('\n') {
let yaml_str = format!("{}:{}", key, value);
if let Ok(parsed) = serde_yaml::from_str::<serde_yaml::Mapping>(&yaml_str) {
for (k, v) in parsed {
mapping.insert(k, v);
}
continue;
}
}
mapping.insert(Value::String(key.clone()), Value::String(value.clone()));
}
if mapping.is_empty() {
String::new()
} else {
serde_yaml::to_string(&mapping).unwrap_or_default()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_metadata_to_yaml_simple() {
let entries = vec![
("source".to_string(), "http://example.com".to_string()),
("servings".to_string(), "4".to_string()),
];
let yaml = metadata_to_yaml(&entries);
assert!(yaml.contains("source: http://example.com"));
assert!(yaml.contains("servings: '4'"));
}
#[test]
fn test_metadata_to_yaml_with_colon() {
let entries = vec![("description".to_string(), "test : sub".to_string())];
let yaml = metadata_to_yaml(&entries);
assert!(yaml.contains("description: 'test : sub'"));
}
#[test]
fn test_metadata_to_yaml_nested() {
let entries = vec![(
"nutrition".to_string(),
"\n calories: 330 calories\n fat: 18 grams fat".to_string(),
)];
let yaml = metadata_to_yaml(&entries);
assert!(yaml.contains("nutrition:"));
assert!(yaml.contains("calories: 330 calories"));
assert!(yaml.contains("fat: 18 grams fat"));
assert!(!yaml.contains("\""));
}
#[test]
fn test_sanitize_name() {
assert_eq!(sanitize_name("hello world\n test"), "hello world test");
}
}