diff --git a/src/filter/highlight.rs b/src/filter/highlight.rs index fc93d9d..07d84e1 100644 --- a/src/filter/highlight.rs +++ b/src/filter/highlight.rs @@ -19,7 +19,10 @@ pub struct HighlightConfig { #[serde(flatten)] keywords: KeywordsOrPatterns, /// Background color to use for highlighting. Default is yellow. + #[serde(default)] bg_color: Option, + #[serde(default)] + case_sensitive: Option, } #[derive( @@ -55,7 +58,8 @@ impl FeedFilterConfig for HighlightConfig { async fn build(self) -> Result { let patterns = self.keywords.into_patterns()?; let bg_color = self.bg_color.unwrap_or_else(|| "#ffff00".into()); - Highlight::new(&patterns, bg_color) + let case_sensitive = self.case_sensitive.unwrap_or(false); + Highlight::new(&patterns, bg_color, case_sensitive) } } @@ -104,13 +108,18 @@ impl Highlight { fn new>( patterns: &[T], bg_color: String, + case_sensitive: bool, ) -> Result { let regexset = RegexSetBuilder::new(patterns) - .case_insensitive(true) + .case_insensitive(!case_sensitive) .build()?; let patterns = patterns .iter() - .map(|p| RegexBuilder::new(p.as_ref()).case_insensitive(true).build()) + .map(|p| { + RegexBuilder::new(p.as_ref()) + .case_insensitive(!case_sensitive) + .build() + }) .collect::, _>>()?; Ok(Self { @@ -241,7 +250,7 @@ mod test { #[test] fn test_highlighting() { let keywords = vec!["foo", "bar"]; - let highlight = Highlight::new(&keywords, "#ffff00".into()) + let highlight = Highlight::new(&keywords, "#ffff00".into(), false) .expect("failed to build highlighter"); let html = r#"

FOO

foo
bar

@@ -274,6 +283,7 @@ highlight: keywords: vec!["foo".into(), "bar".into()], }, bg_color: Some("#ffff00".into()), + case_sensitive: None, }, ); @@ -289,6 +299,7 @@ highlight: patterns: vec![r"\bfoo\b".into()], }, bg_color: Some("#ffff00".into()), + case_sensitive: None, }, ); } diff --git a/src/filter/sanitize.rs b/src/filter/sanitize.rs index 41165a0..6f46c65 100644 --- a/src/filter/sanitize.rs +++ b/src/filter/sanitize.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use regex::Regex; +use regex::{Regex, RegexBuilder}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -12,9 +12,11 @@ use super::{FeedFilter, FeedFilterConfig, FilterContext}; #[derive( JsonSchema, Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, )] -struct SanitizeOpReplaceConfig { +struct ReplaceConfig { from: String, to: String, + #[serde(default)] + case_sensitive: Option, } #[derive( @@ -26,9 +28,9 @@ pub struct SanitizeOpConfig { /// Remove all matches of the regex remove_regex: Option, /// Replace all occurrences of the string - replace: Option, + replace: Option, /// Replace all matches of the regex - replace_regex: Option, + replace_regex: Option, } impl SanitizeOpConfig { @@ -48,7 +50,16 @@ impl SanitizeOpConfig { macro_rules! parse_regex { ($regex:expr) => { - Regex::new(&$regex).map_err(ConfigError::from)? + RegexBuilder::new(&$regex) + .case_insensitive(true) + .build() + .map_err(ConfigError::from)? + }; + ($regex:expr, $cs:expr) => { + RegexBuilder::new(&$regex) + .case_insensitive($cs.unwrap_or(true)) + .build() + .map_err(ConfigError::from)? }; } @@ -62,13 +73,15 @@ impl SanitizeOpConfig { } if let Some(text) = self.replace { - let from = parse_regex!(regex::escape(&text.from)); + let case_sensitive = text.case_sensitive; + let from = parse_regex!(regex::escape(&text.from), case_sensitive); let to = text.to; return Ok(SanitizeOp::Replace(from, to)); } if let Some(repl) = self.replace_regex { - let from = parse_regex!(repl.from); + let case_sensitive = repl.case_sensitive; + let from = parse_regex!(repl.from, case_sensitive); let to = repl.to; return Ok(SanitizeOp::Replace(from, to)); } @@ -182,9 +195,10 @@ mod test { SanitizeOpConfig { remove: None, remove_regex: None, - replace: Some(SanitizeOpReplaceConfig { + replace: Some(ReplaceConfig { from: "bar".into(), to: "baz".into(), + case_sensitive: None, }), replace_regex: None, }, @@ -192,9 +206,10 @@ mod test { remove: None, remove_regex: None, replace: None, - replace_regex: Some(SanitizeOpReplaceConfig { + replace_regex: Some(ReplaceConfig { from: r"\w+".into(), to: "qux".into(), + case_sensitive: None, }), }, ],