//! A collection of officially maintained [postprocessors][crate::Postprocessor]. use super::{Context, MarkdownEvents, PostprocessorResult}; use pulldown_cmark::Event; use serde_yaml::Value; /// This postprocessor converts all soft line breaks to hard line breaks. Enabling this mimics /// Obsidian's _'Strict line breaks'_ setting. pub fn softbreaks_to_hardbreaks( _context: &mut Context, events: &mut MarkdownEvents, ) -> PostprocessorResult { for event in events.iter_mut() { if event == &Event::SoftBreak { *event = Event::HardBreak; } } PostprocessorResult::Continue } pub fn filter_by_tags( skip_tags: Vec, only_tags: Vec, ) -> impl Fn(&mut Context, &mut MarkdownEvents) -> PostprocessorResult { move |context: &mut Context, _events: &mut MarkdownEvents| -> PostprocessorResult { match context.frontmatter.get("tags") { None => filter_by_tags_(&[], &skip_tags, &only_tags), Some(Value::Sequence(tags)) => filter_by_tags_(tags, &skip_tags, &only_tags), _ => PostprocessorResult::Continue, } } } fn filter_by_tags_( tags: &[Value], skip_tags: &[String], only_tags: &[String], ) -> PostprocessorResult { let skip = skip_tags .iter() .any(|tag| tags.contains(&Value::String(tag.to_string()))); let include = only_tags.is_empty() || only_tags .iter() .any(|tag| tags.contains(&Value::String(tag.to_string()))); if skip || !include { PostprocessorResult::StopAndSkipNote } else { PostprocessorResult::Continue } } #[test] fn test_filter_tags() { let tags = vec![ Value::String("skip".to_string()), Value::String("publish".to_string()), ]; let empty_tags = vec![]; assert_eq!( filter_by_tags_(&empty_tags, &[], &[]), PostprocessorResult::Continue, "When no exclusion & inclusion are specified, files without tags are included" ); assert_eq!( filter_by_tags_(&tags, &[], &[]), PostprocessorResult::Continue, "When no exclusion & inclusion are specified, files with tags are included" ); assert_eq!( filter_by_tags_(&tags, &["exclude".to_string()], &[]), PostprocessorResult::Continue, "When exclusion tags don't match files with tags are included" ); assert_eq!( filter_by_tags_(&empty_tags, &["exclude".to_string()], &[]), PostprocessorResult::Continue, "When exclusion tags don't match files without tags are included" ); assert_eq!( filter_by_tags_(&tags, &[], &["publish".to_string()]), PostprocessorResult::Continue, "When exclusion tags don't match files with tags are included" ); assert_eq!( filter_by_tags_(&empty_tags, &[], &["include".to_string()]), PostprocessorResult::StopAndSkipNote, "When inclusion tags are specified files without tags are excluded" ); assert_eq!( filter_by_tags_(&tags, &[], &["include".to_string()]), PostprocessorResult::StopAndSkipNote, "When exclusion tags don't match files with tags are exluded" ); assert_eq!( filter_by_tags_(&tags, &["skip".to_string()], &["skip".to_string()]), PostprocessorResult::StopAndSkipNote, "When both inclusion and exclusion tags are the same exclusion wins" ); assert_eq!( filter_by_tags_(&tags, &["skip".to_string()], &["publish".to_string()]), PostprocessorResult::StopAndSkipNote, "When both inclusion and exclusion tags match exclusion wins" ); }