From 8a5ff3b41298ebbdd32ac6e74421704d06864a94 Mon Sep 17 00:00:00 2001
From: vallentin <mail@vallentin.dev>
Date: Thu, 18 Nov 2021 08:10:28 +0100
Subject: Added support for optional escaper for escape filter (resolves #556)

---
 askama_shared/src/filters/mod.rs |  9 ---------
 askama_shared/src/generator.rs   | 38 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 11 deletions(-)

(limited to 'askama_shared')

diff --git a/askama_shared/src/filters/mod.rs b/askama_shared/src/filters/mod.rs
index 8406dee..7009f58 100644
--- a/askama_shared/src/filters/mod.rs
+++ b/askama_shared/src/filters/mod.rs
@@ -106,15 +106,6 @@ where
     Ok(MarkupDisplay::new_unsafe(v, e))
 }
 
-/// Alias for the `escape()` filter
-pub fn e<E, T>(e: E, v: T) -> Result<MarkupDisplay<E, T>>
-where
-    E: Escaper,
-    T: fmt::Display,
-{
-    escape(e, v)
-}
-
 #[cfg(feature = "humansize")]
 /// Returns adequate string representation (in KB, ..) of number of bytes
 pub fn filesizeformat<B: FileSize>(b: &B) -> Result<String> {
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 5c72934..78ada4b 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -1091,7 +1091,10 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
         mut name: &str,
         args: &[Expr<'_>],
     ) -> Result<DisplayWrap, CompileError> {
-        if name == "format" {
+        if matches!(name, "escape" | "e") {
+            self._visit_escape_filter(buf, args)?;
+            return Ok(DisplayWrap::Wrapped);
+        } else if name == "format" {
             self._visit_format_filter(buf, args)?;
             return Ok(DisplayWrap::Unwrapped);
         } else if name == "fmt" {
@@ -1115,7 +1118,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
             return Err("the `yaml` filter requires the `serde-yaml` feature to be enabled".into());
         }
 
-        const FILTERS: [&str; 5] = ["safe", "escape", "e", "json", "yaml"];
+        const FILTERS: [&str; 3] = ["safe", "json", "yaml"];
         if FILTERS.contains(&name) {
             buf.write(&format!(
                 "::askama::filters::{}({}, ",
@@ -1135,6 +1138,37 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
         })
     }
 
+    fn _visit_escape_filter(
+        &mut self,
+        buf: &mut Buffer,
+        args: &[Expr<'_>],
+    ) -> Result<(), CompileError> {
+        if args.len() > 2 {
+            return Err("only two arguments allowed to escape filter".into());
+        }
+        let opt_escaper = match args.get(1) {
+            Some(Expr::StrLit(name)) => Some(*name),
+            Some(_) => return Err("invalid escaper type for escape filter".into()),
+            None => None,
+        };
+        let escaper = match opt_escaper {
+            Some(name) => self
+                .input
+                .config
+                .escapers
+                .iter()
+                .find_map(|(escapers, escaper)| escapers.contains(name).then(|| escaper))
+                .ok_or(CompileError::Static("invalid escaper for escape filter"))?,
+            None => self.input.escaper,
+        };
+        buf.write("::askama::filters::escape(");
+        buf.write(escaper);
+        buf.write(", ");
+        self._visit_args(buf, &args[..1])?;
+        buf.write(")?");
+        Ok(())
+    }
+
     fn _visit_format_filter(
         &mut self,
         buf: &mut Buffer,
-- 
cgit